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