otsdaq-utilities  3.03.02
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"),
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 } // end transitionConfiguring() catch
215 
216 //==============================================================================
217 void VisualSupervisor::transitionHalting(toolbox::Event::Reference e)
218 {
219  __SUP_COUT__ << "Halting..." << __E__;
220 
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 } //end setSupervisorPropertyDefaults()
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 } //end forceSupervisorPropertyValues()
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_ >=
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
515  xmlOut.addTextElementToData("dir",
516  LIVEDQM_DIR + ".root"); // add to xml
517 
518  // check for ROOT_DISPLAY_CONFIG_PATH
519  DIR* pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH);
520  bool recheck = false;
521  if(!pRtDIR) // if doesn't exist, make it
522  {
523  recheck = true;
524  if(mkdir(ROOT_DISPLAY_CONFIG_PATH,
525  S_IRWXU | (S_IRGRP | S_IXGRP) |
526  (S_IROTH | S_IXOTH))) // mode = drwx r-x r-x
527  __SUP_COUT__ << "Failed to make directory for pre made views: "
528  << ROOT_DISPLAY_CONFIG_PATH << __E__;
529  }
530  else
531  closedir(pRtDIR); // else close and display
532 
533  if(!recheck || (pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH)))
534  {
537  xmlOut.addTextElementToData("dir",
538  PRE_MADE_ROOT_CFG_DIR); // add to xml
539  if(recheck)
540  closedir(pRtDIR);
541  }
542  }
544  while((entry = readdir(pDIR)))
545  {
546  //__SUP_COUT__ << int(entry->d_type) << " " << entry->d_name << "\n" <<
547  // __E__;
548  if(entry->d_name[0] != '.' &&
549  (entry->d_type ==
550  0 || // 0 == UNKNOWN (which can happen - seen in SL7 VM)
551  entry->d_type == 4 ||
552  entry->d_type == 8))
553  {
554  //__SUP_COUT__ << int(entry->d_type) << " " << entry->d_name << "\n"
555  //<< __E__;
556  isNotRtCfg =
557  std::string(entry->d_name).find(".rcfg") == std::string::npos;
558  isDir = false;
559 
560  if(entry->d_type == 0)
561  {
562  // unknown type .. determine if directory
564  DIR* pTmpDIR = opendir((dirpath + entry->d_name).c_str());
565  if(pTmpDIR)
566  {
568  isDir = true;
569  closedir(pTmpDIR);
570  }
571  // else //assume file
572  }
573 
574  if((entry->d_type == 8 ||
575  (!isDir && entry->d_type == 0)) // file type
576  && std::string(entry->d_name).find(".root") == std::string::npos &&
577  isNotRtCfg)
578  continue; // skip if not a root file or a config file
579  else if(entry->d_type == 4)
580  isDir = true; // flag directory types
581 
582  xmlOut.addTextElementToData(
583  isDir ? "dir" : (isNotRtCfg ? "dir" : "file"), entry->d_name);
584  }
585  }
586  closedir(pDIR);
587  }
588  else
589  __SUP_COUT__ << "Failed to access directory contents!" << __E__;
590  // std::ostringstream* out ;
591  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
592  }
593  else if(
594  requestType ==
595  "getRoot") // ################################################################################################################
596  {
597  // return directory structure for requested ROOT path, types are "dir" and "file"
598  std::string path = CgiDataUtilities::postData(cgiIn, "RootPath");
599  __SUP_COUTV__(path);
600 
601  unsigned splitter = path.find(".root") + 5; // 5 = std::string(".root").size();
602  std::string rootFileName =
603  std::string(__ENV__("ROOT_BROWSER_PATH")) + path.substr(0, splitter);
604  __SUP_COUTV__(rootFileName);
605 
606  std::string rootDirectoryName = path.substr(splitter, path.length() - splitter);
607  __SUP_COUTV__(rootDirectoryName);
608 
609  // std::string fullPathToObject = rootFileName + ":" + rootDirectoryName;
610  // __SUP_COUTV__(fullPathToObject);
611 
612  bool isLiveDQM = (path.find("/" + LIVEDQM_DIR + ".root/") == 0) ? true : false;
613  __SUP_COUTV__(isLiveDQM);
614 
615  TFile* rootFile = nullptr;
616  TObject* tObject = nullptr;
617  TDirectory* tDirectory = nullptr;
618 
619  if(!isLiveDQM) // If it is not from LIVE_DQM
620  {
621  rootFile = TFile::Open(rootFileName.c_str());
622 
623  if(rootFile == nullptr || !rootFile->IsOpen())
624  {
625  __SUP_SS__ << "Failed to access ROOT file: " << rootFileName << __E__;
626  __SUP_SS_THROW__;
627  }
628  // First I check if I can find the object to return directly. If not an object
629  // it is a directory
630  if((tObject = rootFile->Get(rootDirectoryName.c_str())) !=
631  nullptr || //for backwards compatibility
632  (rootDirectoryName.size() &&
633  rootDirectoryName[0] == '/' && //for newer root, remove leading '/'
634  (tObject = rootFile->Get(rootDirectoryName.substr(1).c_str())) !=
635  nullptr))
636  {
637  if(tObject->IsA() == TCanvas::Class())
638  {
639  static_cast<TCanvas*>(tObject)->Modified();
640  static_cast<TCanvas*>(tObject)->Update();
641  }
642  TString json = TBufferJSON::ConvertToJSON(tObject);
643  TBufferFile tBuffer(TBuffer::kWrite);
644  tObject->Streamer(tBuffer);
645  std::string hexString = BinaryStringMacros::binaryStringToHexString(
646  tBuffer.Buffer(), tBuffer.Length());
647 
648  __SUP_COUT__ << "Returning object from file '" << tObject->GetName()
649  << "' of class '" << tObject->ClassName() << __E__;
650 
651  xmlOut.addTextElementToData("path", path);
652  xmlOut.addTextElementToData("rootType", tObject->ClassName());
653  xmlOut.addTextElementToData("rootData", hexString);
654  xmlOut.addTextElementToData("rootJSON", json.Data());
655  }
656  else if((tDirectory = rootFile->GetDirectory(rootDirectoryName.c_str())) !=
657  nullptr)
658  {
659  TKey* key;
660  TIter next(tDirectory->GetListOfKeys());
661  xmlOut.addTextElementToData("path", path);
662  while((key = (TKey*)next()))
663  {
664  TString s = key->GetName();
665  TRegexp re("*", kTRUE);
666  if(s.Index(re) == kNPOS)
667  continue;
668  __SUP_COUT__ << "Class Name: " << key->GetClassName() << __E__;
669  xmlOut.addTextElementToData(
670  (std::string(key->GetClassName()).find("Directory") !=
671  std::string::npos ||
672  std::string(key->GetClassName()) == "TTree" ||
673  std::string(key->GetClassName()).find("TBranch") !=
674  std::string::npos) // == "TBranchElement")
675  ? "dir"
676  : "file",
677  key->GetName());
678 
679  if(TTEST(
680  50)) //enable to view json content of each object in directory
681  {
682  tObject = key->ReadObj();
683  __SUP_COUT__ << "JSON : " << key->GetClassName() << __E__;
684 
685  TString json = TBufferJSON::ConvertToJSON(tObject);
686  TBufferFile tBuffer(TBuffer::kWrite);
687  tObject->Streamer(tBuffer);
688  std::string hexString =
690  tBuffer.Length());
691 
692  __SUP_COUT__ << "Returning directory object from file '"
693  << tObject->GetName() << "' of class '"
694  << tObject->ClassName() << __E__;
695 
696  __SUP_COUTV__(json.Data());
697  }
698  }
699  rootFile->Close();
700  }
701  else
702  __SUP_COUT_ERR__ << "Failed to find object " << rootDirectoryName
703  << " in " << rootFileName << __E__;
704  return;
705  }
706  // LIVE DQM PLOTS
707  else if(theDataManager_ != nullptr && theDataManager_->isReady())
708  {
709  if(theDataManager_ != nullptr)
710  theDataManager_->setDoNotStop(true);
711  else
712  return;
713  __SUP_COUT__ << "Attempting to get LIVE ROOT object." << __E__;
714 
715  std::vector<DQMHistosBase*> dqmConsumers = theDataManager_->getLiveDQMs();
716  tObject = nullptr;
717  for(auto const& consumer : dqmConsumers)
718  {
719  rootFile = consumer->getFile();
720  __SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
721  if(rootFile == nullptr || !rootFile->IsOpen())
722  {
723  __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
724  << __E__;
725  theDataManager_->setDoNotStop(false);
726  return;
727  }
728  // If I find an object then I stream it and return
729  if((tObject = rootFile->Get(rootDirectoryName.c_str())) != nullptr)
730  {
731  __SUP_COUT__ << "Object class name: " << tObject->ClassName()
732  << __E__;
733  std::string tmpClassName = tObject->ClassName();
734  TString json;
735  TBufferFile tBuffer(TBuffer::kWrite);
736  if(tObject->IsA() == TCanvas::Class())
737  {
738  static_cast<TCanvas*>(tObject)->Modified();
739  static_cast<TCanvas*>(tObject)->Update();
740  }
741  { // Only locking when converting the object
742  std::unique_lock<std::mutex> lock(
743  static_cast<DQMHistosConsumerBase*>(consumer)
744  ->getFillHistoMutex());
745  json = TBufferJSON::ConvertToJSON(tObject);
746  tObject->Streamer(tBuffer);
747  }
748  std::string hexString = BinaryStringMacros::binaryStringToHexString(
749  tBuffer.Buffer(), tBuffer.Length());
750 
751  __SUP_COUT__ << "Returning object '" << tObject->GetName()
752  << "' of class '" << tObject->ClassName() << __E__;
753 
754  //__SUP_COUT__ << "Data: " << json.Data() << std::endl;
755  xmlOut.addTextElementToData("path", path);
756  xmlOut.addTextElementToData("rootType", tObject->ClassName());
757  xmlOut.addTextElementToData("rootData", hexString);
758  xmlOut.addTextElementToData("rootJSON", json.Data());
759 
760  theDataManager_->setDoNotStop(false);
761  return;
762  }
763  }
764  // If I didn't find any object in the file, then it must be a directory!
765  std::map<std::string, std::string> dirList;
766 
767  for(auto const& consumer : dqmConsumers)
768  {
769  __SUP_COUT__ << "Attempting to get LIVE ROOT directory." << __E__;
770  rootFile = consumer->getFile();
771  __SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
772  if(rootFile == nullptr || !rootFile->IsOpen())
773  {
774  __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
775  << __E__;
776  xmlOut.addTextElementToData("Warning", ss.str());
777  theDataManager_->setDoNotStop(false);
778  return;
779  }
780  if((tDirectory = rootFile->GetDirectory(rootDirectoryName.c_str())) !=
781  nullptr)
782  {
783  xmlOut.addTextElementToData("path", path);
784  __SUP_COUT__ << "Directory found getting the content!" << __E__;
785  TRegexp re("*", kTRUE);
786  TObject* obj;
787  TIter nextobj(tDirectory->GetList());
788  while((obj = (TObject*)nextobj()))
789  {
790  TString s = obj->GetName();
791  if(s.Index(re) == kNPOS)
792  continue;
793  __SUP_COUT__ << "Class Name: " << obj->IsA()->GetName() << __E__;
794  dirList[obj->GetName()] =
795  (std::string(obj->IsA()->GetName()).find("Directory") !=
796  std::string::npos ||
797  std::string(obj->IsA()->GetName()) == "TTree" ||
798  std::string(obj->IsA()->GetName()).find("TBranch") !=
799  std::string::npos) // == "TBranchElement")
800  ? "dir"
801  : "file";
802  }
803  }
804  }
805  for(auto const& dir : dirList)
806  {
807  xmlOut.addTextElementToData(dir.second, dir.first);
808  __SUP_COUT__ << "Class Name: " << dir.second << " Object: " << dir.first
809  << __E__;
810  }
811  }
812 
813  } // END LORENZO GET ROOT
814  // else if(
815  // requestType ==
816  // "RyangetRoot")
817  // //################################################################################################################
818  // {
819  // // return directory structure for requested ROOT path, types are "dir" and "file"
820  // std::string path = CgiDataUtilities::postData(cgiIn, "RootPath");
821 
822  // //////////////////////////////////////////////////////////////////
823  // // DARIO
824  // //////////////////////////////////////////////////////////////////
825  // ss.str("");
826  // ss << "PID: " << ::getpid();
827  // // STDLINE(ss.str(),ACCyan) ;
828  // boost::regex re1("%2F");
829  // path = boost::regex_replace(
830  // path, re1, "/"); // Dario: should be transparent for Ryan's purposes but
831  // // required by Extjs
832  // boost::regex re2("%20");
833  // path = boost::regex_replace(
834  // path, re2, " "); // Dario: should be transparent for Ryan's purposes but
835  // // required by Extjs
836  // boost::regex re3("%3A");
837  // path =
838  // boost::regex_replace(path, re3, ""); // Dario: should be transparent for
839  // // Ryan's purposes but required by Extjs
840  // ss.str("");
841  // ss << "path : " << path;
842  // // STDLINE(ss.str(),ACCyan) ;
843  // //////////////////////////////////////////////////////////////////
844  // // END DARIO
845  // //////////////////////////////////////////////////////////////////
846 
847  // std::string fullPath = std::string(__ENV__("ROOT_BROWSER_PATH")) + path;
848  // __SUP_COUTV__(fullPath);
849 
850  // const size_t rootExtensionStart = fullPath.find(".root");
851  // const size_t rootExtensionEnd = rootExtensionStart + std::string(".root").size();
852 
853  // std::string rootFileName = fullPath.substr(0, rootExtensionEnd);
854 
855  // __SUP_COUTV__(rootFileName);
856  // std::string fullPathToObject =
857  // rootFileName + ":" +
858  // fullPath.substr(rootExtensionEnd, fullPath.size() - rootExtensionEnd + 1);
859 
860  // __SUP_COUTV__(fullPathToObject);
861  // std::string::size_type LDQM_pos = path.find("/" + LIVEDQM_DIR + ".root/");
862  // __SUP_COUTV__(LDQM_pos);
863 
864  // TFile* rootFile = nullptr;
865  // if(LDQM_pos == std::string::npos) // If it is not from LIVE_DQM
866  // {
867  // __SUP_COUTV__(rootFileName);
868  // rootFile = TFile::Open(rootFileName.c_str());
869 
870  // if(rootFile == nullptr || !rootFile->IsOpen())
871  // {
872  // __SUP_SS__ << "Failed to access ROOT file: " << rootFileName << __E__;
873  // __SUP_SS_THROW__;
874  // }
875  // }
876  // else
877  // {
878  // if(theDataManager_ == nullptr || !theDataManager_->isReady())
879  // return;
880  // theDataManager_->setDoNotStop(true);
881  // if(theDataManager_ != nullptr &&
882  // theDataManager_->getLiveDQMHistos() != nullptr)
883  // {
884  // __SUP_COUT__ << "Attempting to get LIVE ROOT object." << __E__;
885  // __SUP_COUTV__(fullPathToObject);
886  // fullPathToObject = path.substr(("/" + LIVEDQM_DIR + ".root").length());
887  // __SUP_COUTV__(fullPathToObject);
888  // rootFile = theDataManager_->getLiveDQMHistos()->getFile();
889 
890  // __SUP_COUT__ << "LIVE file name: " << rootFile->GetName() << __E__;
891 
892  // if(rootFile == nullptr || !rootFile->IsOpen())
893  // {
894  // __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
895  // << __E__;
896  // __SUP_COUT__ << ss.str();
897  // xmlOut.addTextElementToData("Warning", ss.str());
898  // theDataManager_->setDoNotStop(false);
899  // return; // do not treat LIVE root file missing as error, .. assume
900  // // just not Running
901  // }
902  // }
903  // else
904  // {
905  // __SUP_SS__ << "Failed to access LIVE ROOT file: " << rootFileName
906  // << __E__;
907  // __SUP_COUT__ << ss.str();
908  // xmlOut.addTextElementToData("Warning", ss.str());
909  // theDataManager_->setDoNotStop(false);
910  // return; // do not treat LIVE root file missing as error, .. assume just
911  // // not Running
912  // }
913  // }
914 
915  // // at this point initial ROOT object has been successfully opened
916 
917  // xmlOut.addTextElementToData("path", path);
918 
919  // TDirectory* directory = rootFile->GetDirectory(fullPathToObject.c_str());
920  // __SUP_COUT__ << "Getting dir pointer: " << directory
921  // << " dir name: " << fullPathToObject << __E__;
922  // TObject* tobject = nullptr;
923 
924  // if(!directory) // if not directory yet, peak at object for TTree or
925  // // TBranchElement with children
926  // {
927  // ///////////////////////////////////////////////////////////////////////////
928  // // TREE HANDLING
929  // // if TTree or TBranchElement with children, then treat as a directory
930  // // else if TBranchElement without children, then treat as leaf ROOT object
931 
932  // fullPathToObject = fullPath.substr(
933  // rootExtensionEnd); // re-purpose fullPathToObject as path within TTree
934 
935  // std::vector<std::string> splitTTreePath =
936  // StringMacros::getVectorFromString(fullPathToObject, {'/'});
937  // __SUP_COUTV__(StringMacros::vectorToString(splitTTreePath));
938 
939  // unsigned int spliti = 0;
940  // while(spliti < splitTTreePath.size() && splitTTreePath[spliti].size() == 0)
941  // ++spliti; // search for first non-empty
942 
943  // if(spliti < splitTTreePath.size())
944  // {
945  // __SUP_COUTV__(splitTTreePath[spliti]);
946  // tobject = (TObject*)rootFile->Get(splitTTreePath[spliti].c_str());
947  // ++spliti; // search for next non-empty
948  // }
949 
950  // if(tobject == nullptr)
951  // {
952  // __SUP_SS__ << "Failed to access ROOT sub path: " << fullPathToObject
953  // << __E__;
954  // __SUP_SS_THROW__;
955  // }
956  // __SUP_COUTV__(tobject->ClassName());
957 
958  // if(std::string(tobject->ClassName()) == "TTree" ||
959  // std::string(tobject->ClassName()).find("TBranch") !=
960  // std::string::npos || // == "TBranchElement" ||
961  // std::string(tobject->ClassName()).find("TDirectory") != std::string::npos)
962  // {
963  // // continue traversing name split
964  // do
965  // {
966  // while(spliti < splitTTreePath.size() &&
967  // splitTTreePath[spliti].size() == 0)
968  // ++spliti; // search for next non-empty
969  // if(spliti >= splitTTreePath.size())
970  // break; // reached end of traversal!
971 
972  // __SUP_COUTV__(splitTTreePath[spliti]);
973  // __SUP_COUT__ << "Parent class = " << (tobject->ClassName()) << __E__;
974  // if(std::string(tobject->ClassName()) == "TTree")
975  // tobject = (TObject*)((TTree*)tobject)
976  // ->GetBranch(splitTTreePath[spliti].c_str());
977  // else if(std::string(tobject->ClassName()).find("TBranch") !=
978  // std::string::npos)
979  // tobject = (TObject*)((TBranchElement*)tobject)
980  // ->FindBranch(splitTTreePath[spliti].c_str());
981  // else if(std::string(tobject->ClassName()).find("TDirectory") !=
982  // std::string::npos)
983  // tobject = (TObject*)((TDirectoryFile*)tobject)
984  // ->Get(splitTTreePath[spliti].c_str());
985 
986  // ++spliti; // search for next non-empty
987  // } while(tobject);
988 
989  // if(tobject == nullptr)
990  // {
991  // __SUP_SS__ << "Failed to access root sub path: " << fullPathToObject
992  // << __E__;
993  // __SUP_SS_THROW__;
994  // }
995 
996  // __SUP_COUTV__(tobject->ClassName());
997 
998  // // now at path's target element with tobject
999  // // if no branches, then "file" and tobject stringified
1000  // // else "dir"
1001 
1002  // TObjArray* objects = nullptr;
1003 
1004  // if(std::string(tobject->ClassName()) == "TTree")
1005  // objects = ((TTree*)tobject)->GetListOfBranches();
1006  // else if(std::string(tobject->ClassName()).find("TBranch") !=
1007  // std::string::npos) //== "TBranchElement")
1008  // objects = ((TBranchElement*)tobject)->GetListOfBranches();
1009 
1010  // if(objects != nullptr && !objects->IsEmpty())
1011  // {
1012  // __SUP_COUT__ << "Handling as TTree/TBranchElement directory" << __E__;
1013 
1014  // // treat like a directory, and return branches
1015  // TObject* obj;
1016  // TIter nextobj(objects->MakeIterator());
1017  // TRegexp re("*", kTRUE);
1018  // while((obj = (TObject*)nextobj()))
1019  // {
1020  // std::string name = obj->GetName();
1021  // TString s = name;
1022  // if(s.Index(re) == kNPOS)
1023  // continue;
1024 
1025  // __SUP_COUT__ << "Child class Name: " << obj->IsA()->GetName()
1026  // << " " << name << __E__;
1027 
1028  // if(std::string(obj->IsA()->GetName()).find("TBranch") !=
1029  // std::string::npos) // == "TBranchElement")
1030  // {
1031  // // decide if leave based on children branches
1032  // __SUP_COUT__
1033  // << "Child '" << name << "' of type '"
1034  // << ((TBranchElement*)obj)->GetTypeName() << "' isLeaf="
1035  // << ((TBranchElement*)obj)->GetListOfBranches()->IsEmpty()
1036  // << __E__;
1037 
1038  // xmlOut.addTextElementToData(
1039  // (((TBranchElement*)obj)->GetListOfBranches()->IsEmpty())
1040  // ? "file"
1041  // : "dir",
1042  // name);
1043  // }
1044  // else // handle normal way
1045  // {
1046  // xmlOut.addTextElementToData(
1047  // (std::string(obj->IsA()->GetName()).find("Directory") !=
1048  // std::string::npos ||
1049  // std::string(obj->IsA()->GetName()) == "TTree")
1050  // ? "dir"
1051  // : "file",
1052  // name);
1053  // }
1054  // }
1055  // theDataManager_->setDoNotStop(false);
1056  // return;
1057  // } // done handling TTree branches
1058  // } // end TTree and branch handling
1059  // else if(spliti < splitTTreePath.size())
1060  // {
1061  // __COUTV__(fullPathToObject);
1062  // // if more name to mystery object (likely TDirectoryFile), then attempt to
1063  // // get full subpath
1064  // tobject = (TObject*)rootFile->Get(fullPathToObject.c_str());
1065  // }
1066 
1067  // // at this point have tobject to stringify
1068  // } // peaking for TTree
1069 
1070  // if(directory == nullptr) // It MUST be an object to be serialized! tobject !=
1071  // // nullptr at this point.
1072  // {
1073  // __SUP_COUT__ << "This is not a directory!" << __E__;
1074 
1075  // if(tobject == nullptr)
1076  // {
1077  // __SUP_SS__
1078  // << "Something is wrong. Failed to access ROOT TObject at path: "
1079  // << fullPath << __E__;
1080  // __SUP_SS_THROW__;
1081  // }
1082 
1083  // // TObject* tobjectClone = nullptr;
1084 
1085  // if(tobject != nullptr) // turns out was a root object path
1086  // {
1087  // // ignore lock, because Lore says only crashed with Canvas
1088 
1089  // // FIXME -- check this new histo and gDirectory->Get for memory leak!
1090  // bool doJSONobject = false;
1091  // TH1F* h8 = nullptr;
1092  // std::string tmpClassName = tobject->ClassName();
1093  // if(tmpClassName.find("TBranch") != std::string::npos)
1094  // {
1095  // __COUT__ << "Attempting to plot '" << tobject->ClassName()
1096  // << "' type." << __E__;
1097 
1098  // h8 = new TH1F();
1099  // TTree* t3 = ((TBranch*)tobject)->GetTree();
1100  // //__COUT__ << "Attempting to plot '" << t3 << "' type." << __E__;
1101  // //__COUT__ << "JSON=" << TBufferJSON::ConvertToJSON(h8).Data() <<
1102  // //__E__;
1103  // t3->Draw("Value>>h8", "", "goff");
1104  // tobject = gDirectory->Get("h8");
1105 
1106  // __COUT__ << "Attempting to plot '" << tobject->ClassName()
1107  // << "' type." << __E__;
1108  // doJSONobject = true;
1109  // }
1110 
1111  // TString json;
1112  // TBufferFile tBuffer(TBuffer::kWrite);
1113  // if(theDataManager_ != nullptr &&
1114  // theDataManager_->getLiveDQMHistos() != nullptr && LDQM_pos == 0)
1115  // {
1116  // if(tobject->IsA() == TCanvas::Class())
1117  // {
1118  // static_cast<TCanvas*>(tobject)->Modified();
1119  // static_cast<TCanvas*>(tobject)->Update();
1120  // }
1121  // std::unique_lock<std::mutex> lock(
1122  // static_cast<DQMHistosConsumerBase*>(
1123  // theDataManager_->getLiveDQMHistos())
1124  // ->getFillHistoMutex());
1125  // json = TBufferJSON::ConvertToJSON(tobject);
1126  // tobject->Streamer(tBuffer);
1127  // }
1128  // else
1129  // {
1130  // // No need to lock from file!
1131  // json = TBufferJSON::ConvertToJSON(tobject);
1132  // tobject->Streamer(tBuffer);
1133  // }
1134 
1135  // std::string hexString = BinaryStringMacros::binaryStringToHexString(
1136  // tBuffer.Buffer(), tBuffer.Length());
1137 
1138  // __SUP_COUT__ << "Returning object '" << tobject->GetName()
1139  // << "' of class '" << tobject->ClassName() << __E__;
1140 
1141  // //__SUP_COUT__ << "Data: " << json.Data() << std::endl;
1142  // xmlOut.addTextElementToData("rootType",
1143  // doJSONobject ? "JSON" : tobject->ClassName());
1144  // xmlOut.addTextElementToData("rootData", hexString);
1145  // xmlOut.addTextElementToData("rootJSON", json.Data());
1146 
1147  // if(h8 != nullptr)
1148  // delete h8;
1149  // }
1150  // else
1151  // __SUP_COUT_ERR__ << "Failed to access:-" << fullPathToObject << "-"
1152  // << __E__;
1153  // STDLINE("Done with it!", ACBlue);
1154  // }
1155  // else // handle as directory
1156  // {
1157  // __SUP_COUT__ << "directory found getting the content!" << __E__;
1158  // STDLINE("Directory found getting the content!", ACGreen);
1159  // TRegexp re("*", kTRUE);
1160  // if(LDQM_pos == 0)
1161  // {
1162  // TObject* obj;
1163  // TIter nextobj(directory->GetList());
1164  // while((obj = (TObject*)nextobj()))
1165  // {
1166  // TString s = obj->GetName();
1167  // if(s.Index(re) == kNPOS)
1168  // continue;
1169  // __SUP_COUT__ << "Class Name: " << obj->IsA()->GetName() << __E__;
1170 
1171  // xmlOut.addTextElementToData(
1172  // (std::string(obj->IsA()->GetName()).find("Directory") !=
1173  // std::string::npos ||
1174  // std::string(obj->IsA()->GetName()) == "TTree" ||
1175  // std::string(obj->IsA()->GetName()).find("TBranch") !=
1176  // std::string::npos) // == "TBranchElement")
1177  // ? "dir"
1178  // : "file",
1179  // obj->GetName());
1180  // // ss.str("") ; ss << "obj->GetName(): " << obj->GetName() ;
1181  // // //STDLINE(ss.str(),"") ;
1182  // }
1183  // }
1184  // else
1185  // {
1186  // TKey* key;
1187  // TIter next(directory->GetListOfKeys());
1188  // while((key = (TKey*)next()))
1189  // {
1190  // TString s = key->GetName();
1191  // if(s.Index(re) == kNPOS)
1192  // continue;
1193  // __SUP_COUT__ << "Class Name: " << key->GetClassName() << __E__;
1194  // xmlOut.addTextElementToData(
1195  // (std::string(key->GetClassName()).find("Directory") !=
1196  // std::string::npos ||
1197  // std::string(key->GetClassName()) == "TTree" ||
1198  // std::string(key->GetClassName()).find("TBranch") !=
1199  // std::string::npos) // == "TBranchElement")
1200  // ? "dir"
1201  // : "file",
1202  // key->GetName());
1203  // // ss.str("") ; ss << "key->GetName(): " << key->GetName() ;
1204  // ////STDLINE(ss.str(),"") ;
1205  // }
1206  // }
1207  // }
1208  // if(LDQM_pos == std::string::npos)
1209  // rootFile->Close();
1210 
1211  // } // end getRoot handling
1212  else if(
1213  requestType ==
1214  "getEvents") // ################################################################################################################
1215  {
1216  if(theDataManager_ == nullptr)
1217  {
1218  __SS__ << "No Data Manager instantiated." << __E__;
1219  __SS_THROW__;
1220  }
1221 
1222  int Run = atoi(cgiIn("run").c_str());
1223 
1224  __SUP_COUT__ << "getEvents for run " << Run << __E__;
1225 
1226  if(Run != (int)loadedRunNumber_ || loadedRunNumber_ == (unsigned int)-1)
1227  {
1228  theDataManager_->load("Run1684.root", "Monicelli");
1229  loadedRunNumber_ = Run;
1230  }
1231 
1232  /*DOMElement* eventsParent =*/xmlOut.addTextElementToData("events", "");
1233  // DOMElement* eventParent;
1234  // char str[40];
1235 
1236  // const Visual3DEvents& events = theDataManager_->getVisual3DEvents();
1237  // __SUP_COUT__ << "Preparing hits xml" << __E__;
1238  // int numberOfEvents = 0;
1239  // for(Visual3DEvents::const_iterator it=events.begin(); it!=events.end() &&
1240  // numberOfEvents < 10000; it++, numberOfEvents++)
1241  // {
1242  // //__SUP_COUT__ << "Event: " << numberOfEvents << __E__;
1243  // eventParent = xmlOut.addTextElementToParent("event", str,
1244  // eventsParent); const VisualHits& hits = it->getHits();
1245  // for(VisualHits::const_iterator itHits=hits.begin();
1246  // itHits!=hits.end(); itHits++)
1247  // {
1248  // sprintf(str,"%f",itHits->x);
1249  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
1250  // sprintf(str,"%f",itHits->y);
1251  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
1252  // sprintf(str,"%f",itHits->z);
1253  // xmlOut.addTextElementToParent("xyz_point", str, eventParent);
1254  // //__SUP_COUT__ << "X: " << itHits->x << " Y: " << itHits->y << "
1255  // Z:
1256  //"
1257  //<< itHits->z << __E__;
1258  // }
1259  // const VisualTracks& tracks = it->getTracks();
1260  // for(VisualTracks::const_iterator itTrks=tracks.begin();
1261  // itTrks!=tracks.end(); itTrks++)
1262  // {
1263  // sprintf(str,"%f",itTrks->slopeX);
1264  // xmlOut.addTextElementToParent("slope", str, eventParent);
1265  // sprintf(str,"%f",itTrks->slopeY);
1266  // xmlOut.addTextElementToParent("slope", str, eventParent);
1267  // sprintf(str,"%f",itTrks->interceptX);
1268  // xmlOut.addTextElementToParent("intcpt", str, eventParent);
1269  // sprintf(str,"%f",itTrks->interceptY);
1270  // xmlOut.addTextElementToParent("intcpt", str, eventParent);
1271  //
1272  // }
1273  //
1274  // }
1275  __SUP_COUT__ << "Done hits xml" << __E__;
1276  }
1277  else if(
1278  requestType ==
1279  "getGeometry") // ################################################################################################################
1280  {
1281  __SUP_COUT__ << "getGeometry" << __E__;
1282 
1283  if(theDataManager_ == nullptr)
1284  {
1285  __SS__ << "No Data Manager instantiated." << __E__;
1286  __SS_THROW__;
1287  }
1288 
1289  // FIXME -- this crashes when the file doesn't exist!
1290  theDataManager_->load("Run1684.geo", "Geometry");
1291 
1292  __SUP_COUT__ << "getGeometry" << __E__;
1293 
1294  /*DOMElement* geometryParent =*/xmlOut.addTextElementToData("geometry", "");
1295  // const Visual3DShapes& shapes =
1296  // theDataManager_->getVisual3DGeometry().getShapes();
1297  //
1298  // __SUP_COUT__ << "getGeometry" << __E__;
1299  //
1300  //
1301  // DOMElement* objectParent;
1302  // char str[40];
1303  // for(Visual3DShapes::const_iterator itShapes=shapes.begin();
1304  // itShapes!=shapes.end(); itShapes++)
1305  // {
1306  // objectParent = xmlOut.addTextElementToParent("object", str,
1307  // geometryParent);
1308  // xmlOut.addTextElementToParent("object_type", "LINE_LOOP",
1309  // objectParent); sprintf(str,"%d",itShapes->numberOfRows);
1310  // xmlOut.addTextElementToParent("object_rows", str, objectParent);
1311  // sprintf(str,"%d",itShapes->numberOfColumns);
1312  // xmlOut.addTextElementToParent("object_columns", str, objectParent);
1313  // for(Points::const_iterator itCorners=itShapes->corners.begin();
1314  // itCorners!=itShapes->corners.end(); itCorners++)
1315  // {
1316  // sprintf(str,"%f",itCorners->x);
1317  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
1318  // sprintf(str,"%f",itCorners->y);
1319  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
1320  // sprintf(str,"%f",itCorners->z);
1321  // xmlOut.addTextElementToParent("xyz_point", str, objectParent);
1322  // }
1323  // }
1324  }
1325  else if(
1326  requestType ==
1327  "getRootConfig") // ################################################################################################################
1328  {
1329  std::string path = CgiDataUtilities::postData(cgiIn, "RootConfigPath");
1330  __SUP_COUT__ << "path " << path << __E__;
1331 
1332  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
1333  0) // ROOT config path must start the path
1334  {
1335  path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
1336  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2);
1337  __SUP_COUT__ << "mod path " << path << __E__;
1338  }
1339 
1340  HttpXmlDocument cfgXml;
1341  if(cfgXml.loadXmlDocument(path))
1342  {
1343  xmlOut.addTextElementToData("status", "1");
1344  xmlOut.copyDataChildren(cfgXml); // copy file to output xml
1345  cfgXml.saveXmlDocument(path);
1346  }
1347  else
1348  xmlOut.addTextElementToData("status",
1349  "Failed. File to properly load config file.");
1350  }
1351  else if(
1352  requestType ==
1353  "rootAdminControls") // ################################################################################################################
1354  {
1355  // if(userPermissions < ROOT_VIEWER_PERMISSIONS_THRESHOLD)
1356  // {
1357  // __SUP_COUT__ << "Insufficient permissions for Root Viewer Admin
1358  // Controls: " << userPermissions << " < " << ROOT_VIEWER_PERMISSIONS_THRESHOLD <<
1359  // __E__;
1360  // xmlOut.addTextElementToData("status", "Failed. Insufficient user
1361  // permissions.");
1362  // }
1363  // else
1364  // {
1365  std::string cmd = cgiIn("cmd"); // possible commands are
1366  // mkdir
1367  // save
1368  // delete
1369 
1370  std::string path = CgiDataUtilities::postData(cgiIn, "path");
1371  std::string name = CgiDataUtilities::postData(cgiIn, "name");
1372  __SUP_COUT__ << "cmd " << cmd << __E__;
1373  __SUP_COUT__ << "path " << path << __E__;
1374  __SUP_COUT__ << "name " << name << __E__;
1375 
1376  if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") ==
1377  0) // ROOT config path must start the path
1378  {
1379  path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" +
1380  path.substr(PRE_MADE_ROOT_CFG_DIR.length() + 2) + name;
1381  __SUP_COUT__ << "mod path " << path << __E__;
1382 
1383  if(cmd == "mkdir")
1384  {
1385  if(mkdir(path.c_str(),
1386  S_IRWXU | (S_IRGRP | S_IXGRP) |
1387  (S_IROTH | S_IXOTH))) // mode = drwx r-x r-x
1388  xmlOut.addTextElementToData("status",
1389  "Failed. Directory create rejected.");
1390  else
1391  xmlOut.addTextElementToData("status", "1"); // success
1392  }
1393  else if(cmd == "save")
1394  {
1395  path += PRE_MADE_ROOT_CFG_FILE_EXT; // add file extension
1396 
1397  bool useRunWildCard =
1398  atoi(CgiDataUtilities::postData(cgiIn, "useRunWildCard")
1399  .c_str()); // 0 or 1
1400  std::string config = CgiDataUtilities::postData(cgiIn, "config");
1401  __SUP_COUT__ << "config " << config << __E__;
1402  __SUP_COUT__ << "useRunWildCard " << useRunWildCard << __E__;
1403 
1404  // check if file already exists
1405  FILE* fp = fopen(path.c_str(), "r");
1406  if(fp)
1407  {
1408  fclose(fp);
1409  xmlOut.addTextElementToData("status", "Failed. File already exists.");
1410  __SUP_COUT__ << " Failed. File already exists." << __E__;
1411  }
1412  else
1413  {
1414  // dump to file
1415  // verify proper format through read back
1416  // if successfully loaded, re-save for formatting
1417 
1418  // dump to file
1419  fp = fopen(path.c_str(), "w");
1420  fputs(config.c_str(), fp);
1421  fclose(fp);
1422 
1423  // verify proper format through read back
1424  HttpXmlDocument cfgXml;
1425  if(cfgXml.loadXmlDocument(path))
1426  {
1427  // successfully loaded, re-save for formatting
1428  cfgXml.saveXmlDocument(path);
1429  xmlOut.addTextElementToData("status", "1"); // success
1430  }
1431  else // failed to load properly
1432  {
1433  xmlOut.addTextElementToData(
1434  "status", "Failed. Fatal. Improper file format.");
1435  if(remove(path.c_str()) != 0)
1436  __SUP_COUT__ << "Failed. Could not remove poorly formed Root "
1437  "config file!"
1438  << __E__;
1439  }
1440  }
1441  }
1442  else if(cmd == "delete")
1443  {
1444  // guess first directory and then file
1445  if(rmdir(path.c_str()) == 0 ||
1446  remove((path + PRE_MADE_ROOT_CFG_FILE_EXT).c_str()) == 0)
1447  xmlOut.addTextElementToData("status", "1"); // success
1448  else
1449  xmlOut.addTextElementToData("status",
1450  "Failed. Target could not be deleted.");
1451  }
1452  else
1453  xmlOut.addTextElementToData("status", "Failed. Unrecognized command.");
1454  }
1455  else
1456  xmlOut.addTextElementToData("status", "Failed. Invalid path.");
1457 
1458  //}
1459  }
1460  else if(
1461  requestType ==
1462  "getMeDirs") // ################################################################################################################
1463  {
1464  xmlOut.setDarioStyle(true); // workaround for XML formatting....
1465  std::string fSystemPath = std::string(ROOT_BROWSER_PATH) + "/";
1466  std::string fRootPath = CgiDataUtilities::postData(cgiIn, "Path");
1467  boost::regex re("%2F");
1468  fRootPath = boost::regex_replace(fRootPath, re, "/");
1469  std::string fullPath = fSystemPath + fRootPath;
1470  // fFoldersPath_ = "pippo" ;
1471  STDLINE(std::string("Begin: fSystemPath = ") + fSystemPath, ACWhite);
1472  STDLINE(std::string("Begin: fRootPath = ") + fRootPath, ACWhite);
1473  STDLINE(std::string("Begin: fullPath = ") + fullPath, ACWhite);
1474  // STDLINE(std::string("Begin: fFoldersPath = ")+fFoldersPath_,ACCyan ) ;
1475 
1476  xmlOut.setRootPath(fRootPath);
1477  xmlOut.makeDirectoryBinaryTree(fSystemPath, fRootPath, 0, NULL);
1478  std::ostringstream* out = new std::ostringstream();
1479  xmlOut.outputXmlDocument((std::ostringstream*)out, true);
1480  }
1481  else if(
1482  requestType ==
1483  "getMeRootFile") // ################################################################################################################
1484  {
1485  xmlOut.setDarioStyle(true); // workaround for XML formatting....
1486  std::string fSystemPath = std::string(ROOT_BROWSER_PATH) + "/";
1487  std::string fRootPath = CgiDataUtilities::postData(cgiIn, "fRootPath");
1488  std::string fFoldersPath = CgiDataUtilities::postData(cgiIn, "fFoldersPath");
1489  std::string fHistName = CgiDataUtilities::postData(cgiIn, "fHistName");
1490  std::string fRFoldersPath = CgiDataUtilities::postData(cgiIn, "fRFoldersPath");
1491  std::string fFileName = CgiDataUtilities::postData(cgiIn, "fFileName");
1492  boost::regex re("%2F");
1493  fRootPath = boost::regex_replace(fRootPath, re, "/");
1494  fFoldersPath = boost::regex_replace(fFoldersPath, re, "/");
1495  // STDLINE(std::string("fSystemPath : ")+fSystemPath ,ACCyan);
1496  // STDLINE(std::string("fRootPath : ")+fRootPath ,ACCyan);
1497  // STDLINE(std::string("fFoldersPath : ")+fFoldersPath ,ACCyan);
1498  // STDLINE(std::string("fHistName : ")+fHistName ,ACCyan);
1499  // STDLINE(std::string("fRFoldersPath: ")+fRFoldersPath,ACCyan);
1500  // STDLINE(std::string("fFileName : ")+fFileName ,ACCyan);
1501  RootFileExplorer* theExplorer = new RootFileExplorer(
1502  fSystemPath, fRootPath, fFoldersPath, fHistName, fRFoldersPath, fFileName);
1503  xmlOut.setDocument(theExplorer->initialize(false));
1504  // std::ostringstream* out ;
1505  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
1506  }
1507  // else if(
1508  // requestType ==
1509  // "getMeLIVE-DQMFile")
1510  // //################################################################################################################
1511  // {
1512  // xmlOut.setDarioStyle(true); // workaround for XML formatting....
1513  // std::string fSystemPath = std::string(ROOT_BROWSER_PATH) + "/";
1514  // std::string fRootPath = CgiDataUtilities::postData(cgiIn, "fRootPath");
1515  // std::string fFoldersPath = CgiDataUtilities::postData(cgiIn, "fFoldersPath");
1516  // std::string fHistName = CgiDataUtilities::postData(cgiIn, "fHistName");
1517  // std::string fRFoldersPath = CgiDataUtilities::postData(cgiIn, "fRFoldersPath");
1518  // std::string fFileName = CgiDataUtilities::postData(cgiIn, "fFileName");
1519  // STDLINE(std::string("fSystemPath : ") + fSystemPath, ACCyan);
1520  // STDLINE(std::string("fRootPath : ") + fRootPath, ACCyan);
1521  // STDLINE(std::string("fFoldersPath : ") + fFoldersPath, ACCyan);
1522  // STDLINE(std::string("fHistName : ") + fHistName, ACCyan);
1523  // STDLINE(std::string("fRFoldersPath: ") + fRFoldersPath, ACCyan);
1524  // STDLINE(std::string("fFileName : ") + fFileName, ACCyan);
1525  // boost::regex re("%2F");
1526  // fRootPath = boost::regex_replace(fRootPath, re, "/");
1527  // fFoldersPath = boost::regex_replace(fFoldersPath, re, "/");
1528 
1529  // TFile* rootFile;
1530  // STDLINE("Getting LiveDQMHistos", ACGreen);
1531  // if(theDataManager_->getLiveDQMHistos() != nullptr)
1532  // {
1533  // STDLINE("Selecting LIVE_DQM.root", ACCyan);
1534  // rootFile = theDataManager_->getLiveDQMHistos()->getFile();
1535  // fRootPath = "LIVE_DQM.root";
1536  // }
1537  // else
1538  // {
1539  // STDLINE(string("fRootPath: ") + fRootPath, ACGreen);
1540  // rootFile = TFile::Open(fRootPath.c_str());
1541  // }
1542  // string cmd = string("ls -la ") + fRootPath;
1543  // system(cmd.c_str());
1544  // // STDLINE(string("before regexp fRootPath: ")+fRootPath,ACGreen) ;
1545  // // fRootPath = rootFile->GetName() ; // Bisogna strippare via il full path!!!
1546  // // boost::regex regg(fSystemPath.c_str()) ;
1547  // // fRootPath = boost::regex_replace(fRootPath,regg,"/") ; // Dario: should be
1548  // // transparent for Ryan's purposes but required by Extjs STDLINE(string("after
1549  // // regexp fRootPath: ")+fRootPath,ACGreen) ;
1550  // STDLINE(std::string("fSystemPath : ") + fSystemPath, ACCyan);
1551  // STDLINE(std::string("fRootPath : ") + fRootPath, ACCyan);
1552  // STDLINE(std::string("fFoldersPath : ") + fFoldersPath, ACCyan);
1553  // STDLINE(std::string("fHistName : ") + fHistName, ACCyan);
1554  // STDLINE(std::string("fRFoldersPath: ") + fRFoldersPath, ACCyan);
1555  // STDLINE(std::string("fFileName : ") + fFileName, ACCyan);
1556  // RootFileExplorer* theExplorer = new RootFileExplorer(fSystemPath,
1557  // fRootPath,
1558  // fFoldersPath,
1559  // fHistName,
1560  // fRFoldersPath,
1561  // fFileName,
1562  // rootFile);
1563  // xmlOut.setDocument(theExplorer->initialize(true));
1564  // // std::ostringstream* out ;
1565  // // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
1566  // }
1567  else if(
1568  requestType ==
1569  "saveConfiguration") // ################################################################################################################
1570  {
1571  std::string configPayload = CgiDataUtilities::postData(cgiIn, "configPayload");
1572  STDLINE("configPayload: ", ACRed);
1573  STDLINE(configPayload, ACYellow);
1574 
1575  fstream outFile;
1576  outFile.open("/tmp/configPayload.json", ios::out | ios::app);
1577  outFile << configPayload << endl;
1578  outFile.close();
1579  }
1580  else if(
1581  requestType ==
1582  "getConfiguration") // ################################################################################################################
1583  {
1584  std::string configPayload = CgiDataUtilities::postData(cgiIn, "configPayload");
1585  std::string JSONPayLoad = "";
1586  std::string line = "";
1587 
1588  ifstream JSONFile("/tmp/configPayload.json");
1589 
1590  if(JSONFile.is_open())
1591  {
1592  while(getline(JSONFile, line))
1593  {
1594  JSONPayLoad += line;
1595  }
1596  JSONFile.close();
1597  }
1598 
1599  xmlOut.addTextElementToData("JSONPayLoad", JSONPayLoad);
1600  // std::ostringstream* out ;
1601  // xmlOut.outputXmlDocument((std::ostringstream*) out, true);
1602  }
1603  else if(
1604  requestType ==
1605  "getState") // ################################################################################################################
1606  {
1607  std::string fsmName = theStateMachine_.getCurrentStateName();
1608  bool in_transition = theStateMachine_.isInTransition();
1609 
1610  xmlOut.addTextElementToData("current_state", fsmName);
1611  xmlOut.addTextElementToData("in_transition", in_transition ? "1" : "0");
1612  }
1613  else
1614  {
1615  __SUP_SS__ << "requestType Request, " << requestType
1616  << ", not recognized by the Visual Supervisor (was it intended for "
1617  "another Supervisor?)."
1618  << __E__;
1619  __SUP_SS_THROW__;
1620  }
1621 
1622  if(theDataManager_ != nullptr)
1623  theDataManager_->setDoNotStop(false);
1624 
1625 } //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="")