1 #include "otsdaq-utilities/Visualization/VisualSupervisor.h"
3 #include "otsdaq-core/DataManager/DataManagerSingleton.h"
4 #include "otsdaq-core/Macros/BinaryStringMacros.h"
10 #include <TBufferJSON.h>
13 #include <TDirectory.h>
17 #include <TIterator.h>
23 #include "TBufferFile.h"
29 #include <xdaq/NamespaceURI.h>
33 #define ROOT_BROWSER_PATH getenv("ROOT_BROWSER_PATH")
34 #define ROOT_DISPLAY_CONFIG_PATH getenv("ROOT_DISPLAY_CONFIG_PATH")
36 #define LIVEDQM_DIR std::string("LIVE_DQM")
37 #define PRE_MADE_ROOT_CFG_DIR std::string("Pre-made Views")
39 #define PRE_MADE_ROOT_CFG_FILE_EXT std::string(".rcfg")
41 #define PREFERENCES_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/VisualizerData/"
42 #define PREFERENCES_FILE_EXT ".pref"
44 #define ROOT_VIEWER_PERMISSIONS_THRESHOLD 100
49 #define __MF_SUBJECT__ "Visualizer"
55 : CoreSupervisorBase(stub), theDataManager_(0), loadedRunNumber_(-1)
57 __SUP_COUT__ <<
"Constructor." << __E__;
58 INIT_MF(
"VisualSupervisor");
60 theDataManager_ = DataManagerSingleton::getInstance<VisualDataManager>(
61 theConfigurationManager_->getNode(
62 theConfigurationManager_->__GET_CONFIG__(XDAQContextTable)->getTableName()),
63 CorePropertySupervisorBase::getSupervisorConfigurationPath(),
64 CorePropertySupervisorBase::getSupervisorUID());
66 CoreSupervisorBase::theStateMachineImplementation_.push_back(theDataManager_);
68 __SUP_COUT__ <<
"Done instantiating Visual data manager." << __E__;
73 mkdir(((std::string)PREFERENCES_PATH).c_str(), 0755);
75 __SUP_COUT__ <<
"Constructed." << __E__;
79 VisualSupervisor::~VisualSupervisor(
void)
81 __SUP_COUT__ <<
"Destructor." << __E__;
83 __SUP_COUT__ <<
"Destructed." << __E__;
87 void VisualSupervisor::destroy(
void)
89 __SUP_COUT__ <<
"Destroying..." << __E__;
94 DataManagerSingleton::deleteInstance(
95 CorePropertySupervisorBase::getSupervisorUID());
96 theStateMachineImplementation_.pop_back();
123 void VisualSupervisor::setSupervisorPropertyDefaults()
125 CorePropertySupervisorBase::setSupervisorProperty(
126 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AllowNoLoginRequestTypes,
127 "setUserPreferences | getUserPreferences | getDirectoryContents | getRoot | "
130 CorePropertySupervisorBase::setSupervisorProperty(
131 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
132 "*=1 | rootAdminControls=100");
138 void VisualSupervisor::forceSupervisorPropertyValues()
140 CorePropertySupervisorBase::setSupervisorProperty(
141 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
142 "getRoot | getEvents");
143 CorePropertySupervisorBase::setSupervisorProperty(
144 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NoXmlWhiteSpaceRequestTypes,
145 "getRoot | getEvents");
152 void VisualSupervisor::request(
const std::string& requestType,
154 HttpXmlDocument& xmlOut,
155 const WebUsers::RequestUserInfo& userInfo)
178 if(requestType ==
"getRawData")
180 __SUP_COUT__ << __E__;
184 __SUP_COUT__ <<
"Getting Raw data and converting to binary string" << __E__;
185 xmlOut.addBinaryStringToData(
"rawData", theDataManager_->getRawData());
186 __SUP_COUT__ << __E__;
188 catch(std::exception
const& e)
191 <<
"ERROR! Exception while getting raw data. Incoming exception data..."
193 __SUP_COUT__ << e.what() << __E__;
194 __SUP_COUT__ <<
"End Exception Data" << __E__;
198 __SUP_COUT__ <<
"ERROR! Something went wrong trying to get raw data."
200 __SUP_COUT_INFO__ <<
"ERROR! Something went wrong trying to get raw data."
204 else if(requestType ==
"setUserPreferences" &&
205 userInfo.username_ !=
"" )
207 __SUP_COUT__ <<
"userInfo.username_: " << userInfo.username_ << __E__;
208 std::string fullPath =
209 (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
210 __SUP_COUT__ <<
"fullPath: " << fullPath << __E__;
212 std::string radioSelect = CgiDataUtilities::getData(cgiIn,
"radioSelect");
213 std::string autoRefresh = CgiDataUtilities::getData(cgiIn,
"autoRefresh");
214 std::string autoHide = CgiDataUtilities::getData(cgiIn,
"autoHide");
215 std::string hardRefresh = CgiDataUtilities::getData(cgiIn,
"hardRefresh");
216 std::string autoRefreshPeriod =
217 CgiDataUtilities::getData(cgiIn,
"autoRefreshPeriod");
219 __SUP_COUT__ <<
"radioSelect: " << radioSelect << __E__;
220 __SUP_COUT__ <<
"autoRefresh: " << autoRefresh << __E__;
221 __SUP_COUT__ <<
"autoHide: " << autoHide << __E__;
222 __SUP_COUT__ <<
"hardRefresh: " << hardRefresh << __E__;
223 __SUP_COUT__ <<
"autoRefreshPeriod: " << autoRefreshPeriod << __E__;
226 FILE* fp = fopen(fullPath.c_str(),
"r");
232 fgets(line, 100, fp);
233 sscanf(line,
"%*s %s", val);
234 if(radioSelect ==
"")
237 fgets(line, 100, fp);
238 sscanf(line,
"%*s %s", val);
239 if(autoRefresh ==
"")
242 fgets(line, 100, fp);
243 sscanf(line,
"%*s %s", val);
247 fgets(line, 100, fp);
248 sscanf(line,
"%*s %s", val);
249 if(hardRefresh ==
"")
252 fgets(line, 100, fp);
253 sscanf(line,
"%*s %s", val);
254 if(autoRefreshPeriod ==
"")
255 autoRefreshPeriod = val;
261 fp = fopen(fullPath.c_str(),
"w");
264 fprintf(fp,
"radioSelect %s\n", radioSelect.c_str());
265 fprintf(fp,
"autoRefresh %s\n", autoRefresh.c_str());
266 fprintf(fp,
"autoHide %s\n", autoHide.c_str());
267 fprintf(fp,
"hardRefresh %s\n", hardRefresh.c_str());
268 fprintf(fp,
"autoRefreshPeriod %s\n", autoRefreshPeriod.c_str());
272 __SUP_COUT_ERR__ <<
"Failure writing preferences to file: " << fullPath
275 else if(requestType ==
"getUserPreferences")
277 __SUP_COUT__ <<
"userInfo.username_: " << userInfo.username_ << __E__;
278 std::string fullPath =
279 (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
280 __SUP_COUT__ <<
"fullPath: " << fullPath << __E__;
282 FILE* fp = fopen(fullPath.c_str(),
"r");
289 fgets(line, 100, fp);
290 sscanf(line,
"%*s %d", &val);
291 if(val < 0 || val > 3)
293 xmlOut.addTextElementToData(
"radioSelect", std::to_string(val));
294 fgets(line, 100, fp);
295 sscanf(line,
"%*s %d", &val);
296 xmlOut.addTextElementToData(
"autoRefresh", std::to_string(val));
297 fgets(line, 100, fp);
298 sscanf(line,
"%*s %d", &val);
299 xmlOut.addTextElementToData(
"autoHide", std::to_string(val));
300 fgets(line, 100, fp);
301 sscanf(line,
"%*s %d", &val);
302 xmlOut.addTextElementToData(
"hardRefresh", std::to_string(val));
303 fgets(line, 100, fp);
304 sscanf(line,
"%*s %d", &val);
305 xmlOut.addTextElementToData(
"autoRefreshPeriod", std::to_string(val));
311 xmlOut.addTextElementToData(
"radioSelect",
"");
312 xmlOut.addTextElementToData(
"autoRefresh",
"");
313 xmlOut.addTextElementToData(
"autoHide",
"");
314 xmlOut.addTextElementToData(
"hardRefresh",
"");
315 xmlOut.addTextElementToData(
"autoRefreshPeriod",
"");
318 else if(requestType ==
"getDirectoryContents")
322 std::string rootpath = std::string(ROOT_BROWSER_PATH) +
"/";
323 std::string path = CgiDataUtilities::postData(cgiIn,
"Path");
324 __SUP_COUT__ << path << __E__;
330 userInfo.permissionLevel_ >=
331 CoreSupervisorBase::getSupervisorPropertyUserPermissionsThreshold(
332 "rootAdminControls"));
333 xmlOut.addTextElementToData(
"permissions", permStr);
335 std::string dirpath = rootpath + path;
336 if(path ==
"/" + PRE_MADE_ROOT_CFG_DIR +
"/")
337 dirpath = ROOT_DISPLAY_CONFIG_PATH;
339 if(path.find(
"/" + PRE_MADE_ROOT_CFG_DIR +
"/") ==
341 dirpath = std::string(ROOT_DISPLAY_CONFIG_PATH) +
"/" +
342 path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
344 __SUP_COUT__ <<
"full path: " << dirpath << __E__;
347 struct dirent* entry;
350 if((pDIR = opendir(dirpath.c_str())))
352 xmlOut.addTextElementToData(
"path", path);
359 if(theDataManager_->getLiveDQMHistos() != 0)
360 xmlOut.addTextElementToData(
"dir",
361 LIVEDQM_DIR +
".root");
364 DIR* pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH);
365 bool recheck =
false;
369 if(mkdir(ROOT_DISPLAY_CONFIG_PATH,
370 S_IRWXU | (S_IRGRP | S_IXGRP) |
371 (S_IROTH | S_IXOTH)))
372 __SUP_COUT__ <<
"Failed to make directory for pre made views: "
373 << ROOT_DISPLAY_CONFIG_PATH << __E__;
378 if(!recheck || (pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH)))
380 xmlOut.addTextElementToData(
"dir",
381 PRE_MADE_ROOT_CFG_DIR);
387 while((entry = readdir(pDIR)))
391 if(entry->d_name[0] !=
'.' &&
394 entry->d_type == 4 ||
400 std::string(entry->d_name).find(
".rcfg") == std::string::npos;
403 if(entry->d_type == 0)
406 DIR* pTmpDIR = opendir((dirpath + entry->d_name).c_str());
415 if((entry->d_type == 8 ||
416 (!isDir && entry->d_type == 0))
417 && std::string(entry->d_name).find(
".root") == std::string::npos &&
420 else if(entry->d_type == 4)
423 xmlOut.addTextElementToData(
424 isDir ?
"dir" : (isNotRtCfg ?
"dir" :
"file"), entry->d_name);
430 __SUP_COUT__ <<
"Failed to access directory contents!" << __E__;
432 else if(requestType ==
"getRoot")
436 std::string path = CgiDataUtilities::postData(cgiIn,
"RootPath");
437 std::string fullPath = std::string(getenv(
"ROOT_BROWSER_PATH")) + path;
441 std::string rootFileName = fullPath.substr(0, fullPath.find(
".root") + 5);
442 std::string rootDirectoryName =
444 fullPath.substr(fullPath.find(
".root") + 5,
445 fullPath.size() - fullPath.find(
".root") + 5 + 1);
447 std::string::size_type LDQM_pos = path.find(
"/" + LIVEDQM_DIR +
".root/");
450 if(theDataManager_->getLiveDQMHistos() !=
nullptr && LDQM_pos == 0)
453 rootFile = theDataManager_->getLiveDQMHistos()->getFile();
455 __SUP_COUT__ <<
"File was closed." << __E__;
459 rootDirectoryName = path.substr((
"/" + LIVEDQM_DIR +
".root").length());
463 rootFile = TFile::Open(rootFileName.c_str());
468 if(!rootFile || !rootFile->IsOpen())
470 __SUP_COUT__ <<
"Failed to access root file: " << rootFileName << __E__;
474 xmlOut.addTextElementToData(
"path", path);
476 TDirectory* directory;
477 if((directory = rootFile->GetDirectory(rootDirectoryName.c_str())) == 0)
480 directory = rootFile;
485 TObject* histoClone =
nullptr;
486 TObject* histo = (TObject*)rootFile->Get(rootDirectoryName.c_str());
491 histoClone = histo->Clone();
492 TString json = TBufferJSON::ConvertToJSON(histoClone);
493 TBufferFile tBuffer(TBuffer::kWrite);
494 histoClone->Streamer(tBuffer);
498 std::string destination = BinaryStringMacros::binaryToHexString(
499 tBuffer.Buffer(), tBuffer.Length());
501 xmlOut.addTextElementToData(
"rootType", histoClone->ClassName());
502 xmlOut.addTextElementToData(
"rootData", destination);
503 xmlOut.addTextElementToData(
"rootJSON", json.Data());
507 __SUP_COUT_ERR__ <<
"Failed to access:-" << rootDirectoryName <<
"-"
512 __SUP_COUT__ <<
"directory found getting the content!" << __E__;
513 TRegexp re(
"*", kTRUE);
517 TIter nextobj(directory->GetList());
518 while((obj = (TObject*)nextobj()))
520 TString s = obj->GetName();
521 if(s.Index(re) == kNPOS)
523 __SUP_COUT__ <<
"Class Name: " << obj->IsA()->GetName()
525 xmlOut.addTextElementToData(
526 (std::string(obj->IsA()->GetName()).find(
"Directory") !=
536 TIter next(directory->GetListOfKeys());
537 while((key = (TKey*)next()))
539 TString s = key->GetName();
540 if(s.Index(re) == kNPOS)
542 __SUP_COUT__ <<
"Class Name: " << key->GetClassName()
544 xmlOut.addTextElementToData(
545 (std::string(key->GetClassName()).find(
"Directory") !=
553 if(LDQM_pos == std::string::npos)
557 else if(requestType ==
"getEvents")
559 int Run = atoi(cgiIn(
"run").c_str());
561 __SUP_COUT__ <<
"getEvents for run " << Run << __E__;
563 if(Run != (
int)loadedRunNumber_ || loadedRunNumber_ == (
unsigned int)-1)
565 theDataManager_->load(
"Run1684.root",
"Monicelli");
566 loadedRunNumber_ = Run;
569 DOMElement* eventsParent = xmlOut.addTextElementToData(
"events",
"");
570 DOMElement* eventParent;
612 __SUP_COUT__ <<
"Done hits xml" << __E__;
614 else if(requestType ==
"getGeometry")
616 __SUP_COUT__ <<
"getGeometry" << __E__;
619 theDataManager_->load(
"Run1684.geo",
"Geometry");
621 __SUP_COUT__ <<
"getGeometry" << __E__;
623 DOMElement* geometryParent = xmlOut.addTextElementToData(
"geometry",
"");
654 else if(requestType ==
"getRootConfig")
656 std::string path = CgiDataUtilities::postData(cgiIn,
"RootConfigPath");
657 __SUP_COUT__ <<
"path " << path << __E__;
659 if(path.find(
"/" + PRE_MADE_ROOT_CFG_DIR +
"/") ==
662 path = std::string(ROOT_DISPLAY_CONFIG_PATH) +
"/" +
663 path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
664 __SUP_COUT__ <<
"mod path " << path << __E__;
667 HttpXmlDocument cfgXml;
668 if(cfgXml.loadXmlDocument(path))
670 xmlOut.addTextElementToData(
"status",
"1");
671 xmlOut.copyDataChildren(cfgXml);
672 cfgXml.saveXmlDocument(path);
675 xmlOut.addTextElementToData(
"status",
676 "Failed. File to properly load config file.");
678 else if(requestType ==
"rootAdminControls")
690 std::string cmd = cgiIn(
"cmd");
695 std::string path = CgiDataUtilities::postData(cgiIn,
"path");
696 std::string name = CgiDataUtilities::postData(cgiIn,
"name");
697 __SUP_COUT__ <<
"cmd " << cmd << __E__;
698 __SUP_COUT__ <<
"path " << path << __E__;
699 __SUP_COUT__ <<
"name " << name << __E__;
701 if(path.find(
"/" + PRE_MADE_ROOT_CFG_DIR +
"/") ==
704 path = std::string(ROOT_DISPLAY_CONFIG_PATH) +
"/" +
705 path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2) + name;
706 __SUP_COUT__ <<
"mod path " << path << __E__;
710 if(mkdir(path.c_str(),
711 S_IRWXU | (S_IRGRP | S_IXGRP) |
712 (S_IROTH | S_IXOTH)))
713 xmlOut.addTextElementToData(
"status",
714 "Failed. Directory create rejected.");
716 xmlOut.addTextElementToData(
"status",
"1");
718 else if(cmd ==
"save")
720 path += PRE_MADE_ROOT_CFG_FILE_EXT;
722 bool useRunWildCard =
723 atoi(CgiDataUtilities::postData(cgiIn,
"useRunWildCard")
725 std::string config = CgiDataUtilities::postData(cgiIn,
"config");
726 __SUP_COUT__ <<
"config " << config << __E__;
727 __SUP_COUT__ <<
"useRunWildCard " << useRunWildCard << __E__;
730 FILE* fp = fopen(path.c_str(),
"r");
734 xmlOut.addTextElementToData(
"status",
"Failed. File already exists.");
735 __SUP_COUT__ <<
" Failed. File already exists." << __E__;
744 fp = fopen(path.c_str(),
"w");
745 fputs(config.c_str(), fp);
749 HttpXmlDocument cfgXml;
750 if(cfgXml.loadXmlDocument(path))
753 cfgXml.saveXmlDocument(path);
754 xmlOut.addTextElementToData(
"status",
"1");
758 xmlOut.addTextElementToData(
759 "status",
"Failed. Fatal. Improper file format.");
760 if(
remove(path.c_str()) != 0)
761 __SUP_COUT__ <<
"Failed. Could not remove poorly formed Root "
767 else if(cmd ==
"delete")
770 if(rmdir(path.c_str()) == 0 ||
771 remove((path + PRE_MADE_ROOT_CFG_FILE_EXT).c_str()) == 0)
772 xmlOut.addTextElementToData(
"status",
"1");
774 xmlOut.addTextElementToData(
"status",
775 "Failed. Target could not be deleted.");
778 xmlOut.addTextElementToData(
"status",
"Failed. Unrecognized command.");
781 xmlOut.addTextElementToData(
"status",
"Failed. Invalid path.");
786 __SUP_COUT__ <<
"requestType request, " << requestType <<
", not recognized."