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 __ENV__("ROOT_BROWSER_PATH")
34 #define ROOT_DISPLAY_CONFIG_PATH __ENV__("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(__ENV__("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(CorePropertySupervisorBase::getSupervisorUID());
95 theStateMachineImplementation_.pop_back();
122 void VisualSupervisor::setSupervisorPropertyDefaults()
124 CorePropertySupervisorBase::setSupervisorProperty(
125 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AllowNoLoginRequestTypes,
126 "setUserPreferences | getUserPreferences | getDirectoryContents | getRoot | "
129 CorePropertySupervisorBase::setSupervisorProperty(
130 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
131 "*=1 | rootAdminControls=100");
137 void VisualSupervisor::forceSupervisorPropertyValues()
139 CorePropertySupervisorBase::setSupervisorProperty(
140 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
141 "getRoot | getEvents");
142 CorePropertySupervisorBase::setSupervisorProperty(
143 CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NoXmlWhiteSpaceRequestTypes,
144 "getRoot | getEvents");
151 void VisualSupervisor::request(
const std::string& requestType,
153 HttpXmlDocument& xmlOut,
154 const WebUsers::RequestUserInfo& userInfo)
177 if(requestType ==
"getRawData")
179 __SUP_COUT__ << __E__;
183 __SUP_COUT__ <<
"Getting Raw data and converting to binary string" << __E__;
184 xmlOut.addBinaryStringToData(
"rawData", theDataManager_->getRawData());
185 __SUP_COUT__ << __E__;
187 catch(std::exception
const& e)
190 <<
"ERROR! Exception while getting raw data. Incoming exception data..."
192 __SUP_COUT__ << e.what() << __E__;
193 __SUP_COUT__ <<
"End Exception Data" << __E__;
197 __SUP_COUT__ <<
"ERROR! Something went wrong trying to get raw data."
199 __SUP_COUT_INFO__ <<
"ERROR! Something went wrong trying to get raw data."
203 else if(requestType ==
"setUserPreferences" &&
204 userInfo.username_ !=
"" )
206 __SUP_COUT__ <<
"userInfo.username_: " << userInfo.username_ << __E__;
207 std::string fullPath =
208 (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
209 __SUP_COUT__ <<
"fullPath: " << fullPath << __E__;
211 std::string radioSelect = CgiDataUtilities::getData(cgiIn,
"radioSelect");
212 std::string autoRefresh = CgiDataUtilities::getData(cgiIn,
"autoRefresh");
213 std::string autoHide = CgiDataUtilities::getData(cgiIn,
"autoHide");
214 std::string hardRefresh = CgiDataUtilities::getData(cgiIn,
"hardRefresh");
215 std::string autoRefreshPeriod =
216 CgiDataUtilities::getData(cgiIn,
"autoRefreshPeriod");
218 __SUP_COUT__ <<
"radioSelect: " << radioSelect << __E__;
219 __SUP_COUT__ <<
"autoRefresh: " << autoRefresh << __E__;
220 __SUP_COUT__ <<
"autoHide: " << autoHide << __E__;
221 __SUP_COUT__ <<
"hardRefresh: " << hardRefresh << __E__;
222 __SUP_COUT__ <<
"autoRefreshPeriod: " << autoRefreshPeriod << __E__;
225 FILE* fp = fopen(fullPath.c_str(),
"r");
231 fgets(line, 100, fp);
232 sscanf(line,
"%*s %s", val);
233 if(radioSelect ==
"")
236 fgets(line, 100, fp);
237 sscanf(line,
"%*s %s", val);
238 if(autoRefresh ==
"")
241 fgets(line, 100, fp);
242 sscanf(line,
"%*s %s", val);
246 fgets(line, 100, fp);
247 sscanf(line,
"%*s %s", val);
248 if(hardRefresh ==
"")
251 fgets(line, 100, fp);
252 sscanf(line,
"%*s %s", val);
253 if(autoRefreshPeriod ==
"")
254 autoRefreshPeriod = val;
260 fp = fopen(fullPath.c_str(),
"w");
263 fprintf(fp,
"radioSelect %s\n", radioSelect.c_str());
264 fprintf(fp,
"autoRefresh %s\n", autoRefresh.c_str());
265 fprintf(fp,
"autoHide %s\n", autoHide.c_str());
266 fprintf(fp,
"hardRefresh %s\n", hardRefresh.c_str());
267 fprintf(fp,
"autoRefreshPeriod %s\n", autoRefreshPeriod.c_str());
271 __SUP_COUT_ERR__ <<
"Failure writing preferences to file: " << fullPath
274 else if(requestType ==
"getUserPreferences")
276 __SUP_COUT__ <<
"userInfo.username_: " << userInfo.username_ << __E__;
277 std::string fullPath =
278 (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
279 __SUP_COUT__ <<
"fullPath: " << fullPath << __E__;
281 FILE* fp = fopen(fullPath.c_str(),
"r");
288 fgets(line, 100, fp);
289 sscanf(line,
"%*s %d", &val);
290 if(val < 0 || val > 3)
292 xmlOut.addTextElementToData(
"radioSelect", std::to_string(val));
293 fgets(line, 100, fp);
294 sscanf(line,
"%*s %d", &val);
295 xmlOut.addTextElementToData(
"autoRefresh", std::to_string(val));
296 fgets(line, 100, fp);
297 sscanf(line,
"%*s %d", &val);
298 xmlOut.addTextElementToData(
"autoHide", std::to_string(val));
299 fgets(line, 100, fp);
300 sscanf(line,
"%*s %d", &val);
301 xmlOut.addTextElementToData(
"hardRefresh", std::to_string(val));
302 fgets(line, 100, fp);
303 sscanf(line,
"%*s %d", &val);
304 xmlOut.addTextElementToData(
"autoRefreshPeriod", std::to_string(val));
310 xmlOut.addTextElementToData(
"radioSelect",
"");
311 xmlOut.addTextElementToData(
"autoRefresh",
"");
312 xmlOut.addTextElementToData(
"autoHide",
"");
313 xmlOut.addTextElementToData(
"hardRefresh",
"");
314 xmlOut.addTextElementToData(
"autoRefreshPeriod",
"");
317 else if(requestType ==
"getDirectoryContents")
321 std::string rootpath = std::string(ROOT_BROWSER_PATH) +
"/";
322 std::string path = CgiDataUtilities::postData(cgiIn,
"Path");
323 __SUP_COUT__ << path << __E__;
329 userInfo.permissionLevel_ >=
330 CoreSupervisorBase::getSupervisorPropertyUserPermissionsThreshold(
331 "rootAdminControls"));
332 xmlOut.addTextElementToData(
"permissions", permStr);
334 std::string dirpath = rootpath + path;
335 if(path ==
"/" + PRE_MADE_ROOT_CFG_DIR +
"/")
336 dirpath = ROOT_DISPLAY_CONFIG_PATH;
338 if(path.find(
"/" + PRE_MADE_ROOT_CFG_DIR +
"/") ==
340 dirpath = std::string(ROOT_DISPLAY_CONFIG_PATH) +
"/" +
341 path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
343 __SUP_COUT__ <<
"full path: " << dirpath << __E__;
346 struct dirent* entry;
349 if((pDIR = opendir(dirpath.c_str())))
351 xmlOut.addTextElementToData(
"path", path);
358 if(theDataManager_->getLiveDQMHistos() != 0)
359 xmlOut.addTextElementToData(
"dir",
360 LIVEDQM_DIR +
".root");
363 DIR* pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH);
364 bool recheck =
false;
368 if(mkdir(ROOT_DISPLAY_CONFIG_PATH,
369 S_IRWXU | (S_IRGRP | S_IXGRP) |
370 (S_IROTH | S_IXOTH)))
371 __SUP_COUT__ <<
"Failed to make directory for pre made views: "
372 << ROOT_DISPLAY_CONFIG_PATH << __E__;
377 if(!recheck || (pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH)))
379 xmlOut.addTextElementToData(
"dir",
380 PRE_MADE_ROOT_CFG_DIR);
386 while((entry = readdir(pDIR)))
390 if(entry->d_name[0] !=
'.' &&
393 entry->d_type == 4 ||
399 std::string(entry->d_name).find(
".rcfg") == std::string::npos;
402 if(entry->d_type == 0)
405 DIR* pTmpDIR = opendir((dirpath + entry->d_name).c_str());
414 if((entry->d_type == 8 ||
415 (!isDir && entry->d_type == 0))
416 && std::string(entry->d_name).find(
".root") == std::string::npos &&
419 else if(entry->d_type == 4)
422 xmlOut.addTextElementToData(
423 isDir ?
"dir" : (isNotRtCfg ?
"dir" :
"file"), entry->d_name);
429 __SUP_COUT__ <<
"Failed to access directory contents!" << __E__;
431 else if(requestType ==
"getRoot")
435 std::string path = CgiDataUtilities::postData(cgiIn,
"RootPath");
436 std::string fullPath = std::string(__ENV__(
"ROOT_BROWSER_PATH")) + path;
440 std::string rootFileName = fullPath.substr(0, fullPath.find(
".root") + 5);
441 std::string rootDirectoryName =
443 fullPath.substr(fullPath.find(
".root") + 5,
444 fullPath.size() - fullPath.find(
".root") + 5 + 1);
446 std::string::size_type LDQM_pos = path.find(
"/" + LIVEDQM_DIR +
".root/");
449 if(theDataManager_->getLiveDQMHistos() !=
nullptr && LDQM_pos == 0)
452 rootFile = theDataManager_->getLiveDQMHistos()->getFile();
454 __SUP_COUT__ <<
"File was closed." << __E__;
458 rootDirectoryName = path.substr((
"/" + LIVEDQM_DIR +
".root").length());
462 rootFile = TFile::Open(rootFileName.c_str());
467 if(!rootFile || !rootFile->IsOpen())
469 __SUP_COUT__ <<
"Failed to access root file: " << rootFileName << __E__;
473 xmlOut.addTextElementToData(
"path", path);
475 TDirectory* directory;
476 if((directory = rootFile->GetDirectory(rootDirectoryName.c_str())) == 0)
479 directory = rootFile;
484 TObject* histoClone =
nullptr;
485 TObject* histo = (TObject*)rootFile->Get(rootDirectoryName.c_str());
490 histoClone = histo->Clone();
491 TString json = TBufferJSON::ConvertToJSON(histoClone);
492 TBufferFile tBuffer(TBuffer::kWrite);
493 histoClone->Streamer(tBuffer);
497 std::string destination = BinaryStringMacros::binaryToHexString(
498 tBuffer.Buffer(), tBuffer.Length());
500 xmlOut.addTextElementToData(
"rootType", histoClone->ClassName());
501 xmlOut.addTextElementToData(
"rootData", destination);
502 xmlOut.addTextElementToData(
"rootJSON", json.Data());
506 __SUP_COUT_ERR__ <<
"Failed to access:-" << rootDirectoryName <<
"-"
511 __SUP_COUT__ <<
"directory found getting the content!" << __E__;
512 TRegexp re(
"*", kTRUE);
516 TIter nextobj(directory->GetList());
517 while((obj = (TObject*)nextobj()))
519 TString s = obj->GetName();
520 if(s.Index(re) == kNPOS)
522 __SUP_COUT__ <<
"Class Name: " << obj->IsA()->GetName() << __E__;
523 xmlOut.addTextElementToData(
524 (std::string(obj->IsA()->GetName()).find(
"Directory") !=
534 TIter next(directory->GetListOfKeys());
535 while((key = (TKey*)next()))
537 TString s = key->GetName();
538 if(s.Index(re) == kNPOS)
540 __SUP_COUT__ <<
"Class Name: " << key->GetClassName() << __E__;
541 xmlOut.addTextElementToData(
542 (std::string(key->GetClassName()).find(
"Directory") !=
550 if(LDQM_pos == std::string::npos)
554 else if(requestType ==
"getEvents")
556 int Run = atoi(cgiIn(
"run").c_str());
558 __SUP_COUT__ <<
"getEvents for run " << Run << __E__;
560 if(Run != (
int)loadedRunNumber_ || loadedRunNumber_ == (
unsigned int)-1)
562 theDataManager_->load(
"Run1684.root",
"Monicelli");
563 loadedRunNumber_ = Run;
566 DOMElement* eventsParent = xmlOut.addTextElementToData(
"events",
"");
567 DOMElement* eventParent;
609 __SUP_COUT__ <<
"Done hits xml" << __E__;
611 else if(requestType ==
"getGeometry")
613 __SUP_COUT__ <<
"getGeometry" << __E__;
616 theDataManager_->load(
"Run1684.geo",
"Geometry");
618 __SUP_COUT__ <<
"getGeometry" << __E__;
620 DOMElement* geometryParent = xmlOut.addTextElementToData(
"geometry",
"");
651 else if(requestType ==
"getRootConfig")
653 std::string path = CgiDataUtilities::postData(cgiIn,
"RootConfigPath");
654 __SUP_COUT__ <<
"path " << path << __E__;
656 if(path.find(
"/" + PRE_MADE_ROOT_CFG_DIR +
"/") ==
659 path = std::string(ROOT_DISPLAY_CONFIG_PATH) +
"/" +
660 path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
661 __SUP_COUT__ <<
"mod path " << path << __E__;
664 HttpXmlDocument cfgXml;
665 if(cfgXml.loadXmlDocument(path))
667 xmlOut.addTextElementToData(
"status",
"1");
668 xmlOut.copyDataChildren(cfgXml);
669 cfgXml.saveXmlDocument(path);
672 xmlOut.addTextElementToData(
"status",
673 "Failed. File to properly load config file.");
675 else if(requestType ==
"rootAdminControls")
687 std::string cmd = cgiIn(
"cmd");
692 std::string path = CgiDataUtilities::postData(cgiIn,
"path");
693 std::string name = CgiDataUtilities::postData(cgiIn,
"name");
694 __SUP_COUT__ <<
"cmd " << cmd << __E__;
695 __SUP_COUT__ <<
"path " << path << __E__;
696 __SUP_COUT__ <<
"name " << name << __E__;
698 if(path.find(
"/" + PRE_MADE_ROOT_CFG_DIR +
"/") ==
701 path = std::string(ROOT_DISPLAY_CONFIG_PATH) +
"/" +
702 path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2) + name;
703 __SUP_COUT__ <<
"mod path " << path << __E__;
707 if(mkdir(path.c_str(),
708 S_IRWXU | (S_IRGRP | S_IXGRP) |
709 (S_IROTH | S_IXOTH)))
710 xmlOut.addTextElementToData(
"status",
711 "Failed. Directory create rejected.");
713 xmlOut.addTextElementToData(
"status",
"1");
715 else if(cmd ==
"save")
717 path += PRE_MADE_ROOT_CFG_FILE_EXT;
719 bool useRunWildCard =
720 atoi(CgiDataUtilities::postData(cgiIn,
"useRunWildCard")
722 std::string config = CgiDataUtilities::postData(cgiIn,
"config");
723 __SUP_COUT__ <<
"config " << config << __E__;
724 __SUP_COUT__ <<
"useRunWildCard " << useRunWildCard << __E__;
727 FILE* fp = fopen(path.c_str(),
"r");
731 xmlOut.addTextElementToData(
"status",
"Failed. File already exists.");
732 __SUP_COUT__ <<
" Failed. File already exists." << __E__;
741 fp = fopen(path.c_str(),
"w");
742 fputs(config.c_str(), fp);
746 HttpXmlDocument cfgXml;
747 if(cfgXml.loadXmlDocument(path))
750 cfgXml.saveXmlDocument(path);
751 xmlOut.addTextElementToData(
"status",
"1");
755 xmlOut.addTextElementToData(
756 "status",
"Failed. Fatal. Improper file format.");
757 if(
remove(path.c_str()) != 0)
758 __SUP_COUT__ <<
"Failed. Could not remove poorly formed Root "
764 else if(cmd ==
"delete")
767 if(rmdir(path.c_str()) == 0 ||
768 remove((path + PRE_MADE_ROOT_CFG_FILE_EXT).c_str()) == 0)
769 xmlOut.addTextElementToData(
"status",
"1");
771 xmlOut.addTextElementToData(
"status",
772 "Failed. Target could not be deleted.");
775 xmlOut.addTextElementToData(
"status",
"Failed. Unrecognized command.");
778 xmlOut.addTextElementToData(
"status",
"Failed. Invalid path.");
783 __SUP_COUT__ <<
"requestType request, " << requestType <<
", not recognized."