00001 #include "otsdaq-utilities/Visualization/VisualSupervisor.h"
00002
00003 #include "otsdaq-core/DataManager/DataManagerSingleton.h"
00004 #include "otsdaq-core/Macros/BinaryStringMacros.h"
00005
00006
00007
00008
00009
00010 #include "TBufferFile.h"
00011 #include "TObject.h"
00012 #include <TH1.h>
00013 #include <TH2.h>
00014 #include <TProfile.h>
00015 #include <TCanvas.h>
00016 #include <TBuffer.h>
00017 #include <TDirectory.h>
00018 #include <TFile.h>
00019 #include <TROOT.h>
00020 #include <TKey.h>
00021 #include <TRegexp.h>
00022 #include <TIterator.h>
00023 #include <TString.h>
00024 #include <TClass.h>
00025 #include <TBufferJSON.h>
00026
00027
00028 #include <dirent.h>
00029 #include <sys/stat.h>
00030
00031 #include <xdaq/NamespaceURI.h>
00032
00033 #include <iostream>
00034
00035
00036 #define ROOT_BROWSER_PATH getenv("ROOT_BROWSER_PATH")
00037 #define ROOT_DISPLAY_CONFIG_PATH getenv("ROOT_DISPLAY_CONFIG_PATH")
00038
00039 #define LIVEDQM_DIR std::string("LIVE_DQM")
00040 #define PRE_MADE_ROOT_CFG_DIR std::string("Pre-made Views")
00041
00042 #define PRE_MADE_ROOT_CFG_FILE_EXT std::string(".rcfg")
00043
00044 #define PREFERENCES_PATH std::string(getenv("SERVICE_DATA_PATH")) + "/VisualizerData/"
00045 #define PREFERENCES_FILE_EXT ".pref"
00046
00047 #define ROOT_VIEWER_PERMISSIONS_THRESHOLD 100
00048
00049 using namespace ots;
00050
00051 #undef __MF_SUBJECT__
00052 #define __MF_SUBJECT__ "Visualizer"
00053
00054
00055
00056 XDAQ_INSTANTIATOR_IMPL(VisualSupervisor)
00057
00058
00059 VisualSupervisor::VisualSupervisor(xdaq::ApplicationStub* stub)
00060 : CoreSupervisorBase (stub)
00061 , theDataManager_ (0)
00062 , loadedRunNumber_ (-1)
00063 {
00064 INIT_MF("VisualSupervisor");
00065 __SUP_COUT__ << std::endl;
00066
00067 theDataManager_ = DataManagerSingleton::getInstance<VisualDataManager>
00068 (
00069 theConfigurationManager_->getNode(theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getConfigurationName()),
00070 supervisorConfigurationPath_,
00071 supervisorApplicationUID_
00072 );
00073
00074 CoreSupervisorBase::theStateMachineImplementation_.push_back(theDataManager_);
00075
00076 __SUP_COUT__ << "Done instantiating Visual data manager." << std::endl;
00077
00078
00079
00080
00081
00082 mkdir(((std::string)PREFERENCES_PATH).c_str(), 0755);
00083 }
00084
00085
00086 VisualSupervisor::~VisualSupervisor(void)
00087 {
00088 destroy();
00089 }
00090
00091
00092 void VisualSupervisor::destroy(void)
00093 {
00094
00095
00096
00097 DataManagerSingleton::deleteInstance(CorePropertySupervisorBase::supervisorApplicationUID_);
00098 theStateMachineImplementation_.pop_back();
00099 }
00100
00102
00103
00104
00105
00106
00107
00108
00109
00110
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 void VisualSupervisor::setSupervisorPropertyDefaults()
00122 {
00123 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AllowNoLoginRequestTypes,
00124 "setUserPreferences | getUserPreferences | getDirectoryContents | getRoot | getEvents");
00125
00126 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold,
00127 "*=1 | rootAdminControls=100");
00128 }
00129
00130
00131
00132
00133
00134 void VisualSupervisor::forceSupervisorPropertyValues()
00135 {
00136 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes,
00137 "getRoot | getEvents");
00138 CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NoXmlWhiteSpaceRequestTypes,
00139 "getRoot | getEvents");
00140
00141
00142 }
00143
00144
00145 void VisualSupervisor::request(const std::string& requestType, cgicc::Cgicc& cgiIn,
00146 HttpXmlDocument& xmlOut, const WebUsers::RequestUserInfo& userInfo)
00147 {
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 if(requestType == "getRawData")
00172 {
00173 __SUP_COUT__ << __E__;
00174 try{
00175
00176 __SUP_COUT__ << "Getting Raw data and converting to binary string" << __E__;
00177 xmlOut.addBinaryStringToData("rawData",
00178 theDataManager_->getRawData());
00179 __SUP_COUT__ << __E__;
00180 }
00181 catch(std::exception const& e){
00182 __SUP_COUT__ << "ERROR! Exception while getting raw data. Incoming exception data..." << __E__;
00183 __SUP_COUT__ << e.what() << __E__;
00184 __SUP_COUT__ << "End Exception Data" << __E__;
00185
00186 }
00187 catch(...){
00188 __SUP_COUT__ << "ERROR! Something went wrong trying to get raw data." << __E__;
00189 __SUP_COUT_INFO__ << "ERROR! Something went wrong trying to get raw data." << __E__;
00190 }
00191 }
00192 else if (requestType == "setUserPreferences" && userInfo.username_ != "" )
00193 {
00194 __SUP_COUT__ << "userInfo.username_: " << userInfo.username_ << std::endl;
00195 std::string fullPath = (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
00196 __SUP_COUT__ << "fullPath: " << fullPath << std::endl;
00197
00198 std::string radioSelect = CgiDataUtilities::getData(cgiIn,"radioSelect");
00199 std::string autoRefresh = CgiDataUtilities::getData(cgiIn,"autoRefresh");
00200 std::string autoHide = CgiDataUtilities::getData(cgiIn,"autoHide");
00201 std::string hardRefresh = CgiDataUtilities::getData(cgiIn,"hardRefresh");
00202 std::string autoRefreshPeriod = CgiDataUtilities::getData(cgiIn,"autoRefreshPeriod");
00203
00204 __SUP_COUT__ << "radioSelect: " << radioSelect << std::endl;
00205 __SUP_COUT__ << "autoRefresh: " << autoRefresh << std::endl;
00206 __SUP_COUT__ << "autoHide: " << autoHide << std::endl;
00207 __SUP_COUT__ << "hardRefresh: " << hardRefresh << std::endl;
00208 __SUP_COUT__ << "autoRefreshPeriod: " << autoRefreshPeriod << std::endl;
00209
00210
00211
00212 FILE *fp = fopen(fullPath.c_str(),"r");
00213 if(fp)
00214 {
00215 char line[100];
00216 char val[100];
00217
00218 fgets(line,100,fp);
00219 sscanf(line,"%*s %s",val);
00220 if(radioSelect == "")
00221 radioSelect = val;
00222
00223 fgets(line,100,fp);
00224 sscanf(line,"%*s %s",val);
00225 if(autoRefresh == "")
00226 autoRefresh = val;
00227
00228 fgets(line,100,fp);
00229 sscanf(line,"%*s %s",val);
00230 if(autoHide == "")
00231 autoHide = val;
00232
00233 fgets(line,100,fp);
00234 sscanf(line,"%*s %s",val);
00235 if(hardRefresh == "")
00236 hardRefresh = val;
00237
00238 fgets(line,100,fp);
00239 sscanf(line,"%*s %s",val);
00240 if(autoRefreshPeriod == "")
00241 autoRefreshPeriod = val;
00242
00243 fclose(fp);
00244 }
00245
00246
00247 fp = fopen(fullPath.c_str(),"w");
00248 if(fp)
00249 {
00250 fprintf(fp,"radioSelect %s\n",radioSelect.c_str());
00251 fprintf(fp,"autoRefresh %s\n",autoRefresh.c_str());
00252 fprintf(fp,"autoHide %s\n",autoHide.c_str());
00253 fprintf(fp,"hardRefresh %s\n",hardRefresh.c_str());
00254 fprintf(fp,"autoRefreshPeriod %s\n",autoRefreshPeriod.c_str());
00255 fclose(fp);
00256 }
00257 else
00258 __SUP_COUT_ERR__ << "Failure writing preferences to file: " << fullPath << std::endl;
00259 }
00260 else if (requestType == "getUserPreferences")
00261 {
00262 __SUP_COUT__ << "userInfo.username_: " << userInfo.username_ << std::endl;
00263 std::string fullPath = (std::string)PREFERENCES_PATH + userInfo.username_ + PREFERENCES_FILE_EXT;
00264 __SUP_COUT__ << "fullPath: " << fullPath << std::endl;
00265
00266 FILE *fp = fopen(fullPath.c_str(),"r");
00267 if(fp)
00268 {
00269 char line[100];
00270
00271 int val;
00272
00273 fgets(line,100,fp);
00274 sscanf(line,"%*s %d",&val);
00275 if(val < 0 || val > 3) val = 0;
00276 xmlOut.addTextElementToData("radioSelect", std::to_string(val));
00277 fgets(line,100,fp);
00278 sscanf(line,"%*s %d",&val);
00279 xmlOut.addTextElementToData("autoRefresh", std::to_string(val));
00280 fgets(line,100,fp);
00281 sscanf(line,"%*s %d",&val);
00282 xmlOut.addTextElementToData("autoHide", std::to_string(val));
00283 fgets(line,100,fp);
00284 sscanf(line,"%*s %d",&val);
00285 xmlOut.addTextElementToData("hardRefresh", std::to_string(val));
00286 fgets(line,100,fp);
00287 sscanf(line,"%*s %d",&val);
00288 xmlOut.addTextElementToData("autoRefreshPeriod", std::to_string(val));
00289 fclose(fp);
00290 }
00291 else
00292 {
00293
00294 xmlOut.addTextElementToData("radioSelect", "");
00295 xmlOut.addTextElementToData("autoRefresh", "");
00296 xmlOut.addTextElementToData("autoHide", "");
00297 xmlOut.addTextElementToData("hardRefresh", "");
00298 xmlOut.addTextElementToData("autoRefreshPeriod", "");
00299 }
00300 }
00301 else if (requestType == "getDirectoryContents")
00302 {
00303
00304
00305 std::string rootpath = std::string(ROOT_BROWSER_PATH) + "/";
00306 std::string path = CgiDataUtilities::postData(cgiIn,"Path");
00307 __SUP_COUT__ << path << std::endl;
00308
00309
00310
00311 char permStr[10];
00312 sprintf(permStr,"%d",
00313 userInfo.permissionLevel_ >=
00314 CoreSupervisorBase::getSupervisorPropertyUserPermissionsThreshold("rootAdminControls")
00315 );
00316 xmlOut.addTextElementToData("permissions", permStr);
00317
00318 std::string dirpath = rootpath + path;
00319 if(path == "/" + PRE_MADE_ROOT_CFG_DIR + "/")
00320 dirpath = ROOT_DISPLAY_CONFIG_PATH;
00321
00322 if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") == 0)
00323 dirpath = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" + path.substr(PRE_MADE_ROOT_CFG_DIR.length()+2);
00324
00325 __SUP_COUT__ << "full path: " << dirpath << std::endl;
00326
00327 DIR *pDIR;
00328 struct dirent *entry;
00329 bool isNotRtCfg;
00330 bool isDir;
00331 if( (pDIR=opendir(dirpath.c_str())) )
00332 {
00333 xmlOut.addTextElementToData("path", path);
00334
00335
00336
00337 if(path == "/")
00338 {
00339
00340 if(theDataManager_->getLiveDQMHistos() != 0)
00341 xmlOut.addTextElementToData("dir", LIVEDQM_DIR + ".root");
00342
00343
00344 DIR *pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH);
00345 bool recheck = false;
00346 if(!pRtDIR)
00347 {
00348 recheck = true;
00349 if(mkdir(ROOT_DISPLAY_CONFIG_PATH, S_IRWXU | (S_IRGRP | S_IXGRP) | (S_IROTH | S_IXOTH)))
00350 __SUP_COUT__ << "Failed to make directory for pre made views: " << ROOT_DISPLAY_CONFIG_PATH << std::endl;
00351 }
00352 else
00353 closedir(pRtDIR);
00354
00355 if(!recheck || (pRtDIR = opendir(ROOT_DISPLAY_CONFIG_PATH)))
00356 {
00357 xmlOut.addTextElementToData("dir", PRE_MADE_ROOT_CFG_DIR);
00358 if(recheck)
00359 closedir(pRtDIR);
00360 }
00361 }
00362
00363 while((entry = readdir(pDIR)))
00364 {
00365
00366 if( entry->d_name[0] != '.' && (entry->d_type == 0 ||
00367 entry->d_type == 4 || entry->d_type == 8))
00368 {
00369
00370 isNotRtCfg = std::string(entry->d_name).find(".rcfg") == std::string::npos;
00371 isDir = false;
00372
00373 if(entry->d_type == 0)
00374 {
00375
00376 DIR *pTmpDIR = opendir((dirpath + entry->d_name).c_str());
00377 if(pTmpDIR)
00378 {
00379 isDir = true;
00380 closedir(pTmpDIR);
00381 }
00382
00383 }
00384
00385 if((entry->d_type == 8 || (!isDir && entry->d_type == 0))
00386 && std::string(entry->d_name).find(".root") == std::string::npos
00387 && isNotRtCfg)
00388 continue;
00389 else if(entry->d_type == 4)
00390 isDir = true;
00391
00392
00393 xmlOut.addTextElementToData(isDir?"dir":
00394 (isNotRtCfg?"dir":"file"),
00395 entry->d_name);
00396 }
00397 }
00398 closedir(pDIR);
00399 }
00400 else
00401 __SUP_COUT__ << "Failed to access directory contents!" << std::endl;
00402 }
00403 else if (requestType == "getRoot")
00404 {
00405
00406
00407 std::string path = CgiDataUtilities::postData(cgiIn,"RootPath");
00408 std::string fullPath = std::string(getenv("ROOT_BROWSER_PATH")) + path;
00409
00410
00411
00412 std::string rootFileName = fullPath.substr(0,fullPath.find(".root")+5);
00413 std::string rootDirectoryName = rootFileName + ":" + fullPath.substr(fullPath.find(".root")+5,fullPath.size()-fullPath.find(".root")+5+1);
00414
00415 std::string::size_type LDQM_pos = path.find("/" + LIVEDQM_DIR + ".root/");
00416 TFile* rootFile;
00417
00418 if(theDataManager_->getLiveDQMHistos() != nullptr && LDQM_pos == 0)
00419 {
00420
00421 rootFile = theDataManager_->getLiveDQMHistos()->getFile();
00422 if(!rootFile)
00423 __SUP_COUT__ << "File was closed." << std::endl;
00424 else
00425 {
00426
00427 rootDirectoryName = path.substr(("/" + LIVEDQM_DIR + ".root").length());
00428 }
00429 }
00430 else
00431 rootFile = TFile::Open(rootFileName.c_str());
00432
00433
00434
00435 if(!rootFile || !rootFile->IsOpen())
00436 {
00437 __SUP_COUT__ << "Failed to access root file: " << rootFileName << std::endl;
00438 }
00439 else
00440 {
00441 xmlOut.addTextElementToData("path", path);
00442
00443 TDirectory* directory;
00444 if((directory = rootFile->GetDirectory(rootDirectoryName.c_str())) == 0)
00445 {
00446
00447 directory = rootFile;
00448
00449
00450
00451 TObject* histoClone = nullptr;
00452 TObject* histo = (TObject*)rootFile->Get(rootDirectoryName.c_str());
00453
00454 if(histo != nullptr)
00455 {
00456
00457 histoClone = histo->Clone();
00458 TString json = TBufferJSON::ConvertToJSON(histoClone);
00459 TBufferFile tBuffer(TBuffer::kWrite);
00460 histoClone->Streamer(tBuffer);
00461
00462
00463
00464 std::string destination =
00465 BinaryStringMacros::binaryToHexString(tBuffer.Buffer(), tBuffer.Length());
00466
00467 xmlOut.addTextElementToData("rootType", histoClone->ClassName());
00468 xmlOut.addTextElementToData("rootData", destination);
00469 xmlOut.addTextElementToData("rootJSON", json.Data());
00470 delete histoClone;
00471 }
00472 else
00473 __SUP_COUT_ERR__ << "Failed to access:-" << rootDirectoryName << "-" << std::endl;
00474
00475 }
00476 else
00477 {
00478 __SUP_COUT__ << "directory found getting the content!" << std::endl;
00479 TRegexp re("*", kTRUE);
00480 if (LDQM_pos == 0)
00481 {
00482 TObject *obj;
00483 TIter nextobj(directory->GetList());
00484 while ((obj = (TObject *) nextobj()))
00485 {
00486 TString s = obj->GetName();
00487 if (s.Index(re) == kNPOS)
00488 continue;
00489 __SUP_COUT__ << "Class Name: " << obj->IsA()->GetName() << std::endl;
00490 xmlOut.addTextElementToData((std::string(obj->IsA()->GetName()).find("Directory") != std::string::npos)?"dir":"file", obj->GetName());
00491 }
00492 }
00493 else
00494 {
00495
00496 TKey *key;
00497 TIter next(directory->GetListOfKeys());
00498 while ((key = (TKey *) next()))
00499 {
00500 TString s = key->GetName();
00501 if (s.Index(re) == kNPOS)
00502 continue;
00503 __SUP_COUT__ << "Class Name: " << key->GetClassName() << std::endl;
00504 xmlOut.addTextElementToData((std::string(key->GetClassName()).find("Directory") != std::string::npos)?"dir":"file", key->GetName());
00505 }
00506 }
00507 }
00508 if(LDQM_pos == std::string::npos)
00509 rootFile->Close();
00510 }
00511 }
00512 else if (requestType == "getEvents")
00513 {
00514 int Run = atoi(cgiIn("run").c_str());
00515
00516 __SUP_COUT__ << "getEvents for run " << Run << std::endl;
00517
00518 if(Run != (int)loadedRunNumber_ || loadedRunNumber_ == (unsigned int)-1)
00519 {
00520 theDataManager_->load("Run1684.root","Monicelli");
00521 loadedRunNumber_ = Run;
00522 }
00523
00524 DOMElement* eventsParent = xmlOut.addTextElementToData("events", "");
00525 DOMElement* eventParent;
00526 char str[40];
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 __SUP_COUT__ << "Done hits xml" << std::endl;
00562 }
00563 else if (requestType == "getGeometry")
00564 {
00565 __SUP_COUT__ << "getGeometry" << std::endl;
00566
00567
00568 theDataManager_->load("Run1684.geo","Geometry");
00569
00570 __SUP_COUT__ << "getGeometry" << std::endl;
00571
00572 DOMElement* geometryParent = xmlOut.addTextElementToData("geometry", "");
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 }
00599 else if (requestType == "getRootConfig")
00600 {
00601 std::string path = CgiDataUtilities::postData(cgiIn,"RootConfigPath");
00602 __SUP_COUT__ << "path " << path << std::endl;
00603
00604 if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") == 0)
00605 {
00606 path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" + path.substr(PRE_MADE_ROOT_CFG_DIR.length()+2);
00607 __SUP_COUT__ << "mod path " << path << std::endl;
00608 }
00609
00610 HttpXmlDocument cfgXml;
00611 if(cfgXml.loadXmlDocument(path))
00612 {
00613 xmlOut.addTextElementToData("status", "1");
00614 xmlOut.copyDataChildren(cfgXml);
00615 cfgXml.saveXmlDocument(path);
00616 }
00617 else
00618 xmlOut.addTextElementToData("status", "Failed. File to properly load config file.");
00619 }
00620 else if (requestType == "rootAdminControls")
00621 {
00622
00623
00624
00625
00626
00627
00628
00629 std::string cmd = cgiIn("cmd");
00630
00631
00632
00633
00634 std::string path = CgiDataUtilities::postData(cgiIn,"path");
00635 std::string name = CgiDataUtilities::postData(cgiIn,"name");
00636 __SUP_COUT__ << "cmd " << cmd << std::endl;
00637 __SUP_COUT__ << "path " << path << std::endl;
00638 __SUP_COUT__ << "name " << name << std::endl;
00639
00640 if(path.find("/" + PRE_MADE_ROOT_CFG_DIR + "/") == 0)
00641 {
00642 path = std::string(ROOT_DISPLAY_CONFIG_PATH) + "/" + path.substr(PRE_MADE_ROOT_CFG_DIR.length()+2) + name;
00643 __SUP_COUT__ << "mod path " << path << std::endl;
00644
00645
00646 if(cmd == "mkdir")
00647 {
00648 if(mkdir(path.c_str(), S_IRWXU | (S_IRGRP | S_IXGRP) | (S_IROTH | S_IXOTH)))
00649 xmlOut.addTextElementToData("status", "Failed. Directory create rejected.");
00650 else
00651 xmlOut.addTextElementToData("status", "1");
00652 }
00653 else if(cmd == "save")
00654 {
00655 path += PRE_MADE_ROOT_CFG_FILE_EXT;
00656
00657 bool useRunWildCard = atoi(CgiDataUtilities::postData(cgiIn,"useRunWildCard").c_str());
00658 std::string config = CgiDataUtilities::postData(cgiIn,"config");
00659 __SUP_COUT__ << "config " << config << std::endl;
00660 __SUP_COUT__ << "useRunWildCard " << useRunWildCard << std::endl;
00661
00662
00663 FILE *fp = fopen(path.c_str(),"r");
00664 if(fp)
00665 {
00666 fclose(fp);
00667 xmlOut.addTextElementToData("status", "Failed. File already exists.");
00668 __SUP_COUT__ << " Failed. File already exists." << std::endl;
00669 }
00670 else
00671 {
00672
00673
00674
00675
00676
00677 fp = fopen(path.c_str(),"w");
00678 fputs(config.c_str(),fp);
00679 fclose(fp);
00680
00681
00682 HttpXmlDocument cfgXml;
00683 if(cfgXml.loadXmlDocument(path))
00684 {
00685
00686 cfgXml.saveXmlDocument(path);
00687 xmlOut.addTextElementToData("status", "1");
00688 }
00689 else
00690 {
00691 xmlOut.addTextElementToData("status", "Failed. Fatal. Improper file format.");
00692 if(remove(path.c_str()) != 0)
00693 __SUP_COUT__ << "Failed. Could not remove poorly formed Root config file!" << std::endl;
00694 }
00695 }
00696
00697 }
00698 else if(cmd == "delete")
00699 {
00700
00701 if (rmdir(path.c_str()) == 0 || remove((path+PRE_MADE_ROOT_CFG_FILE_EXT).c_str()) == 0 )
00702 xmlOut.addTextElementToData("status", "1");
00703 else
00704 xmlOut.addTextElementToData("status", "Failed. Target could not be deleted.");
00705 }
00706 else
00707 xmlOut.addTextElementToData("status", "Failed. Unrecognized command.");
00708 }
00709 else
00710 xmlOut.addTextElementToData("status", "Failed. Invalid path.");
00711
00712
00713
00714 }
00715 else
00716 __SUP_COUT__ << "requestType request, " << requestType << ", not recognized." << std::endl;
00717
00718
00719 }
00720