otsdaq-utilities  3.09.00
VisualSupervisor.cc
1 #include "otsdaq-utilities/Visualization/VisualSupervisor.h"
2 #include "otsdaq/DataManager/DataManagerSingleton.h"
3 #include "otsdaq/Macros/BinaryStringMacros.h"
4 #include "otsdaq/RootUtilities/VisualDataManager.h"
5 #include "otsdaq/XmlUtilities/XmlDocument.h"
6 // #include "otsdaq/otsdaq/Macros/MessageTools.h"
7 #include <boost/regex.hpp>
8 #include "otsdaq/DataManager/DQMHistosConsumerBase.h"
9 #include "otsdaq/Macros/MessageTools.h"
10 #include "otsdaq/RootUtilities/RootFileExplorer.h"
11 
15 #include <TBranchElement.h>
16 #include <TBuffer.h>
17 #include <TBufferJSON.h>
18 #include <TCanvas.h>
19 #include <TClass.h>
20 #include <TDirectory.h>
21 #include <TFile.h>
22 #include <TH1.h>
23 #include <TH2.h>
24 #include <TIterator.h>
25 #include <TKey.h>
26 #include <TProfile.h>
27 #include <TROOT.h>
28 #include <TRegexp.h>
29 #include <TString.h>
30 #include <TTree.h>
31 #include "TBufferFile.h"
32 #include "TObject.h"
33 
34 #include <dirent.h> /*DIR and dirent*/
35 #include <sys/stat.h> /*mkdir*/
36 
37 #include <xdaq/NamespaceURI.h>
38 
39 #include <fstream>
40 #include <iostream>
41 #include <map>
42 #include <mutex>
43 
44 // #include <chrono>
45 // #include <thread>
46 
47 #define ROOT_BROWSER_PATH __ENV__("ROOT_BROWSER_PATH")
48 #define ROOT_DISPLAY_CONFIG_PATH __ENV__("ROOT_DISPLAY_CONFIG_PATH")
49 
50 #define LIVEDQM_DIR std::string("LIVE_DQM")
51 #define PRE_MADE_ROOT_CFG_DIR std::string("Pre-made Views")
52 #define HISTORY_DIR std::string("History")
53 
54 #define PRE_MADE_ROOT_CFG_FILE_EXT std::string(".rcfg")
55 
56 #define PREFERENCES_PATH std::string(__ENV__("SERVICE_DATA_PATH")) + "/VisualizerData/"
57 #define PREFERENCES_FILE_EXT ".pref"
58 
59 #define ROOT_VIEWER_PERMISSIONS_THRESHOLD 100
60 
61 using namespace ots;
62 
63 #undef __MF_SUBJECT__
64 #define __MF_SUBJECT__ "Visualizer"
65 
66 XDAQ_INSTANTIATOR_IMPL(VisualSupervisor)
67 
68 #undef STDLINE
69 #define STDLINE(X, Y) __COUT__ << X
70 
71 //==============================================================================
72 VisualSupervisor::VisualSupervisor(xdaq::ApplicationStub* stub)
73  : CoreSupervisorBase(stub), theDataManager_(nullptr), loadedRunNumber_(-1)
74 {
75  __SUP_COUT__ << "Constructor." << __E__;
76  INIT_MF("VisualSupervisor");
77 
78  mkdir(((std::string)PREFERENCES_PATH).c_str(), 0755);
79  ROOT::EnableThreadSafety();
80 
81  __SUP_COUT__ << "Constructed." << __E__;
82 } // end constructor
83 
84 //========================================================================================================================
85 VisualSupervisor::~VisualSupervisor(void)
86 {
87  __SUP_COUT__ << "Destructor." << __E__;
88  destroy();
89  __SUP_COUT__ << "Destructed." << __E__;
90 } // end destructor
91 
92 //========================================================================================================================
93 void VisualSupervisor::destroy(void)
94 {
95  __SUP_COUT__ << "Destroying..." << __E__;
96 
97  DataManagerSingleton::deleteInstance(CorePropertySupervisorBase::getSupervisorUID());
98  if(theStateMachineImplementation_.size() > 1)
99  {
100  __SS__ << "Not expecting more than one visual data manager!" << __E__;
101  __SS_THROW__;
102  }
103  if(theStateMachineImplementation_.size())
104  theStateMachineImplementation_.pop_back();
105  else
106  __COUT_WARN__ << "No visual data manager was pushed." << __E__;
107 } // end destroy()
108 
109 //==============================================================================
110 void VisualSupervisor::transitionConfiguring(toolbox::Event::Reference /*e*/)
111 try
112 {
113  __SUP_COUT__ << "Configuring..." << __E__;
114 
115  CoreSupervisorBase::configureInit();
116 
117  try
118  {
119  ConfigurationTree testAppLink = theConfigurationManager_->getNode(
120  "/" +
121  theConfigurationManager_->__GET_CONFIG__(XDAQContextTable)->getTableName() +
122  CorePropertySupervisorBase::getSupervisorConfigurationPath());
123  }
124  catch(const std::runtime_error& e)
125  {
126  __SS__ << "The link to the Visual Supervisor configuration seems to be broken. "
127  "Please check this path: "
128  << "/" +
129  theConfigurationManager_->__GET_CONFIG__(XDAQContextTable)
130  ->getTableName() +
131  CorePropertySupervisorBase::getSupervisorConfigurationPath()
132  << __E__ << __E__ << e.what() << __E__;
133  __SS_THROW__;
134  }
135 
136  ConfigurationTree appLink = theConfigurationManager_->getNode(
137  "/" + theConfigurationManager_->__GET_CONFIG__(XDAQContextTable)->getTableName() +
138  CorePropertySupervisorBase::getSupervisorConfigurationPath());
139 
140  __COUTV__(appLink.getValueAsString());
141 
142  if(!appLink.isDisconnected())
143  {
144  theDataManager_ = DataManagerSingleton::getInstance<VisualDataManager>(
145  theConfigurationManager_->getNode(
146  theConfigurationManager_->__GET_CONFIG__(XDAQContextTable)
147  ->getTableName()),
148  CorePropertySupervisorBase::getSupervisorConfigurationPath(),
149  CorePropertySupervisorBase::getSupervisorUID());
150 
151  CoreSupervisorBase::theStateMachineImplementation_.push_back(theDataManager_);
152 
153  __SUP_COUT__ << "Done instantiating Visual data manager." << __E__;
154  }
155  else
156  __SUP_COUT__ << "No Visual Supervisor configuration link, so skipping Visual "
157  "data manager instantiation."
158  << __E__;
159 
160  // just handle FSMs
161  CoreSupervisorBase::transitionConfiguringFSMs();
162 
163  __SUP_COUT__ << "Configured." << __E__;
164 } // end transitionConfiguring()
165 catch(const std::runtime_error& e)
166 {
167  __SS__ << "Error with VisualSupervisor::transitionConfiguring(): " << e.what()
168  << __E__;
169  __COUT_ERR__ << ss.str();
170  // ExceptionHandler(ExceptionHandlerRethrow::no, ss.str());
171 
172  //__SS_THROW_ONLY__;
173  theStateMachine_.setErrorMessage(ss.str());
174  throw toolbox::fsm::exception::Exception(
175  "Transition Error" /*name*/,
176  ss.str() /* message*/,
177  "VisualSupervisor::transitionConfiguring" /*module*/,
178  __LINE__ /*line*/,
179  __FUNCTION__ /*function*/
180  );
181 } // end transitionConfiguring() catch
182 
183 //==============================================================================
184 void VisualSupervisor::transitionHalting(toolbox::Event::Reference e)
185 {
186  __SUP_COUT__ << "Halting..." << __E__;
187 
189  destroy();
190 
191  __SUP_COUT__ << "Halted." << __E__;
192 } // end transitionHalting()
193 
194 //==============================================================================
199 {
200  CorePropertySupervisorBase::setSupervisorProperty(
201  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AllowNoLoginRequestTypes,
202  "setUserPreferences | getUserPreferences | getDirectoryContents | getRoot | "
203  "getEvents");
204 
205  CorePropertySupervisorBase::setSupervisorProperty(
206  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
207  "*=1 | rootAdminControls=100");
208 } //end setSupervisorPropertyDefaults()
209 
210 //========================================================================================================================
214 {
215  CorePropertySupervisorBase::setSupervisorProperty(
216  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
217  "getRoot | getEvents");
218  CorePropertySupervisorBase::setSupervisorProperty(
219  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NoXmlWhiteSpaceRequestTypes,
220  "getRoot | getEvents");
221  //Note: json data in ROOTJS library expects no funny characters
222 } //end forceSupervisorPropertyValues()
223 
224 //========================================================================================================================
225 void VisualSupervisor::request(const std::string& requestType,
226  cgicc::Cgicc& cgiIn,
227  HttpXmlDocument& xmlOut,
228  const WebUsers::RequestUserInfo& userInfo)
229 {
230  // Commands
231  // getRawData
232  // getGeometry
233  // getEvents
234  // getRoot
235  // getDirectoryContents
236  // setUserPreferences
237  // getUserPreference
238 
239  // if (requestType == "getHisto" && theDataManager_->getLiveDQMHistos() != 0)
240  // {
241  // // TH1I* histo =
242  // (TH1I*)theDataManager_->getLiveDQMHistos()->get("Planes/Plane_0_Occupancy");
243  //
244  // // theDataManager_->load("Run185_Histo.root","Histograms");
245  // //TH1F* histo1d = theDataManager_->getFileDQMHistos().getHisto1D();
246  // //TCanvas* canvas = theDataManager_->getFileDQMHistos().getCanvas ();
247  // //TH2F* histo2d = theDataManager_->getFileDQMHistos().getHisto2D();
248  // //TProfile* profile = theDataManager_->getFileDQMHistos().getProfile();
249  //
250  // }
251  // std::stringstream ss;
252  // ss << "Request type: |" << requestType << "|";
253  // STDLINE(ss.str(),"") ;
254 
255  __SUP_COUT__ << "Request type: " << requestType << __E__;
256  if(requestType ==
257  "getRawData") // ################################################################################################################
258  {
259  __SUP_COUT__ << __E__;
260  try
261  {
262  // TODO -- add timestamp, so we know if data is new
263 
264  if(theDataManager_ == nullptr)
265  {
266  __SS__ << "No data manager instantiated." << __E__;
267  __SS_THROW__;
268  }
269  __SUP_COUT__ << "Getting Raw data and converting to binary string" << __E__;
270  // xmlOut.addBinaryStringToData("rawData",
271  // theDataManager_->getRawData());
272  __SUP_COUT__ << __E__;
273  __SUP_SS__ << "Raw data visualizion is deprecated!" << __E__;
274  __SUP_SS_THROW__;
275  }
276  catch(std::exception const& e)
277  {
278  __SUP_COUT__
279  << "ERROR! Exception while getting raw data. Incoming exception data..."
280  << __E__;
281  __SUP_COUT__ << e.what() << __E__;
282  __SUP_COUT__ << "End Exception Data" << __E__;
283  }
284  catch(...)
285  {
286  __SUP_COUT__ << "ERROR! Something went wrong trying to get raw data."
287  << __E__;
288  try
289  {
290  throw;
291  } //one more try to printout extra info
292  catch(const std::exception& e)
293  {
294  __SUP_COUT_ERR__ << "Exception message: " << e.what();
295  }
296  catch(...)
297  {
298  }
299  __SUP_COUT_INFO__ << "ERROR! Something went wrong trying to get raw data."
300  << __E__;
301  }
302  }
303  else if(
304  requestType == "setUserPreferences" &&
305  userInfo.username_ !=
306  "" /*from allow no user*/) // ################################################################################################################
307  {
308  __SUP_COUT__ << "userInfo.username_: " << userInfo.username_ << __E__;
309  std::string fullPath =
310  (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
311  __SUP_COUT__ << "fullPath: " << fullPath << __E__;
312 
313  std::string radioSelect = CgiDataUtilities::getData(cgiIn, "radioSelect");
314  std::string autoRefresh = CgiDataUtilities::getData(cgiIn, "autoRefresh");
315  std::string autoHide = CgiDataUtilities::getData(cgiIn, "autoHide");
316  std::string hardRefresh = CgiDataUtilities::getData(cgiIn, "hardRefresh");
317  std::string autoRefreshPeriod =
318  CgiDataUtilities::getData(cgiIn, "autoRefreshPeriod");
319 
320  __SUP_COUT__ << "radioSelect: " << radioSelect << __E__;
321  __SUP_COUT__ << "autoRefresh: " << autoRefresh << __E__;
322  __SUP_COUT__ << "autoHide: " << autoHide << __E__;
323  __SUP_COUT__ << "hardRefresh: " << hardRefresh << __E__;
324  __SUP_COUT__ << "autoRefreshPeriod: " << autoRefreshPeriod << __E__;
325 
326  // read existing
327  FILE* fp = fopen(fullPath.c_str(), "r");
328  if(fp)
329  {
330  char line[100];
331  char val[100];
332 
333  fgets(line, 100, fp);
334  sscanf(line, "%*s %s", val);
335  if(radioSelect == "")
336  radioSelect = val;
337 
338  fgets(line, 100, fp);
339  sscanf(line, "%*s %s", val);
340  if(autoRefresh == "")
341  autoRefresh = val;
342 
343  fgets(line, 100, fp);
344  sscanf(line, "%*s %s", val);
345  if(autoHide == "")
346  autoHide = val;
347 
348  fgets(line, 100, fp);
349  sscanf(line, "%*s %s", val);
350  if(hardRefresh == "")
351  hardRefresh = val;
352 
353  fgets(line, 100, fp);
354  sscanf(line, "%*s %s", val);
355  if(autoRefreshPeriod == "")
356  autoRefreshPeriod = val;
357 
358  fclose(fp);
359  }
360 
361  // write new
362  fp = fopen(fullPath.c_str(), "w");
363  if(fp)
364  {
365  fprintf(fp, "radioSelect %s\n", radioSelect.c_str());
366  fprintf(fp, "autoRefresh %s\n", autoRefresh.c_str());
367  fprintf(fp, "autoHide %s\n", autoHide.c_str());
368  fprintf(fp, "hardRefresh %s\n", hardRefresh.c_str());
369  fprintf(fp, "autoRefreshPeriod %s\n", autoRefreshPeriod.c_str());
370  fclose(fp);
371  }
372  else
373  __SUP_COUT_ERR__ << "Failure writing preferences to file: " << fullPath
374  << __E__;
375  }
376  else if(
377  requestType ==
378  "getUserPreferences") // ################################################################################################################
379  {
380  __SUP_COUT__ << "Next is userinfo" << __E__;
381  __SUP_COUT__ << "userInfo.username_: " << userInfo.username_ << __E__;
382  std::string fullPath =
383  (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
384  __SUP_COUT__ << "fullPath: " << fullPath << __E__;
385 
386  FILE* fp = fopen(fullPath.c_str(), "r");
387  if(fp)
388  {
389  char line[100];
390  // char val[100];
391  int val;
392 
393  fgets(line, 100, fp);
394  sscanf(line, "%*s %d", &val);
395  if(val < 0 || val > 3)
396  val = 0; // FIXME.. value can get corrupt...
397  xmlOut.addTextElementToData("radioSelect", std::to_string(val));
398  fgets(line, 100, fp);
399  sscanf(line, "%*s %d", &val);
400  xmlOut.addTextElementToData("autoRefresh", std::to_string(val));
401  fgets(line, 100, fp);
402  sscanf(line, "%*s %d", &val);
403  xmlOut.addTextElementToData("autoHide", std::to_string(val));
404  fgets(line, 100, fp);
405  sscanf(line, "%*s %d", &val);
406  xmlOut.addTextElementToData("hardRefresh", std::to_string(val));
407  fgets(line, 100, fp);
408  sscanf(line, "%*s %d", &val);
409  xmlOut.addTextElementToData("autoRefreshPeriod", std::to_string(val));
410  fclose(fp);
411  }
412  else
413  {
414  // else assume user has no preferences yet
415  xmlOut.addTextElementToData("radioSelect", "");
416  xmlOut.addTextElementToData("autoRefresh", "");
417  xmlOut.addTextElementToData("autoHide", "");
418  xmlOut.addTextElementToData("hardRefresh", "");
419  xmlOut.addTextElementToData("autoRefreshPeriod", "");
420  }
421  __SUP_COUT__ << "Done with preferences!" << __E__;
422  }
423  else if(
424  requestType ==
425  "getDirectoryContents") // ################################################################################################################
426  {
427  // return directory structure for requested path, types are "dir" and "file"
428  std::string rootpath =
429  std::string(ROOT_BROWSER_PATH) +
430  "/"; // Base directory where the Visualizer will look for files
431  std::string path = CgiDataUtilities::postData(cgiIn, "Path");
432  boost::regex re("%2F");
433  path = boost::regex_replace(path, re, "/"); // Dario: should be transparent for
434  // Ryan's purposes but required by Extjs
435 
438 
439  // return 1 if user has access to admin controls, else 0
440  char permStr[10];
441  sprintf(permStr,
442  "%d",
443  userInfo.permissionLevel_ >=
445  "rootAdminControls"));
446  xmlOut.addTextElementToData("permissions", permStr); // add permissions
449 
450  std::string dirpath = rootpath + path;
451  // If I am not looking for a file but just for the dir with the premade views
452  if(path == "/" + PRE_MADE_ROOT_CFG_DIR + "/")
453  dirpath = ROOT_DISPLAY_CONFIG_PATH;
454 
455  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
456  0) // ROOT config path must start the path
457  dirpath = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
458  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
459 
460  // If looking for the History virtual dir, remap to ROOT_BROWSER_PATH
461  if(path == "/" + HISTORY_DIR + "/")
462  dirpath = std::string(ROOT_BROWSER_PATH) + "/";
463  else if(path.find("/" + HISTORY_DIR + "/") == 0)
464  dirpath = std::string(ROOT_BROWSER_PATH) + "/" +
465  path.substr(HISTORY_DIR.length() + 2);
466 
468  __SUP_COUT__ << "rootpath:-" << rootpath << "-path:-" << path << "-dirpath:-"
469  << dirpath << "-" << __E__;
470 
471  DIR* pDIR;
472  struct dirent* entry;
473  bool isNotRtCfg;
474  bool isDir;
475  if((pDIR = opendir(dirpath.c_str())))
476  {
477  xmlOut.addTextElementToData("path", path);
478  xmlOut.addTextElementToData("headOfSearch", "located");
479 
480  // add LIVE if path is / and DQM is active
481  // add Pre-made Views if path is / and ROOT_DISPLAY_CONFIG_PATH isnt already
482  // there
483  if(theDataManager_ != nullptr)
484  __COUT__ << "path-" << path << "-DM: " << theDataManager_
485  << " Live: " << theDataManager_->getLiveDQMHistos() << std::endl;
486  if(path == "/")
487  {
488  // Add live histos
489  xmlOut.addTextElementToData("dir",
490  LIVEDQM_DIR + ".root"); // add to xml
491 
492  // check for ROOT_DISPLAY_CONFIG_PATH
493  DIR* pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH);
494  bool recheck = false;
495  if(!pRtDIR) // if doesn't exist, make it
496  {
497  recheck = true;
498  if(mkdir(ROOT_DISPLAY_CONFIG_PATH,
499  S_IRWXU | (S_IRGRP | S_IXGRP) |
500  (S_IROTH | S_IXOTH))) // mode = drwx r-x r-x
501  __SUP_COUT__ << "Failed to make directory for pre made views: "
502  << ROOT_DISPLAY_CONFIG_PATH << __E__;
503  }
504  else
505  closedir(pRtDIR); // else close and display
506 
507  if(!recheck || (pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH)))
508  {
511  xmlOut.addTextElementToData("dir",
512  PRE_MADE_ROOT_CFG_DIR); // add to xml
513  if(recheck)
514  closedir(pRtDIR);
515  }
516 
517  xmlOut.addTextElementToData("dir", HISTORY_DIR); // add to xml
518  }
520  if(path != "/")
521  while((entry = readdir(pDIR)))
522  {
523  //__SUP_COUT__ << int(entry->d_type) << " " << entry->d_name << "\n" <<
524  // __E__;
525  if(entry->d_name[0] != '.' &&
526  (entry->d_type ==
527  0 || // 0 == UNKNOWN (which can happen - seen in SL7 VM)
528  entry->d_type == 4 ||
529  entry->d_type == 8))
530  {
531  //__SUP_COUT__ << int(entry->d_type) << " " << entry->d_name << "\n"
532  //<< __E__;
533  isNotRtCfg =
534  std::string(entry->d_name).find(".rcfg") == std::string::npos;
535  isDir = false;
536 
537  if(entry->d_type == 0)
538  {
539  // unknown type .. determine if directory
541  DIR* pTmpDIR = opendir((dirpath + entry->d_name).c_str());
542  if(pTmpDIR)
543  {
545  isDir = true;
546  closedir(pTmpDIR);
547  }
548  // else //assume file
549  }
550 
551  if((entry->d_type == 8 ||
552  (!isDir && entry->d_type == 0)) // file type
553  && std::string(entry->d_name).find(".root") ==
554  std::string::npos &&
555  isNotRtCfg)
556  continue; // skip if not a root file or a config file
557  else if(entry->d_type == 4)
558  isDir = true; // flag directory types
559 
560  xmlOut.addTextElementToData(
561  isDir ? "dir" : (isNotRtCfg ? "dir" : "file"), entry->d_name);
562  }
563  }
564  closedir(pDIR);
565  }
566  else
567  __SUP_COUT__ << "Failed to access directory contents!" << __E__;
568  // std::ostringstream* out ;
569  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
570  }
571  else if(
572  requestType ==
573  "getRoot") // ################################################################################################################
574  {
575  // return directory structure for requested ROOT path, types are "dir" and "file"
576  std::string path = CgiDataUtilities::postData(cgiIn, "RootPath");
577  __SUP_COUTV__(path);
578 
579  // Strip History virtual directory prefix for file resolution, keep original path for response
580  std::string filePath = path;
581  if(filePath.find("/" + HISTORY_DIR + "/") == 0)
582  filePath = filePath.substr(HISTORY_DIR.length() + 1);
583 
584  unsigned splitter =
585  filePath.find(".root") + 5; // 5 = std::string(".root").size();
586  std::string rootFileName =
587  std::string(__ENV__("ROOT_BROWSER_PATH")) + filePath.substr(0, splitter);
588  __SUP_COUTV__(rootFileName);
589 
590  std::string rootDirectoryName =
591  filePath.substr(splitter, filePath.length() - splitter);
592  __SUP_COUTV__(rootDirectoryName);
593 
594  // std::string fullPathToObject = rootFileName + ":" + rootDirectoryName;
595  // __SUP_COUTV__(fullPathToObject);
596 
597  bool isLiveDQM = (path.find("/" + LIVEDQM_DIR + ".root/") == 0) ? true : false;
598  __SUP_COUTV__(isLiveDQM);
599 
600  TFile* rootFile = nullptr;
601  TObject* tObject = nullptr;
602  TDirectory* tDirectory = nullptr;
603 
604  if(!isLiveDQM) // If it is not from LIVE_DQM
605  {
606  rootFile = TFile::Open(rootFileName.c_str());
607 
608  if(rootFile == nullptr || !rootFile->IsOpen())
609  {
610  __SUP_SS__ << "Failed to access ROOT file: " << rootFileName << __E__;
611  __SUP_SS_THROW__;
612  }
613  // First I check if I can find the object to return directly. If not an object
614  // it is a directory
615  if((tObject = rootFile->Get(rootDirectoryName.c_str())) !=
616  nullptr || //for backwards compatibility
617  (rootDirectoryName.size() &&
618  rootDirectoryName[0] == '/' && //for newer root, remove leading '/'
619  (tObject = rootFile->Get(rootDirectoryName.substr(1).c_str())) !=
620  nullptr))
621  {
622  if(tObject->IsA() == TCanvas::Class())
623  {
624  static_cast<TCanvas*>(tObject)->Modified();
625  static_cast<TCanvas*>(tObject)->Update();
626  }
627  TString json = TBufferJSON::ConvertToJSON(tObject);
628  TBufferFile tBuffer(TBuffer::kWrite);
629  tObject->Streamer(tBuffer);
630  std::string hexString = BinaryStringMacros::binaryStringToHexString(
631  tBuffer.Buffer(), tBuffer.Length());
632 
633  __SUP_COUT__ << "Returning object from file '" << tObject->GetName()
634  << "' of class '" << tObject->ClassName() << __E__;
635 
636  xmlOut.addTextElementToData("path", path);
637  xmlOut.addTextElementToData("rootType", tObject->ClassName());
638  xmlOut.addTextElementToData("rootData", hexString);
639  xmlOut.addTextElementToData("rootJSON", json.Data());
640  }
641  else if((tDirectory = rootFile->GetDirectory(rootDirectoryName.c_str())) !=
642  nullptr)
643  {
644  TKey* key;
645  TIter next(tDirectory->GetListOfKeys());
646  xmlOut.addTextElementToData("path", path);
647  while((key = (TKey*)next()))
648  {
649  TString s = key->GetName();
650  TRegexp re("*", kTRUE);
651  if(s.Index(re) == kNPOS)
652  continue;
653  __SUP_COUT__ << "Class Name: " << key->GetClassName() << __E__;
654  xmlOut.addTextElementToData(
655  (std::string(key->GetClassName()).find("Directory") !=
656  std::string::npos ||
657  std::string(key->GetClassName()) == "TTree" ||
658  std::string(key->GetClassName()).find("TBranch") !=
659  std::string::npos) // == "TBranchElement")
660  ? "dir"
661  : "file",
662  key->GetName());
663 
664  if(TTEST(
665  50)) //enable to view json content of each object in directory
666  {
667  tObject = key->ReadObj();
668  __SUP_COUT__ << "JSON : " << key->GetClassName() << __E__;
669 
670  TString json = TBufferJSON::ConvertToJSON(tObject);
671  TBufferFile tBuffer(TBuffer::kWrite);
672  tObject->Streamer(tBuffer);
673  std::string hexString =
675  tBuffer.Length());
676 
677  __SUP_COUT__ << "Returning directory object from file '"
678  << tObject->GetName() << "' of class '"
679  << tObject->ClassName() << __E__;
680 
681  __SUP_COUTV__(json.Data());
682  }
683  }
684  rootFile->Close();
685  }
686  else
687  __SUP_COUT_ERR__ << "Failed to find object " << rootDirectoryName
688  << " in " << rootFileName << __E__;
689  return;
690  }
691  // LIVE DQM PLOTS
692  else if(theDataManager_ != nullptr && theDataManager_->isReady())
693  {
694  if(theDataManager_ != nullptr)
695  theDataManager_->setDoNotStop(true);
696  else
697  return;
698  __SUP_COUT__ << "Attempting to get LIVE ROOT object." << __E__;
699 
700  std::vector<DQMHistosBase*> dqmConsumers = theDataManager_->getLiveDQMs();
701  tObject = nullptr;
702  for(auto const& consumer : dqmConsumers)
703  {
704  rootFile = consumer->getFile();
705  __SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
706  if(rootFile == nullptr || !rootFile->IsOpen())
707  {
708  __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
709  << __E__;
710  theDataManager_->setDoNotStop(false);
711  return;
712  }
713  // If I find an object then I stream it and return
714  if((tObject = rootFile->Get(rootDirectoryName.c_str())) != nullptr)
715  {
716  __SUP_COUT__ << "Object class name: " << tObject->ClassName()
717  << __E__;
718  std::string tmpClassName = tObject->ClassName();
719  TString json;
720  TBufferFile tBuffer(TBuffer::kWrite);
721  if(tObject->IsA() == TCanvas::Class())
722  {
723  static_cast<TCanvas*>(tObject)->Modified();
724  static_cast<TCanvas*>(tObject)->Update();
725  }
726  { // Only locking when converting the object
727  std::unique_lock<std::mutex> lock(
728  static_cast<DQMHistosConsumerBase*>(consumer)
729  ->getFillHistoMutex());
730  json = TBufferJSON::ConvertToJSON(tObject);
731  tObject->Streamer(tBuffer);
732  }
733  std::string hexString = BinaryStringMacros::binaryStringToHexString(
734  tBuffer.Buffer(), tBuffer.Length());
735 
736  __SUP_COUT__ << "Returning object '" << tObject->GetName()
737  << "' of class '" << tObject->ClassName() << __E__;
738 
739  //__SUP_COUT__ << "Data: " << json.Data() << std::endl;
740  xmlOut.addTextElementToData("path", path);
741  xmlOut.addTextElementToData("rootType", tObject->ClassName());
742  xmlOut.addTextElementToData("rootData", hexString);
743  xmlOut.addTextElementToData("rootJSON", json.Data());
744 
745  theDataManager_->setDoNotStop(false);
746  return;
747  }
748  }
749  // If I didn't find any object in the file, then it must be a directory!
750  std::map<std::string, std::string> dirList;
751 
752  for(auto const& consumer : dqmConsumers)
753  {
754  __SUP_COUT__ << "Attempting to get LIVE ROOT directory." << __E__;
755  rootFile = consumer->getFile();
756  __SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
757  if(rootFile == nullptr || !rootFile->IsOpen())
758  {
759  __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
760  << __E__;
761  xmlOut.addTextElementToData("Warning", ss.str());
762  theDataManager_->setDoNotStop(false);
763  return;
764  }
765  if((tDirectory = rootFile->GetDirectory(rootDirectoryName.c_str())) !=
766  nullptr)
767  {
768  xmlOut.addTextElementToData("path", path);
769  __SUP_COUT__ << "Directory found getting the content!" << __E__;
770  TRegexp re("*", kTRUE);
771  TObject* obj;
772  TIter nextobj(tDirectory->GetList());
773  while((obj = (TObject*)nextobj()))
774  {
775  TString s = obj->GetName();
776  if(s.Index(re) == kNPOS)
777  continue;
778  __SUP_COUT__ << "Class Name: " << obj->IsA()->GetName() << __E__;
779  dirList[obj->GetName()] =
780  (std::string(obj->IsA()->GetName()).find("Directory") !=
781  std::string::npos ||
782  std::string(obj->IsA()->GetName()) == "TTree" ||
783  std::string(obj->IsA()->GetName()).find("TBranch") !=
784  std::string::npos) // == "TBranchElement")
785  ? "dir"
786  : "file";
787  }
788  }
789  }
790  for(auto const& dir : dirList)
791  {
792  xmlOut.addTextElementToData(dir.second, dir.first);
793  __SUP_COUT__ << "Class Name: " << dir.second << " Object: " << dir.first
794  << __E__;
795  }
796  }
797 
798  } // END LORENZO GET ROOT
799  // else if(
800  // requestType ==
801  // "RyangetRoot")
802  // //################################################################################################################
803  // {
804  // // return directory structure for requested ROOT path, types are "dir" and "file"
805  // std::string path = CgiDataUtilities::postData(cgiIn, "RootPath");
806 
807  // //////////////////////////////////////////////////////////////////
808  // // DARIO
809  // //////////////////////////////////////////////////////////////////
810  // ss.str("");
811  // ss << "PID: " << ::getpid();
812  // // STDLINE(ss.str(),ACCyan) ;
813  // boost::regex re1("%2F");
814  // path = boost::regex_replace(
815  // path, re1, "/"); // Dario: should be transparent for Ryan's purposes but
816  // // required by Extjs
817  // boost::regex re2("%20");
818  // path = boost::regex_replace(
819  // path, re2, " "); // Dario: should be transparent for Ryan's purposes but
820  // // required by Extjs
821  // boost::regex re3("%3A");
822  // path =
823  // boost::regex_replace(path, re3, ""); // Dario: should be transparent for
824  // // Ryan's purposes but required by Extjs
825  // ss.str("");
826  // ss << "path : " << path;
827  // // STDLINE(ss.str(),ACCyan) ;
828  // //////////////////////////////////////////////////////////////////
829  // // END DARIO
830  // //////////////////////////////////////////////////////////////////
831 
832  // std::string fullPath = std::string(__ENV__("ROOT_BROWSER_PATH")) + path;
833  // __SUP_COUTV__(fullPath);
834 
835  // const size_t rootExtensionStart = fullPath.find(".root");
836  // const size_t rootExtensionEnd = rootExtensionStart + std::string(".root").size();
837 
838  // std::string rootFileName = fullPath.substr(0, rootExtensionEnd);
839 
840  // __SUP_COUTV__(rootFileName);
841  // std::string fullPathToObject =
842  // rootFileName + ":" +
843  // fullPath.substr(rootExtensionEnd, fullPath.size() - rootExtensionEnd + 1);
844 
845  // __SUP_COUTV__(fullPathToObject);
846  // std::string::size_type LDQM_pos = path.find("/" + LIVEDQM_DIR + ".root/");
847  // __SUP_COUTV__(LDQM_pos);
848 
849  // TFile* rootFile = nullptr;
850  // if(LDQM_pos == std::string::npos) // If it is not from LIVE_DQM
851  // {
852  // __SUP_COUTV__(rootFileName);
853  // rootFile = TFile::Open(rootFileName.c_str());
854 
855  // if(rootFile == nullptr || !rootFile->IsOpen())
856  // {
857  // __SUP_SS__ << "Failed to access ROOT file: " << rootFileName << __E__;
858  // __SUP_SS_THROW__;
859  // }
860  // }
861  // else
862  // {
863  // if(theDataManager_ == nullptr || !theDataManager_->isReady())
864  // return;
865  // theDataManager_->setDoNotStop(true);
866  // if(theDataManager_ != nullptr &&
867  // theDataManager_->getLiveDQMHistos() != nullptr)
868  // {
869  // __SUP_COUT__ << "Attempting to get LIVE ROOT object." << __E__;
870  // __SUP_COUTV__(fullPathToObject);
871  // fullPathToObject = path.substr(("/" + LIVEDQM_DIR + ".root").length());
872  // __SUP_COUTV__(fullPathToObject);
873  // rootFile = theDataManager_->getLiveDQMHistos()->getFile();
874 
875  // __SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
876 
877  // if(rootFile == nullptr || !rootFile->IsOpen())
878  // {
879  // __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
880  // << __E__;
881  // __SUP_COUT__ << ss.str();
882  // xmlOut.addTextElementToData("Warning", ss.str());
883  // theDataManager_->setDoNotStop(false);
884  // return; // do not treat LIVE root file missing as error, .. assume
885  // // just not Running
886  // }
887  // }
888  // else
889  // {
890  // __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
891  // << __E__;
892  // __SUP_COUT__ << ss.str();
893  // xmlOut.addTextElementToData("Warning", ss.str());
894  // theDataManager_->setDoNotStop(false);
895  // return; // do not treat LIVE root file missing as error, .. assume just
896  // // not Running
897  // }
898  // }
899 
900  // // at this point initial ROOT object has been successfully opened
901 
902  // xmlOut.addTextElementToData("path", path);
903 
904  // TDirectory* directory = rootFile->GetDirectory(fullPathToObject.c_str());
905  // __SUP_COUT__ << "Getting dir pointer: " << directory
906  // << " dir name: " << fullPathToObject << __E__;
907  // TObject* tobject = nullptr;
908 
909  // if(!directory) // if not directory yet, peak at object for TTree or
910  // // TBranchElement with children
911  // {
912  // ///////////////////////////////////////////////////////////////////////////
913  // // TREE HANDLING
914  // // if TTree or TBranchElement with children, then treat as a directory
915  // // else if TBranchElement without children, then treat as leaf ROOT object
916 
917  // fullPathToObject = fullPath.substr(
918  // rootExtensionEnd); // re-purpose fullPathToObject as path within TTree
919 
920  // std::vector<std::string> splitTTreePath =
921  // StringMacros::getVectorFromString(fullPathToObject, {'/'});
922  // __SUP_COUTV__(StringMacros::vectorToString(splitTTreePath));
923 
924  // unsigned int spliti = 0;
925  // while(spliti < splitTTreePath.size() && splitTTreePath[spliti].size() == 0)
926  // ++spliti; // search for first non-empty
927 
928  // if(spliti < splitTTreePath.size())
929  // {
930  // __SUP_COUTV__(splitTTreePath[spliti]);
931  // tobject = (TObject*)rootFile->Get(splitTTreePath[spliti].c_str());
932  // ++spliti; // search for next non-empty
933  // }
934 
935  // if(tobject == nullptr)
936  // {
937  // __SUP_SS__ << "Failed to access ROOT sub path: " << fullPathToObject
938  // << __E__;
939  // __SUP_SS_THROW__;
940  // }
941  // __SUP_COUTV__(tobject->ClassName());
942 
943  // if(std::string(tobject->ClassName()) == "TTree" ||
944  // std::string(tobject->ClassName()).find("TBranch") !=
945  // std::string::npos || // == "TBranchElement" ||
946  // std::string(tobject->ClassName()).find("TDirectory") != std::string::npos)
947  // {
948  // // continue traversing name split
949  // do
950  // {
951  // while(spliti < splitTTreePath.size() &&
952  // splitTTreePath[spliti].size() == 0)
953  // ++spliti; // search for next non-empty
954  // if(spliti >= splitTTreePath.size())
955  // break; // reached end of traversal!
956 
957  // __SUP_COUTV__(splitTTreePath[spliti]);
958  // __SUP_COUT__ << "Parent class = " << (tobject->ClassName()) << __E__;
959  // if(std::string(tobject->ClassName()) == "TTree")
960  // tobject = (TObject*)((TTree*)tobject)
961  // ->GetBranch(splitTTreePath[spliti].c_str());
962  // else if(std::string(tobject->ClassName()).find("TBranch") !=
963  // std::string::npos)
964  // tobject = (TObject*)((TBranchElement*)tobject)
965  // ->FindBranch(splitTTreePath[spliti].c_str());
966  // else if(std::string(tobject->ClassName()).find("TDirectory") !=
967  // std::string::npos)
968  // tobject = (TObject*)((TDirectoryFile*)tobject)
969  // ->Get(splitTTreePath[spliti].c_str());
970 
971  // ++spliti; // search for next non-empty
972  // } while(tobject);
973 
974  // if(tobject == nullptr)
975  // {
976  // __SUP_SS__ << "Failed to access root sub path: " << fullPathToObject
977  // << __E__;
978  // __SUP_SS_THROW__;
979  // }
980 
981  // __SUP_COUTV__(tobject->ClassName());
982 
983  // // now at path's target element with tobject
984  // // if no branches, then "file" and tobject stringified
985  // // else "dir"
986 
987  // TObjArray* objects = nullptr;
988 
989  // if(std::string(tobject->ClassName()) == "TTree")
990  // objects = ((TTree*)tobject)->GetListOfBranches();
991  // else if(std::string(tobject->ClassName()).find("TBranch") !=
992  // std::string::npos) //== "TBranchElement")
993  // objects = ((TBranchElement*)tobject)->GetListOfBranches();
994 
995  // if(objects != nullptr && !objects->IsEmpty())
996  // {
997  // __SUP_COUT__ << "Handling as TTree/TBranchElement directory" << __E__;
998 
999  // // treat like a directory, and return branches
1000  // TObject* obj;
1001  // TIter nextobj(objects->MakeIterator());
1002  // TRegexp re("*", kTRUE);
1003  // while((obj = (TObject*)nextobj()))
1004  // {
1005  // std::string name = obj->GetName();
1006  // TString s = name;
1007  // if(s.Index(re) == kNPOS)
1008  // continue;
1009 
1010  // __SUP_COUT__ << "Child class Name: " << obj->IsA()->GetName()
1011  // << " " << name << __E__;
1012 
1013  // if(std::string(obj->IsA()->GetName()).find("TBranch") !=
1014  // std::string::npos) // == "TBranchElement")
1015  // {
1016  // // decide if leave based on children branches
1017  // __SUP_COUT__
1018  // << "Child '" << name << "' of type '"
1019  // << ((TBranchElement*)obj)->GetTypeName() << "' isLeaf="
1020  // << ((TBranchElement*)obj)->GetListOfBranches()->IsEmpty()
1021  // << __E__;
1022 
1023  // xmlOut.addTextElementToData(
1024  // (((TBranchElement*)obj)->GetListOfBranches()->IsEmpty())
1025  // ? "file"
1026  // : "dir",
1027  // name);
1028  // }
1029  // else // handle normal way
1030  // {
1031  // xmlOut.addTextElementToData(
1032  // (std::string(obj->IsA()->GetName()).find("Directory") !=
1033  // std::string::npos ||
1034  // std::string(obj->IsA()->GetName()) == "TTree")
1035  // ? "dir"
1036  // : "file",
1037  // name);
1038  // }
1039  // }
1040  // theDataManager_->setDoNotStop(false);
1041  // return;
1042  // } // done handling TTree branches
1043  // } // end TTree and branch handling
1044  // else if(spliti < splitTTreePath.size())
1045  // {
1046  // __COUTV__(fullPathToObject);
1047  // // if more name to mystery object (likely TDirectoryFile), then attempt to
1048  // // get full subpath
1049  // tobject = (TObject*)rootFile->Get(fullPathToObject.c_str());
1050  // }
1051 
1052  // // at this point have tobject to stringify
1053  // } // peaking for TTree
1054 
1055  // if(directory == nullptr) // It MUST be an object to be serialized! tobject !=
1056  // // nullptr at this point.
1057  // {
1058  // __SUP_COUT__ << "This is not a directory!" << __E__;
1059 
1060  // if(tobject == nullptr)
1061  // {
1062  // __SUP_SS__
1063  // << "Something is wrong. Failed to access ROOT TObject at path: "
1064  // << fullPath << __E__;
1065  // __SUP_SS_THROW__;
1066  // }
1067 
1068  // // TObject* tobjectClone = nullptr;
1069 
1070  // if(tobject != nullptr) // turns out was a root object path
1071  // {
1072  // // ignore lock, because Lore says only crashed with Canvas
1073 
1074  // // FIXME -- check this new histo and gDirectory->Get for memory leak!
1075  // bool doJSONobject = false;
1076  // TH1F* h8 = nullptr;
1077  // std::string tmpClassName = tobject->ClassName();
1078  // if(tmpClassName.find("TBranch") != std::string::npos)
1079  // {
1080  // __COUT__ << "Attempting to plot '" << tobject->ClassName()
1081  // << "' type." << __E__;
1082 
1083  // h8 = new TH1F();
1084  // TTree* t3 = ((TBranch*)tobject)->GetTree();
1085  // //__COUT__ << "Attempting to plot '" << t3 << "' type." << __E__;
1086  // //__COUT__ << "JSON=" << TBufferJSON::ConvertToJSON(h8).Data() <<
1087  // //__E__;
1088  // t3->Draw("Value>>h8", "", "goff");
1089  // tobject = gDirectory->Get("h8");
1090 
1091  // __COUT__ << "Attempting to plot '" << tobject->ClassName()
1092  // << "' type." << __E__;
1093  // doJSONobject = true;
1094  // }
1095 
1096  // TString json;
1097  // TBufferFile tBuffer(TBuffer::kWrite);
1098  // if(theDataManager_ != nullptr &&
1099  // theDataManager_->getLiveDQMHistos() != nullptr && LDQM_pos == 0)
1100  // {
1101  // if(tobject->IsA() == TCanvas::Class())
1102  // {
1103  // static_cast<TCanvas*>(tobject)->Modified();
1104  // static_cast<TCanvas*>(tobject)->Update();
1105  // }
1106  // std::unique_lock<std::mutex> lock(
1107  // static_cast<DQMHistosConsumerBase*>(
1108  // theDataManager_->getLiveDQMHistos())
1109  // ->getFillHistoMutex());
1110  // json = TBufferJSON::ConvertToJSON(tobject);
1111  // tobject->Streamer(tBuffer);
1112  // }
1113  // else
1114  // {
1115  // // No need to lock from file!
1116  // json = TBufferJSON::ConvertToJSON(tobject);
1117  // tobject->Streamer(tBuffer);
1118  // }
1119 
1120  // std::string hexString = BinaryStringMacros::binaryStringToHexString(
1121  // tBuffer.Buffer(), tBuffer.Length());
1122 
1123  // __SUP_COUT__ << "Returning object '" << tobject->GetName()
1124  // << "' of class '" << tobject->ClassName() << __E__;
1125 
1126  // //__SUP_COUT__ << "Data: " << json.Data() << std::endl;
1127  // xmlOut.addTextElementToData("rootType",
1128  // doJSONobject ? "JSON" : tobject->ClassName());
1129  // xmlOut.addTextElementToData("rootData", hexString);
1130  // xmlOut.addTextElementToData("rootJSON", json.Data());
1131 
1132  // if(h8 != nullptr)
1133  // delete h8;
1134  // }
1135  // else
1136  // __SUP_COUT_ERR__ << "Failed to access:-" << fullPathToObject << "-"
1137  // << __E__;
1138  // STDLINE("Done with it!", ACBlue);
1139  // }
1140  // else // handle as directory
1141  // {
1142  // __SUP_COUT__ << "directory found getting the content!" << __E__;
1143  // STDLINE("Directory found getting the content!", ACGreen);
1144  // TRegexp re("*", kTRUE);
1145  // if(LDQM_pos == 0)
1146  // {
1147  // TObject* obj;
1148  // TIter nextobj(directory->GetList());
1149  // while((obj = (TObject*)nextobj()))
1150  // {
1151  // TString s = obj->GetName();
1152  // if(s.Index(re) == kNPOS)
1153  // continue;
1154  // __SUP_COUT__ << "Class Name: " << obj->IsA()->GetName() << __E__;
1155 
1156  // xmlOut.addTextElementToData(
1157  // (std::string(obj->IsA()->GetName()).find("Directory") !=
1158  // std::string::npos ||
1159  // std::string(obj->IsA()->GetName()) == "TTree" ||
1160  // std::string(obj->IsA()->GetName()).find("TBranch") !=
1161  // std::string::npos) // == "TBranchElement")
1162  // ? "dir"
1163  // : "file",
1164  // obj->GetName());
1165  // // ss.str("") ; ss << "obj->GetName(): " << obj->GetName() ;
1166  // // //STDLINE(ss.str(),"") ;
1167  // }
1168  // }
1169  // else
1170  // {
1171  // TKey* key;
1172  // TIter next(directory->GetListOfKeys());
1173  // while((key = (TKey*)next()))
1174  // {
1175  // TString s = key->GetName();
1176  // if(s.Index(re) == kNPOS)
1177  // continue;
1178  // __SUP_COUT__ << "Class Name: " << key->GetClassName() << __E__;
1179  // xmlOut.addTextElementToData(
1180  // (std::string(key->GetClassName()).find("Directory") !=
1181  // std::string::npos ||
1182  // std::string(key->GetClassName()) == "TTree" ||
1183  // std::string(key->GetClassName()).find("TBranch") !=
1184  // std::string::npos) // == "TBranchElement")
1185  // ? "dir"
1186  // : "file",
1187  // key->GetName());
1188  // // ss.str("") ; ss << "key->GetName(): " << key->GetName() ;
1189  // ////STDLINE(ss.str(),"") ;
1190  // }
1191  // }
1192  // }
1193  // if(LDQM_pos == std::string::npos)
1194  // rootFile->Close();
1195 
1196  // } // end getRoot handling
1197  else if(
1198  requestType ==
1199  "getEvents") // ################################################################################################################
1200  {
1201  if(theDataManager_ == nullptr)
1202  {
1203  __SS__ << "No Data Manager instantiated." << __E__;
1204  __SS_THROW__;
1205  }
1206 
1207  int Run = atoi(cgiIn("run").c_str());
1208 
1209  __SUP_COUT__ << "getEvents for run " << Run << __E__;
1210 
1211  if(Run != (int)loadedRunNumber_ || loadedRunNumber_ == (unsigned int)-1)
1212  {
1213  theDataManager_->load("Run1684.root", "Monicelli");
1214  loadedRunNumber_ = Run;
1215  }
1216 
1217  /*DOMElement* eventsParent =*/xmlOut.addTextElementToData("events", "");
1218  // DOMElement* eventParent;
1219  // char str[40];
1220 
1221  // const Visual3DEvents& events = theDataManager_->getVisual3DEvents();
1222  // __SUP_COUT__ << "Preparing hits xml" << __E__;
1223  // int numberOfEvents = 0;
1224  // for(Visual3DEvents::const_iterator it=events.begin(); it!=events.end() &&
1225  // numberOfEvents < 10000; it++, numberOfEvents++)
1226  // {
1227  // //__SUP_COUT__ << "Event: " << numberOfEvents << __E__;
1228  // eventParent = xmlOut.addTextElementToParent("event", str,
1229  // eventsParent); const VisualHits& hits = it->getHits();
1230  // for(VisualHits::const_iterator itHits=hits.begin();
1231  // itHits!=hits.end(); itHits++)
1232  // {
1233  // sprintf(str,"%f",itHits->x);
1234  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
1235  // sprintf(str,"%f",itHits->y);
1236  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
1237  // sprintf(str,"%f",itHits->z);
1238  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
1239  // //__SUP_COUT__ << "X: " << itHits->x << " Y: " << itHits->y << "
1240  // Z:
1241  //"
1242  //<< itHits->z << __E__;
1243  // }
1244  // const VisualTracks& tracks = it->getTracks();
1245  // for(VisualTracks::const_iterator itTrks=tracks.begin();
1246  // itTrks!=tracks.end(); itTrks++)
1247  // {
1248  // sprintf(str,"%f",itTrks->slopeX);
1249  // xmlOut.addTextElementToParent("slope", str, eventParent);
1250  // sprintf(str,"%f",itTrks->slopeY);
1251  // xmlOut.addTextElementToParent("slope", str, eventParent);
1252  // sprintf(str,"%f",itTrks->interceptX);
1253  // xmlOut.addTextElementToParent("intcpt", str, eventParent);
1254  // sprintf(str,"%f",itTrks->interceptY);
1255  // xmlOut.addTextElementToParent("intcpt", str, eventParent);
1256  //
1257  // }
1258  //
1259  // }
1260  __SUP_COUT__ << "Done hits xml" << __E__;
1261  }
1262  else if(
1263  requestType ==
1264  "getGeometry") // ################################################################################################################
1265  {
1266  __SUP_COUT__ << "getGeometry" << __E__;
1267 
1268  if(theDataManager_ == nullptr)
1269  {
1270  __SS__ << "No Data Manager instantiated." << __E__;
1271  __SS_THROW__;
1272  }
1273 
1274  // FIXME -- this crashes when the file doesn't exist!
1275  theDataManager_->load("Run1684.geo", "Geometry");
1276 
1277  __SUP_COUT__ << "getGeometry" << __E__;
1278 
1279  /*DOMElement* geometryParent =*/xmlOut.addTextElementToData("geometry", "");
1280  // const Visual3DShapes& shapes =
1281  // theDataManager_->getVisual3DGeometry().getShapes();
1282  //
1283  // __SUP_COUT__ << "getGeometry" << __E__;
1284  //
1285  //
1286  // DOMElement* objectParent;
1287  // char str[40];
1288  // for(Visual3DShapes::const_iterator itShapes=shapes.begin();
1289  // itShapes!=shapes.end(); itShapes++)
1290  // {
1291  // objectParent = xmlOut.addTextElementToParent("object", str,
1292  // geometryParent);
1293  // xmlOut.addTextElementToParent("object_type", "LINE_LOOP",
1294  // objectParent); sprintf(str,"%d",itShapes->numberOfRows);
1295  // xmlOut.addTextElementToParent("object_rows", str, objectParent);
1296  // sprintf(str,"%d",itShapes->numberOfColumns);
1297  // xmlOut.addTextElementToParent("object_columns", str, objectParent);
1298  // for(Points::const_iterator itCorners=itShapes->corners.begin();
1299  // itCorners!=itShapes->corners.end(); itCorners++)
1300  // {
1301  // sprintf(str,"%f",itCorners->x);
1302  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
1303  // sprintf(str,"%f",itCorners->y);
1304  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
1305  // sprintf(str,"%f",itCorners->z);
1306  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
1307  // }
1308  // }
1309  }
1310  else if(
1311  requestType ==
1312  "getRootConfig") // ################################################################################################################
1313  {
1314  std::string path = CgiDataUtilities::postData(cgiIn, "RootConfigPath");
1315  __SUP_COUT__ << "path " << path << __E__;
1316 
1317  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
1318  0) // ROOT config path must start the path
1319  {
1320  path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
1321  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
1322  __SUP_COUT__ << "mod path " << path << __E__;
1323  }
1324 
1325  HttpXmlDocument cfgXml;
1326  if(cfgXml.loadXmlDocument(path))
1327  {
1328  xmlOut.addTextElementToData("status", "1");
1329  xmlOut.copyDataChildren(cfgXml); // copy file to output xml
1330  cfgXml.saveXmlDocument(path);
1331  }
1332  else
1333  xmlOut.addTextElementToData("status",
1334  "Failed. File to properly load config file.");
1335  }
1336  else if(
1337  requestType ==
1338  "rootAdminControls") // ################################################################################################################
1339  {
1340  // if(userPermissions < ROOT_VIEWER_PERMISSIONS_THRESHOLD)
1341  // {
1342  // __SUP_COUT__ << "Insufficient permissions for Root Viewer Admin
1343  // Controls: " << userPermissions << " < " << ROOT_VIEWER_PERMISSIONS_THRESHOLD <<
1344  // __E__;
1345  // xmlOut.addTextElementToData("status", "Failed. Insufficient user
1346  // permissions.");
1347  // }
1348  // else
1349  // {
1350  std::string cmd = cgiIn("cmd"); // possible commands are
1351  // mkdir
1352  // save
1353  // delete
1354 
1355  std::string path = CgiDataUtilities::postData(cgiIn, "path");
1356  std::string name = CgiDataUtilities::postData(cgiIn, "name");
1357  __SUP_COUT__ << "cmd " << cmd << __E__;
1358  __SUP_COUT__ << "path " << path << __E__;
1359  __SUP_COUT__ << "name " << name << __E__;
1360 
1361  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
1362  0) // ROOT config path must start the path
1363  {
1364  path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
1365  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2) + name;
1366  __SUP_COUT__ << "mod path " << path << __E__;
1367 
1368  if(cmd == "mkdir")
1369  {
1370  if(mkdir(path.c_str(),
1371  S_IRWXU | (S_IRGRP | S_IXGRP) |
1372  (S_IROTH | S_IXOTH))) // mode = drwx r-x r-x
1373  xmlOut.addTextElementToData("status",
1374  "Failed. Directory create rejected.");
1375  else
1376  xmlOut.addTextElementToData("status", "1"); // success
1377  }
1378  else if(cmd == "save")
1379  {
1380  path += PRE_MADE_ROOT_CFG_FILE_EXT; // add file extension
1381 
1382  bool useRunWildCard =
1383  atoi(CgiDataUtilities::postData(cgiIn, "useRunWildCard")
1384  .c_str()); // 0 or 1
1385  std::string config = CgiDataUtilities::postData(cgiIn, "config");
1386  __SUP_COUT__ << "config " << config << __E__;
1387  __SUP_COUT__ << "useRunWildCard " << useRunWildCard << __E__;
1388 
1389  // check if file already exists
1390  FILE* fp = fopen(path.c_str(), "r");
1391  if(fp)
1392  {
1393  fclose(fp);
1394  xmlOut.addTextElementToData("status", "Failed. File already exists.");
1395  __SUP_COUT__ << " Failed. File already exists." << __E__;
1396  }
1397  else
1398  {
1399  // dump to file
1400  // verify proper format through read back
1401  // if successfully loaded, re-save for formatting
1402 
1403  // dump to file
1404  fp = fopen(path.c_str(), "w");
1405  fputs(config.c_str(), fp);
1406  fclose(fp);
1407 
1408  // verify proper format through read back
1409  HttpXmlDocument cfgXml;
1410  if(cfgXml.loadXmlDocument(path))
1411  {
1412  // successfully loaded, re-save for formatting
1413  cfgXml.saveXmlDocument(path);
1414  xmlOut.addTextElementToData("status", "1"); // success
1415  }
1416  else // failed to load properly
1417  {
1418  xmlOut.addTextElementToData(
1419  "status", "Failed. Fatal. Improper file format.");
1420  if(remove(path.c_str()) != 0)
1421  __SUP_COUT__ << "Failed. Could not remove poorly formed Root "
1422  "config file!"
1423  << __E__;
1424  }
1425  }
1426  }
1427  else if(cmd == "delete")
1428  {
1429  // guess first directory and then file
1430  if(rmdir(path.c_str()) == 0 ||
1431  remove((path + PRE_MADE_ROOT_CFG_FILE_EXT).c_str()) == 0)
1432  xmlOut.addTextElementToData("status", "1"); // success
1433  else
1434  xmlOut.addTextElementToData("status",
1435  "Failed. Target could not be deleted.");
1436  }
1437  else
1438  xmlOut.addTextElementToData("status", "Failed. Unrecognized command.");
1439  }
1440  else
1441  xmlOut.addTextElementToData("status", "Failed. Invalid path.");
1442 
1443  //}
1444  }
1445  else if(
1446  requestType ==
1447  "getMeDirs") // ################################################################################################################
1448  {
1449  xmlOut.setDarioStyle(true); // workaround for XML formatting....
1450  std::string fSystemPath = std::string(ROOT_BROWSER_PATH) + "/";
1451  std::string fRootPath = CgiDataUtilities::postData(cgiIn, "Path");
1452  boost::regex re("%2F");
1453  fRootPath = boost::regex_replace(fRootPath, re, "/");
1454  std::string fullPath = fSystemPath + fRootPath;
1455  // fFoldersPath_ = "pippo" ;
1456  STDLINE(std::string("Begin: fSystemPath = ") + fSystemPath, ACWhite);
1457  STDLINE(std::string("Begin: fRootPath = ") + fRootPath, ACWhite);
1458  STDLINE(std::string("Begin: fullPath = ") + fullPath, ACWhite);
1459  // STDLINE(std::string("Begin: fFoldersPath = ")+fFoldersPath_,ACCyan ) ;
1460 
1461  xmlOut.setRootPath(fRootPath);
1462  xmlOut.makeDirectoryBinaryTree(fSystemPath, fRootPath, 0, NULL);
1463  std::ostringstream* out = new std::ostringstream();
1464  xmlOut.outputXmlDocument((std::ostringstream*)out, true);
1465  }
1466  else if(
1467  requestType ==
1468  "getMeRootFile") // ################################################################################################################
1469  {
1470  xmlOut.setDarioStyle(true); // workaround for XML formatting....
1471  std::string fSystemPath = std::string(ROOT_BROWSER_PATH) + "/";
1472  std::string fRootPath = CgiDataUtilities::postData(cgiIn, "fRootPath");
1473  std::string fFoldersPath = CgiDataUtilities::postData(cgiIn, "fFoldersPath");
1474  std::string fHistName = CgiDataUtilities::postData(cgiIn, "fHistName");
1475  std::string fRFoldersPath = CgiDataUtilities::postData(cgiIn, "fRFoldersPath");
1476  std::string fFileName = CgiDataUtilities::postData(cgiIn, "fFileName");
1477  boost::regex re("%2F");
1478  fRootPath = boost::regex_replace(fRootPath, re, "/");
1479  fFoldersPath = boost::regex_replace(fFoldersPath, re, "/");
1480  // STDLINE(std::string("fSystemPath : ")+fSystemPath ,ACCyan);
1481  // STDLINE(std::string("fRootPath : ")+fRootPath ,ACCyan);
1482  // STDLINE(std::string("fFoldersPath : ")+fFoldersPath ,ACCyan);
1483  // STDLINE(std::string("fHistName : ")+fHistName ,ACCyan);
1484  // STDLINE(std::string("fRFoldersPath: ")+fRFoldersPath,ACCyan);
1485  // STDLINE(std::string("fFileName : ")+fFileName ,ACCyan);
1486  RootFileExplorer* theExplorer = new RootFileExplorer(
1487  fSystemPath, fRootPath, fFoldersPath, fHistName, fRFoldersPath, fFileName);
1488  xmlOut.setDocument(theExplorer->initialize(false));
1489  // std::ostringstream* out ;
1490  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
1491  }
1492  // else if(
1493  // requestType ==
1494  // "getMeLIVE-DQMFile")
1495  // //################################################################################################################
1496  // {
1497  // xmlOut.setDarioStyle(true); // workaround for XML formatting....
1498  // std::string fSystemPath = std::string(ROOT_BROWSER_PATH) + "/";
1499  // std::string fRootPath = CgiDataUtilities::postData(cgiIn, "fRootPath");
1500  // std::string fFoldersPath = CgiDataUtilities::postData(cgiIn, "fFoldersPath");
1501  // std::string fHistName = CgiDataUtilities::postData(cgiIn, "fHistName");
1502  // std::string fRFoldersPath = CgiDataUtilities::postData(cgiIn, "fRFoldersPath");
1503  // std::string fFileName = CgiDataUtilities::postData(cgiIn, "fFileName");
1504  // STDLINE(std::string("fSystemPath : ") + fSystemPath, ACCyan);
1505  // STDLINE(std::string("fRootPath : ") + fRootPath, ACCyan);
1506  // STDLINE(std::string("fFoldersPath : ") + fFoldersPath, ACCyan);
1507  // STDLINE(std::string("fHistName : ") + fHistName, ACCyan);
1508  // STDLINE(std::string("fRFoldersPath: ") + fRFoldersPath, ACCyan);
1509  // STDLINE(std::string("fFileName : ") + fFileName, ACCyan);
1510  // boost::regex re("%2F");
1511  // fRootPath = boost::regex_replace(fRootPath, re, "/");
1512  // fFoldersPath = boost::regex_replace(fFoldersPath, re, "/");
1513 
1514  // TFile* rootFile;
1515  // STDLINE("Getting LiveDQMHistos", ACGreen);
1516  // if(theDataManager_->getLiveDQMHistos() != nullptr)
1517  // {
1518  // STDLINE("Selecting LIVE_DQM.root", ACCyan);
1519  // rootFile = theDataManager_->getLiveDQMHistos()->getFile();
1520  // fRootPath = "LIVE_DQM.root";
1521  // }
1522  // else
1523  // {
1524  // STDLINE(string("fRootPath: ") + fRootPath, ACGreen);
1525  // rootFile = TFile::Open(fRootPath.c_str());
1526  // }
1527  // string cmd = string("ls -la ") + fRootPath;
1528  // system(cmd.c_str());
1529  // // STDLINE(string("before regexp fRootPath: ")+fRootPath,ACGreen) ;
1530  // // fRootPath = rootFile->GetName() ; // Bisogna strippare via il full path!!!
1531  // // boost::regex regg(fSystemPath.c_str()) ;
1532  // // fRootPath = boost::regex_replace(fRootPath,regg,"/") ; // Dario: should be
1533  // // transparent for Ryan's purposes but required by Extjs STDLINE(string("after
1534  // // regexp fRootPath: ")+fRootPath,ACGreen) ;
1535  // STDLINE(std::string("fSystemPath : ") + fSystemPath, ACCyan);
1536  // STDLINE(std::string("fRootPath : ") + fRootPath, ACCyan);
1537  // STDLINE(std::string("fFoldersPath : ") + fFoldersPath, ACCyan);
1538  // STDLINE(std::string("fHistName : ") + fHistName, ACCyan);
1539  // STDLINE(std::string("fRFoldersPath: ") + fRFoldersPath, ACCyan);
1540  // STDLINE(std::string("fFileName : ") + fFileName, ACCyan);
1541  // RootFileExplorer* theExplorer = new RootFileExplorer(fSystemPath,
1542  // fRootPath,
1543  // fFoldersPath,
1544  // fHistName,
1545  // fRFoldersPath,
1546  // fFileName,
1547  // rootFile);
1548  // xmlOut.setDocument(theExplorer->initialize(true));
1549  // // std::ostringstream* out ;
1550  // // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
1551  // }
1552  else if(
1553  requestType ==
1554  "saveConfiguration") // ################################################################################################################
1555  {
1556  std::string configPayload = CgiDataUtilities::postData(cgiIn, "configPayload");
1557  STDLINE("configPayload: ", ACRed);
1558  STDLINE(configPayload, ACYellow);
1559 
1560  fstream outFile;
1561  outFile.open("/tmp/configPayload.json", ios::out | ios::app);
1562  outFile << configPayload << endl;
1563  outFile.close();
1564  }
1565  else if(
1566  requestType ==
1567  "getConfiguration") // ################################################################################################################
1568  {
1569  std::string configPayload = CgiDataUtilities::postData(cgiIn, "configPayload");
1570  std::string JSONPayLoad = "";
1571  std::string line = "";
1572 
1573  ifstream JSONFile("/tmp/configPayload.json");
1574 
1575  if(JSONFile.is_open())
1576  {
1577  while(getline(JSONFile, line))
1578  {
1579  JSONPayLoad += line;
1580  }
1581  JSONFile.close();
1582  }
1583 
1584  xmlOut.addTextElementToData("JSONPayLoad", JSONPayLoad);
1585  // std::ostringstream* out ;
1586  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
1587  }
1588  else if(
1589  requestType ==
1590  "getState") // ################################################################################################################
1591  {
1592  std::string fsmName = theStateMachine_.getCurrentStateName();
1593  bool in_transition = theStateMachine_.isInTransition();
1594 
1595  xmlOut.addTextElementToData("current_state", fsmName);
1596  xmlOut.addTextElementToData("in_transition", in_transition ? "1" : "0");
1597  }
1598  else
1599  {
1600  __SUP_SS__ << "requestType Request, " << requestType
1601  << ", not recognized by the Visual Supervisor (was it intended for "
1602  "another Supervisor?)."
1603  << __E__;
1604  __SUP_SS_THROW__;
1605  }
1606 
1607  if(theDataManager_ != nullptr)
1608  theDataManager_->setDoNotStop(false);
1609 
1610 } //end request()
static std::string postData(cgicc::Cgicc &cgi, const std::string &needle)
static std::string getData(cgicc::Cgicc &cgi, const std::string &needle)
bool isDisconnected(void) const
ConfigurationTree getNode(const std::string &nodeName, bool doNotThrowOnBrokenUIDLinks=false) const
const std::string & getValueAsString(bool returnLinkTableValue=false) const
WebUsers::permissionLevel_t getSupervisorPropertyUserPermissionsThreshold(const std::string &requestType)
virtual void transitionHalting(toolbox::Event::Reference event)
static void deleteInstance(std::string instanceUID)
void copyDataChildren(HttpXmlDocument &document)
bool loadXmlDocument(const std::string &filePath)
void outputXmlDocument(std::ostringstream *out, bool dispStdOut=false, bool allowWhiteSpace=false, bool printErrors=false)
const std::vector< DQMHistosBase * > & getLiveDQMs(void)
virtual void setSupervisorPropertyDefaults(void) override
virtual void forceSupervisorPropertyValues(void) override
virtual void transitionConfiguring(toolbox::Event::Reference e) override
virtual void request(const std::string &requestType, cgicc::Cgicc &cgiIn, HttpXmlDocument &xmlOut, const WebUsers::RequestUserInfo &userInfo) override
void setDarioStyle(bool darioStyle)
void saveXmlDocument(const std::string &filePath)
void INIT_MF(const char *name)
static std::string binaryStringToHexString(const void *binaryBuffer, unsigned int numberOfBytes, const std::string &resultPreamble="", const std::string &resultDelimiter="")