Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:20:55

0001 #include "OnlMonClient.h"
0002 #include "ClientHistoList.h"
0003 #include "OnlMonDraw.h"
0004 #include "OnlMonHtml.h"
0005 
0006 #include <onlmon/HistoBinDefs.h>
0007 #include <onlmon/OnlMonBase.h>  // for OnlMonBase
0008 #include <onlmon/OnlMonDefs.h>
0009 
0010 #include <MessageTypes.h>  // for kMESS_STRING, kMESS_OBJECT
0011 #include <TCanvas.h>
0012 #include <TDirectory.h>
0013 #include <TFile.h>
0014 #include <TGClient.h>  // for gClient, TGClient
0015 #include <TGFrame.h>
0016 #include <TH1.h>
0017 #include <TImage.h>
0018 #include <TIterator.h>
0019 #include <TList.h>  // for TList
0020 #include <TMessage.h>
0021 #include <TROOT.h>
0022 #include <TSeqCollection.h>
0023 #include <TSocket.h>
0024 #include <TStyle.h>
0025 #include <TSystem.h>
0026 
0027 #include <odbc++/connection.h>
0028 #include <odbc++/drivermanager.h>
0029 #include <odbc++/resultset.h>
0030 #include <odbc++/statement.h>  // for Statement
0031 #include <odbc++/types.h>      // for SQLException
0032 
0033 #include <sys/stat.h>
0034 #include <sys/utsname.h>
0035 #include <unistd.h>
0036 #include <uuid/uuid.h>
0037 #include <algorithm>
0038 #include <cstdio>   // for printf, remove
0039 #include <cstdlib>  // for getenv, exit
0040 #include <cstring>  // for strcmp
0041 #include <filesystem>
0042 #include <fstream>
0043 #include <iostream>
0044 #include <list>
0045 #include <sstream>
0046 #include <utility>  // for pair
0047 
0048 OnlMonClient *OnlMonClient::__instance = nullptr;
0049 
0050 int pinit()
0051 {
0052   return 0;
0053 }
0054 
0055 OnlMonClient *OnlMonClient::instance()
0056 {
0057   if (__instance)
0058   {
0059     return __instance;
0060   }
0061   __instance = new OnlMonClient("ONLMONCLIENT");
0062   return __instance;
0063 }
0064 
0065 OnlMonClient::OnlMonClient(const std::string &name)
0066   : OnlMonBase(name)
0067 {
0068   defaultStyle = new TStyle();
0069   SetStyleToDefault();
0070   InitAll();
0071 }
0072 
0073 void OnlMonClient::InitAll()
0074 {
0075   if (gROOT->FindObject("ServerRunning"))
0076   {
0077     std::cout << "Don't run Server and Client in same session, exiting" << std::endl;
0078     exit(1);
0079   }
0080   if (!gClient)  // cannot draw on display, warn and bail out
0081   {
0082     const char *env_display = getenv("DISPLAY");
0083     if (env_display)
0084     {
0085       std::string displaystring = env_display;
0086       std::cout << "Cannot open Display, Display Env Var is set to "
0087                 << displaystring << std::endl;
0088       if (displaystring.find("unix") != std::string::npos)
0089       {
0090         utsname ThisNode{};
0091         uname(&ThisNode);
0092         std::cout << "presumably the virtual framebuffer is not running on " << ThisNode.nodename
0093                   << ", check if process /usr/X11R6/bin/Xvfb is alive" << std::endl;
0094       }
0095       else if (displaystring.find("localhost") != std::string::npos)
0096       {
0097         std::cout << "Check your ssh forwarding" << std::endl;
0098         std::cout << "your $HOME/.ssh/config has to contain the line" << std::endl;
0099         std::cout << "ForwardX11 yes" << std::endl;
0100       }
0101     }
0102     else
0103     {
0104       std::cout << "Display not set, cannot continue" << std::endl;
0105     }
0106     exit(1);
0107   }
0108   // we have a working display
0109   clientrunning = new TH1F("ClientRunning", "ClientRunning", 1, 0, 1);
0110   if (getenv("ONLMON_HTMLDIR") == nullptr)
0111   {
0112     std::cout << "ONLMON_HTMLDIR not set, exiting" << std::endl;
0113     exit(1);
0114   }
0115   fHtml = new OnlMonHtml(getenv("ONLMON_HTMLDIR"));
0116 
0117   TGFrame *rootWin = (TGFrame *) gClient->GetRoot();
0118   display_sizex = rootWin->GetDefaultWidth();
0119   display_sizey = rootWin->GetDefaultHeight();
0120   for (int i = 0; i < kMAXSIGNALS; i++)
0121   {
0122     gSystem->IgnoreSignal((ESignals) i);
0123   }
0124   return;
0125 }
0126 
0127 OnlMonClient::~OnlMonClient()
0128 {
0129   while (DrawerList.begin() != DrawerList.end())
0130   {
0131     if (verbosity > 0)
0132     {
0133       std::cout << "deleting " << DrawerList.begin()->first << std::endl;
0134     }
0135     delete DrawerList.begin()->second;
0136     DrawerList.erase(DrawerList.begin());
0137   }
0138   while (Histo.begin() != Histo.end())
0139   {
0140     delete Histo.begin()->second;
0141     Histo.erase(Histo.begin());
0142   }
0143   delete clientrunning;
0144   delete fHtml;
0145   delete defaultStyle;
0146   // this deletes all open canvases
0147   TSeqCollection *allCanvases = gROOT->GetListOfCanvases();
0148   TCanvas *canvas = nullptr;
0149   while ((canvas = static_cast<TCanvas *>(allCanvases->First())))
0150   {
0151     if (verbosity > 0)
0152     {
0153       std::cout << "Deleting Canvas " << canvas->GetName() << std::endl;
0154     }
0155     delete canvas;
0156   }
0157   __instance = nullptr;
0158   return;
0159 }
0160 
0161 void OnlMonClient::registerHisto(const std::string &hname, const std::string &subsys)
0162 {
0163   auto subsysiter = SubsysHisto.find(subsys);
0164   if (subsysiter == SubsysHisto.end())
0165   {
0166     std::map<const std::string, ClientHistoList *> entry;
0167     // c++11 map.insert returns pair<iterator,bool>
0168     subsysiter = SubsysHisto.insert(std::make_pair(subsys, entry)).first;
0169     if (Verbosity() > 2)
0170     {
0171       std::cout << "inserting " << subsys << " into SubsysHisto, readback: " << subsysiter->first << std::endl;
0172     }
0173   }
0174   auto hiter = subsysiter->second.find(hname);
0175   if (hiter == subsysiter->second.end())
0176   {
0177     ClientHistoList *newhisto = new ClientHistoList();
0178     newhisto->SubSystem(subsys);
0179     subsysiter->second.insert(std::make_pair(hname, newhisto));
0180     if (Verbosity() > 0)
0181     {
0182       std::cout << "new histogram " << hname << " of subsystem " << subsys << std::endl;
0183     }
0184   }
0185   else
0186   {
0187     hiter->second->SubSystem(subsys);
0188   }
0189   // register FrameWorkVars histo if we don't have it already
0190   std::string frameworkhistoname = "FrameWorkVars";
0191   hiter = subsysiter->second.find(frameworkhistoname);
0192   if (hiter == subsysiter->second.end())
0193   {
0194     ClientHistoList *newhisto = new ClientHistoList();
0195     newhisto->SubSystem(subsys);
0196     subsysiter->second.insert(std::make_pair(frameworkhistoname, newhisto));
0197     if (Verbosity() > 0)
0198     {
0199       std::cout << "new histogram " << frameworkhistoname << " of subsystem " << subsys << std::endl;
0200     }
0201   }
0202   else
0203   {
0204     hiter->second->SubSystem(subsys);
0205   }
0206 
0207   return;
0208 }
0209 
0210 int OnlMonClient::requestHistoBySubSystem(const std::string &subsys, int getall)
0211 {
0212   std::string mysubsys = subsys.substr(0, subsys.find('_'));
0213   for (const auto &frwrkiter : m_MonitorFetchedSet)
0214   {
0215     if (frwrkiter.find(mysubsys) == std::string::npos)
0216     {
0217       m_MonitorFetchedSet.clear();
0218       break;
0219     }
0220   }
0221   int iret = 0;
0222   std::map<const std::string, ClientHistoList *>::const_iterator histoiter;
0223   std::map<const std::string, ClientHistoList *>::const_iterator histonewiter;
0224   if (!IsMonitorRunning(subsys))  // test if saved monitor server is still running
0225   {
0226     // monitor is not running - remove its entry if it exists
0227     auto moniiter = MonitorHostPorts.find(subsys);
0228     if (moniiter != MonitorHostPorts.end())
0229     {
0230       MonitorHostPorts.erase(moniiter);
0231     }
0232     // Find monitor, if not found reset ClientHistoList entries for host and port
0233     if (FindMonitor(subsys) == 0)
0234     {
0235       auto subsyshistos = SubsysHisto.find(subsys);
0236       if (subsyshistos != SubsysHisto.end())
0237       {
0238         for (auto &hiter : subsyshistos->second)
0239         {
0240           hiter.second->ServerHost("UNKNOWN");
0241           hiter.second->ServerPort(0);
0242           if (hiter.second->Histo() != nullptr)
0243           {
0244             hiter.second->Histo()->Delete();
0245           }
0246           hiter.second->Histo(nullptr);
0247         }
0248       }
0249       return iret;
0250     }
0251   }
0252 
0253   if (getall == 0)
0254   {
0255     std::map<std::string, std::map<const std::string, ClientHistoList *>>::const_iterator histos = SubsysHisto.find(subsys);
0256     for (auto &hiter : histos->second)
0257     {
0258       if (requestHistoByName(subsys, hiter.first))
0259       {
0260         if (Verbosity() > 2)
0261         {
0262           std::cout << "Request for " << hiter.first << " on " << subsys << " failed " << std::endl;
0263         }
0264         if (hiter.second->Histo())
0265         {
0266           hiter.second->Histo()->Delete();
0267           hiter.second->Histo(nullptr);
0268           hiter.second->ServerHost("UNKNOWN");
0269           hiter.second->ServerPort(0);
0270         }
0271         iret = -1;
0272       }
0273     }
0274   }
0275   else if (getall == 1)
0276   {
0277     std::map<std::string, std::list<std::string>> transferlist;
0278     std::ostringstream host_port;
0279 
0280     int failed_to_locate = 0;
0281     auto subs = SubsysHisto.find(subsys);
0282     {
0283       for (auto &histos : subs->second)
0284       {
0285         if (Verbosity() > 2)
0286         {
0287           std::cout << "checking for subsystem " << subs->first << ", histo " << histos.first << std::endl;
0288         }
0289         if (histos.second->SubSystem() == subsys)
0290         {
0291           int unknown_histo = 0;
0292           std::string hname = histos.first;
0293           if (histos.second->ServerHost() == "UNKNOWN")
0294           {
0295             if (!failed_to_locate)
0296             {
0297           //          std::cout << "Looking for " << hname << ", server " << subsys << std::endl;
0298               if (LocateHistogram(hname, subsys) < 1)
0299               {
0300                 if (Verbosity() > 2)
0301                 {
0302                   std::cout << "Subsystem " << subsys << " Histogram " << hname << " cannot be located" << std::endl;
0303                 }
0304                 failed_to_locate = 1;
0305                 unknown_histo = 1;
0306                 iret = -1;
0307               }
0308             }
0309             else
0310             {
0311               unknown_histo = 1;
0312             }
0313           }
0314           // reset histogram in case they don't exist on the server anymore
0315           if (histos.second->Histo())
0316           {
0317             histos.second->Histo()->Reset();
0318           }
0319           if (!unknown_histo)
0320           {
0321             std::string fullhname = subsys + std::string(" ") + hname;
0322             (transferlist[subsys]).push_back(fullhname);
0323           }
0324         }
0325       }
0326     }
0327     std::list<std::string>::const_iterator liter;
0328     for (auto &listiter : transferlist)
0329     {
0330       std::list<std::string> hlist = listiter.second;
0331       auto hostportiter = MonitorHostPorts.find(listiter.first);
0332       if (hostportiter == MonitorHostPorts.end())
0333       {
0334         std::cout << __PRETTY_FUNCTION__ << "Cannot find MonitorHostPorts entry for " << listiter.first << std::endl;
0335         std::cout << "existing hosts: " << std::endl;
0336         for (auto &hport : MonitorHostPorts)
0337         {
0338           std::cout << "subsystem " << hport.first << " on host " << hport.second.first
0339                     << " listening on port " << hport.second.second << std::endl;
0340         }
0341         continue;
0342       }
0343       if (requestHistoList(listiter.first, hostportiter->second.first, hostportiter->second.second, hlist) != 0)
0344       {
0345         for (liter = hlist.begin(); liter != hlist.end(); ++liter)
0346         {
0347           if (requestHistoByName(*liter))
0348           {
0349             std::cout << "Request for " << *liter << " failed " << std::endl;
0350             histoiter = Histo.find(*liter);
0351             if (histoiter->second && histoiter->second->Histo())
0352             {
0353               histoiter->second->Histo()->Delete();
0354               histoiter->second->Histo(nullptr);
0355               histoiter->second->ServerHost("UNKNOWN");
0356               histoiter->second->ServerPort(0);
0357             }
0358           }
0359         }
0360       }
0361     }
0362   }
0363   else if (getall == 2)
0364   {
0365     const char *hname = "none";
0366     for (histoiter = Histo.begin(); histoiter != Histo.end(); ++histoiter)
0367     {
0368       if (histoiter->second->SubSystem() == subsys)
0369       {
0370         hname = histoiter->first.c_str();
0371         break;
0372       }
0373     }
0374     // histoiter points here to first histogram of subsystem
0375     if (histoiter != Histo.end())
0376     {
0377       std::string hostname = histoiter->second->ServerHost();
0378       int moniport = histoiter->second->ServerPort();
0379       {
0380         if (hostname == "UNKNOWN")
0381         {
0382           if (LocateHistogram(hname, "") < 1)
0383           {
0384             std::cout << "Histogram " << hname << " cannot be located" << std::endl;
0385             return -1;
0386           }
0387           histonewiter = Histo.find(hname);
0388           hostname = histonewiter->second->ServerHost();
0389           moniport = histonewiter->second->ServerPort();
0390         }
0391 
0392         // Reset the histograms in case they don't exhist on the host.
0393         for (histonewiter = Histo.begin(); histonewiter != Histo.end(); ++histonewiter)
0394         {
0395           if (histonewiter->second->SubSystem() == subsys)
0396           {
0397             if (histonewiter->second->Histo())
0398             {
0399               histonewiter->second->Histo()->Reset();
0400             }
0401           }
0402         }
0403 
0404         if (requestHisto("ALL", hostname, moniport))
0405         {
0406           std::cout << "Request for all histograms from "
0407                     << hostname << " failed, trying single " << std::endl;
0408           iret = requestHistoBySubSystem(subsys, 0);
0409         }
0410       }
0411     }
0412     else
0413     {
0414       std::cout << "No Histogram of subsystem "
0415                 << subsys << " registered" << std::endl;
0416     }
0417   }
0418   m_MonitorFetchedSet.insert(subsys);
0419   return iret;
0420 }
0421 
0422 void OnlMonClient::registerDrawer(OnlMonDraw *Drawer)
0423 {
0424   std::map<const std::string, OnlMonDraw *>::iterator iter = DrawerList.find(Drawer->Name());
0425   if (iter != DrawerList.end())
0426   {
0427     std::cout << "Drawer " << Drawer->Name() << " already registered, I won't overwrite it" << std::endl;
0428     std::cout << "Use a different name and try again" << std::endl;
0429   }
0430   else
0431   {
0432     DrawerList[Drawer->Name()] = Drawer;
0433     Drawer->Init();
0434     SetStyleToDefault();
0435   }
0436   return;
0437 }
0438 
0439 int OnlMonClient::Draw(const char *who, const char *what)
0440 {
0441   GetServerInfo();
0442   int iret = DoSomething(who, what, "DRAW");
0443   //  gSystem->ProcessEvents();
0444   return iret;
0445 }
0446 
0447 int OnlMonClient::SavePlot(const std::string &who, const std::string &what)
0448 {
0449   int iret = DoSomething(who, what, "SAVEPLOT");
0450   TSeqCollection *allCanvases = gROOT->GetListOfCanvases();
0451   TCanvas *canvas = nullptr;
0452   while ((canvas = static_cast<TCanvas *>(allCanvases->First())))
0453   {
0454     if (verbosity > 0)
0455     {
0456       std::cout << "Deleting Canvas " << canvas->GetName() << std::endl;
0457     }
0458     delete canvas;
0459   }
0460   //  gSystem->ProcessEvents();
0461   return iret;
0462 }
0463 
0464 int OnlMonClient::MakePS(const char *who, const char *what)
0465 {
0466   int iret = DoSomething(who, what, "PS");
0467   //  gSystem->ProcessEvents();
0468   return iret;
0469 }
0470 
0471 int OnlMonClient::MakeHtml(const char *who, const char *what)
0472 {
0473   isHtml(true); // so the client knows we run in html mode
0474   GetServerInfo();
0475   mode_t old_umask;
0476   int runno = RunNumber();
0477   if (runno <= 0)
0478   {
0479     std::cout << "Run Number too small: " << runno
0480               << " not creating html output" << std::endl;
0481     return 0;
0482   }
0483   char *onlmon_real_html = getenv("ONLMON_REAL_HTML");
0484   if (!onlmon_real_html)
0485   {
0486     old_umask = umask(S_IWOTH);
0487     std::cout << "Making html output group writable so others can run tests as well" << std::endl;
0488   }
0489   fHtml->runNumber(runno);  // do not forget this !
0490   int iret = DoSomething(who, what, "HTML");
0491 
0492   if (!onlmon_real_html)
0493   {
0494     umask(old_umask);
0495   }
0496   //  gSystem->ProcessEvents();
0497   return iret;
0498 }
0499 
0500 int OnlMonClient::DoSomething(const std::string &who, const std::string &what, const std::string &opt)
0501 {
0502   std::map<const std::string, OnlMonDraw *>::iterator iter;
0503   if (who != "ALL")  // is drawer was specified (!All)
0504   {
0505     iter = DrawerList.find(who);
0506     if (iter != DrawerList.end())
0507     {
0508       if (opt == "DRAW")
0509       {
0510         iter->second->Draw(what);
0511       }
0512       else if (opt == "PS")
0513       {
0514         iter->second->MakePS(what);
0515       }
0516       else if (opt == "SAVEPLOT")
0517       {
0518         iter->second->SavePlot(what, "png");
0519       }
0520       else if (opt == "HTML")
0521       {
0522         if (verbosity > 0)
0523         {
0524           std::cout << __PRETTY_FUNCTION__ << " creating html output for "
0525                     << iter->second->Name() << std::endl;
0526         }
0527         iter->second->isHtml(true);
0528         if (iter->second->MakeHtml(what))
0529         {
0530           std::cout << "subsystem " << iter->second->Name()
0531                     << " not in root file, skipping" << std::endl;
0532         }
0533       }
0534       else
0535       {
0536         std::cout << "option " << opt << " not implemented" << std::endl;
0537         return 0;
0538       }
0539       SetStyleToDefault();
0540       return 0;
0541     }
0542     else
0543     {
0544       std::cout << "Drawer " << who << " not in list" << std::endl;
0545       Print("DRAWER");
0546       return -1;
0547     }
0548   }
0549   else
0550   {
0551     for (iter = DrawerList.begin(); iter != DrawerList.end(); ++iter)
0552     {
0553       if (opt == "DRAW")
0554       {
0555         iter->second->Draw(what);
0556       }
0557       else if (opt == "PS")
0558       {
0559         iter->second->MakePS(what);
0560       }
0561       else if (opt == "HTML")
0562       {
0563         if (verbosity > 0)
0564         {
0565           std::cout << __PRETTY_FUNCTION__ << " creating html output for "
0566                     << iter->second->Name() << std::endl;
0567         }
0568         gROOT->Reset();
0569         iter->second->isHtml(true);
0570         int iret = iter->second->MakeHtml(what);
0571         if (iret)
0572         {
0573           std::cout << "subsystem " << iter->second->Name()
0574                     << " not in root file, skipping" << std::endl;
0575           // delete all canvases (no more piling up of 50 canvases)
0576           // if run for a single subsystem this leaves the canvas intact
0577           // for debugging
0578           TSeqCollection *allCanvases = gROOT->GetListOfCanvases();
0579           TCanvas *canvas = nullptr;
0580           while ((canvas = static_cast<TCanvas *>(allCanvases->First())))
0581           {
0582             std::cout << "Deleting Canvas " << canvas->GetName() << std::endl;
0583             delete canvas;
0584           }
0585         }
0586       }
0587       SetStyleToDefault();
0588     }
0589   }
0590   return 0;
0591 }
0592 
0593 int OnlMonClient::requestHistoByName(const std::string &subsys, const std::string &what)
0594 {
0595   std::string hostname = "UNKNOWN";
0596   int moniport = OnlMonDefs::MONIPORT;
0597   std::map<std::string, std::map<const std::string, ClientHistoList *>>::const_iterator histos = SubsysHisto.find(subsys);
0598   auto histoiter = histos->second.find(what);
0599   if (Verbosity() > 2)
0600   {
0601     std::cout << __PRETTY_FUNCTION__ << "checking for " << what << " on monitor " << subsys << std::endl;
0602   }
0603   if (histoiter != histos->second.end())
0604   {
0605     hostname = histoiter->second->ServerHost();
0606     moniport = histoiter->second->ServerPort();
0607     if (hostname == "UNKNOWN")
0608     {
0609       if (LocateHistogram(what, subsys) < 1)
0610       {
0611         std::cout << "Histogram " << what << " cannot be located" << std::endl;
0612         return -1;
0613       }
0614       // search again since LocateHistogram can change the map
0615       histoiter = histos->second.find(what);
0616       hostname = histoiter->second->ServerHost();
0617       moniport = histoiter->second->ServerPort();
0618       if (hostname == "UNKNOWN")
0619       {
0620         std::cout << __PRETTY_FUNCTION__ << "host UNKNOWN for whatever reason" << std::endl;
0621         return -3;
0622       }
0623     }
0624   }
0625   else
0626   {
0627     if (LocateHistogram(what, subsys) < 1)
0628     {
0629       std::cout << "Histogram " << what << " cannot be located" << std::endl;
0630       return -2;
0631     }
0632     histoiter = histos->second.find(what);
0633     if (histoiter != histos->second.end())
0634     {
0635       hostname = histoiter->second->ServerHost();
0636       moniport = histoiter->second->ServerPort();
0637       if (hostname == "UNKNOWN")
0638       {
0639         std::cout << __PRETTY_FUNCTION__ << "host UNKNOWN for whatever reason" << std::endl;
0640         return -3;
0641       }
0642     }
0643     else
0644     {
0645       std::cout << __PRETTY_FUNCTION__ << "Problem determining host" << std::endl;
0646     }
0647   }
0648   // Open connection to server
0649   TSocket sock(hostname.c_str(), moniport);
0650   TMessage *mess;
0651   std::string fullhistoname = subsys + std::string(" ") + what;
0652   if (Verbosity() > 2)
0653   {
0654     std::cout << __PRETTY_FUNCTION__ << " sending " << fullhistoname << " to " << hostname << " port " << moniport << std::endl;
0655   }
0656   sock.Send(fullhistoname.c_str());
0657   while (true)
0658   {
0659     if (verbosity > 1)
0660     {
0661       std::cout << __PRETTY_FUNCTION__ << "Waiting for Message from : " << hostname
0662                 << " on port " << moniport << std::endl;
0663     }
0664     sock.Recv(mess);
0665     if (!mess)  // if server is not up mess is NULL
0666     {
0667       std::cout << __PRETTY_FUNCTION__ << "Server not running on " << hostname << std::endl;
0668       sock.Close();
0669       return 1;
0670     }
0671     if (mess->What() == kMESS_STRING)
0672     {
0673       char str[OnlMonDefs::MSGLEN];
0674       mess->ReadString(str, OnlMonDefs::MSGLEN);
0675       delete mess;
0676       if (verbosity > 1)
0677       {
0678         std::cout << __PRETTY_FUNCTION__ << "Message: " << str << std::endl;
0679       }
0680       if (!strcmp(str, "Finished"))
0681       {
0682         break;
0683       }
0684       else if (!strcmp(str, "UnknownHisto"))
0685       {
0686         break;
0687       }
0688       else
0689       {
0690         std::cout << __PRETTY_FUNCTION__ << "Unknown Text Message: " << str << std::endl;
0691         sock.Send("Ack");
0692       }
0693     }
0694     else if (mess->What() == kMESS_OBJECT)
0695     {
0696       TH1 *histo = static_cast<TH1 *>(mess->ReadObjectAny(mess->GetClass()));
0697       delete mess;
0698       TH1 *maphist = static_cast<TH1 *>(histo->Clone(histo->GetName()));
0699       if (verbosity > 1)
0700       {
0701         std::cout << __PRETTY_FUNCTION__ << "histoname: " << histo->GetName() << " at "
0702                   << histo << std::endl;
0703       }
0704 
0705       updateHistoMap(subsys, histo->GetName(), maphist);
0706       delete histo;
0707       sock.Send("Ack");
0708     }
0709   }
0710   sock.Send("Finished");  // tell server we are finished
0711   // Close the socket
0712   sock.Close();
0713   return 0;
0714 }
0715 
0716 int OnlMonClient::requestHisto(const std::string &what, const std::string &hostname, const int moniport)
0717 {
0718   // Open connection to server
0719   TSocket sock(hostname.c_str(), moniport);
0720   TMessage *mess;
0721   sock.Send(what.c_str());
0722   while (true)
0723   {
0724     sock.Recv(mess);
0725     if (!mess)  // if server is not up mess is NULL
0726     {
0727       std::cout << __PRETTY_FUNCTION__ << "Server not running on " << hostname << std::endl;
0728       sock.Close();
0729       return 1;
0730     }
0731     if (mess->What() == kMESS_STRING)
0732     {
0733       char str[OnlMonDefs::MSGLEN];
0734       mess->ReadString(str, OnlMonDefs::MSGLEN);
0735       delete mess;
0736       if (verbosity > 1)
0737       {
0738         std::cout << __PRETTY_FUNCTION__ << "Message: " << str << std::endl;
0739       }
0740 
0741       if (!strcmp(str, "Finished"))
0742       {
0743         break;
0744       }
0745       else if (!strcmp(str, "UnknownHisto"))
0746       {
0747         break;
0748       }
0749       else
0750       {
0751         std::cout << __PRETTY_FUNCTION__ << "Unknown Text Message: " << str << std::endl;
0752         sock.Send("Ack");
0753       }
0754     }
0755     else if (mess->What() == kMESS_OBJECT)
0756     {
0757       // this reads the message and allocate space for new histogram
0758       TH1 *histo = static_cast<TH1 *>(mess->ReadObjectAny(mess->GetClass()));
0759       delete mess;
0760       if (verbosity > 1)
0761       {
0762         std::cout << __PRETTY_FUNCTION__ << "histoname: " << histo->GetName() << " at "
0763                   << histo << std::endl;
0764       }
0765 
0766       updateHistoMap(what, histo->GetName(), histo);
0767       sock.Send("Ack");
0768     }
0769   }
0770   sock.Send("Finished");  // tell server we are finished
0771 
0772   // Close the socket
0773   sock.Close();
0774   return 0;
0775 }
0776 
0777 int OnlMonClient::requestMonitorList(const std::string &hostname, const int moniport)
0778 {
0779   TSocket sock(hostname.c_str(), moniport);
0780   TMessage *mess;
0781   sock.Send("LISTMONITORS");
0782   sock.Recv(mess);
0783   if (!mess)  // if server is not up mess is NULL
0784   {
0785     std::cout << __PRETTY_FUNCTION__ << "Server not running on " << hostname << std::endl;
0786     sock.Close();
0787     return 1;
0788   }
0789   delete mess;
0790   while (true)
0791   {
0792     sock.Recv(mess);
0793     if (mess->What() == kMESS_STRING)
0794     {
0795       char strmess[OnlMonDefs::MSGLEN];
0796       mess->ReadString(strmess, OnlMonDefs::MSGLEN);
0797       delete mess;
0798       if (Verbosity() > 1)
0799       {
0800         std::cout << "received " << strmess << std::endl;
0801       }
0802       std::string str(strmess);
0803       if (str == "Finished")
0804       {
0805         break;
0806       }
0807       if (Verbosity() > 2)
0808       {
0809         std::cout << "inserting " << str << " on host " << hostname
0810                   << " listening to " << moniport << std::endl;
0811       }
0812       MonitorHostPorts.insert(std::make_pair(str, std::make_pair(hostname, moniport)));
0813     }
0814     else
0815     {
0816       std::cout << "requestMonitorList: received unexpected message type: " << mess->What() << std::endl;
0817       break;
0818     }
0819   }
0820   sock.Send("Finished");  // tell server we are finished
0821 
0822   // Close the socket
0823   sock.Close();
0824   return 0;
0825 }
0826 
0827 int OnlMonClient::requestHistoList(const std::string &subsys, const std::string &hostname, const int moniport, std::list<std::string> &histolist)
0828 {
0829   // Open connection to server
0830   TSocket sock(hostname.c_str(), moniport);
0831   TMessage *mess;
0832   sock.Send("LIST");
0833   std::list<std::string>::const_iterator listiter;
0834   sock.Recv(mess);
0835   if (!mess)  // if server is not up mess is NULL
0836   {
0837     std::cout << __PRETTY_FUNCTION__ << "Server not running on " << hostname << std::endl;
0838     sock.Close();
0839     return 1;
0840   }
0841 
0842   delete mess;
0843   for (listiter = histolist.begin(); listiter != histolist.end(); ++listiter)
0844   {
0845     if (Verbosity() > 2)
0846     {
0847       std::cout << __PRETTY_FUNCTION__ << "asking for " << *listiter << std::endl;
0848     }
0849     sock.Send((*listiter).c_str());
0850     sock.Recv(mess);
0851     if (!mess)
0852     {
0853       std::cout << __PRETTY_FUNCTION__ << "Server shut down during getting histo list" << std::endl;
0854       sock.Close();
0855       return 1;
0856     }
0857     if (mess->What() == kMESS_STRING)
0858     {
0859       char str[OnlMonDefs::MSGLEN];
0860       mess->ReadString(str, OnlMonDefs::MSGLEN);
0861       delete mess;
0862       if (verbosity > 1)
0863       {
0864         std::cout << __PRETTY_FUNCTION__ << "Message: " << str << std::endl;
0865       }
0866 
0867       if (!strcmp(str, "Ack"))
0868       {
0869         break;
0870       }
0871       else if (!strcmp(str, "UnknownHisto"))
0872       {
0873         break;
0874       }
0875       else
0876       {
0877         std::cout << __PRETTY_FUNCTION__ << "Unknown Text Message: " << str << std::endl;
0878       }
0879     }
0880     else if (mess->What() == kMESS_OBJECT)
0881     {
0882       // this reads the message and allocate space for new histogram
0883       TH1 *histo = static_cast<TH1 *>(mess->ReadObjectAny(mess->GetClass()));
0884       delete mess;
0885       if (verbosity > 1)
0886       {
0887         std::cout << __PRETTY_FUNCTION__ << "histoname: " << histo->GetName() << " at "
0888                   << histo << std::endl;
0889       }
0890 
0891       updateHistoMap(subsys, histo->GetName(), histo);
0892     }
0893   }
0894   sock.Send("alldone");
0895   sock.Recv(mess);
0896   delete mess;
0897   sock.Send("Finished");  // tell server we are finished
0898 
0899   // Close the socket
0900   sock.Close();
0901   return 0;
0902 }
0903 
0904 void OnlMonClient::updateHistoMap(const std::string &subsys, const std::string &hname, TH1 *h1d)
0905 {
0906   auto subsysiter = SubsysHisto.find(subsys);
0907   if (subsysiter == SubsysHisto.end())
0908   {
0909     std::map<const std::string, ClientHistoList *> newmap;
0910     ClientHistoList *entry = new ClientHistoList(subsys);
0911     entry->Histo(h1d);
0912     newmap.insert(std::make_pair(hname, entry));
0913     SubsysHisto.insert(std::make_pair(subsys, newmap));
0914     return;
0915   }
0916   auto histoiter = subsysiter->second.find(hname);
0917   //  std::map<const std::string, ClientHistoList *>::const_iterator histoiter = Histo.find(hname);
0918   if (histoiter != subsysiter->second.end())
0919   {
0920     if (Verbosity() > 2)
0921     {
0922       std::cout << "deleting histogram " << hname << " at " << Histo[hname] << std::endl;
0923     }
0924     delete histoiter->second->Histo();  // delete old histogram
0925     histoiter->second->Histo(h1d);
0926   }
0927   else
0928   {
0929     ClientHistoList *newhisto = new ClientHistoList(subsys);
0930     newhisto->Histo(h1d);
0931     subsysiter->second.insert(std::make_pair(hname, newhisto));
0932     if (Verbosity() > 2)
0933     {
0934       std::cout << "new histogram " << hname << " at " << newhisto->Histo() << std::endl;
0935     }
0936   }
0937   return;
0938 }
0939 
0940 OnlMonDraw *
0941 OnlMonClient::getDrawer(const std::string &name)
0942 {
0943   std::map<const std::string, OnlMonDraw *>::iterator iter = DrawerList.find(name);
0944   if (iter != DrawerList.end())
0945   {
0946     return iter->second;
0947   }
0948   std::cout << "Could not locate drawer" << name << std::endl;
0949   return nullptr;
0950 }
0951 
0952 TH1 *OnlMonClient::getHisto(const std::string &monitor, const std::string &hname)
0953 {
0954   auto subsysiter = SubsysHisto.find(monitor);
0955   if (subsysiter == SubsysHisto.end())
0956   {
0957     return nullptr;
0958   }
0959   auto hiter = subsysiter->second.find(hname);
0960   if (hiter == subsysiter->second.end())
0961   {
0962     return nullptr;
0963   }
0964   return hiter->second->Histo();
0965 }
0966 
0967 void OnlMonClient::Print(const char *what)
0968 {
0969   if (!strcmp(what, "ALL") || !strcmp(what, "DRAWER"))
0970   {
0971     // loop over the map and print out the content (name and location in memory)
0972     std::cout << "--------------------------------------" << std::endl
0973               << std::endl;
0974     std::cout << "List of Drawers in OnlMonClient:" << std::endl;
0975 
0976     std::map<const std::string, OnlMonDraw *>::const_iterator hiter;
0977     for (hiter = DrawerList.begin(); hiter != DrawerList.end(); ++hiter)
0978     {
0979       std::cout << hiter->first << " is at " << hiter->second << std::endl;
0980     }
0981     std::cout << std::endl;
0982   }
0983   if (!strcmp(what, "ALL") || !strcmp(what, "SERVERS"))
0984   {
0985     // loop over the map and print out the content (name and location in memory)
0986     std::cout << "--------------------------------------" << std::endl
0987               << std::endl;
0988     std::cout << "List of Servers in OnlMonClient:" << std::endl;
0989 
0990     std::vector<std::string>::iterator hostiter;
0991     for (hostiter = MonitorHosts.begin(); hostiter != MonitorHosts.end(); ++hostiter)
0992     {
0993       std::cout << "ServerHost: " << *hostiter << std::endl;
0994     }
0995   }
0996   if (!strcmp(what, "ALL") || !strcmp(what, "MONITORS"))
0997   {
0998     // loop over the map and print out the content (name and location in memory)
0999     std::cout << "--------------------------------------" << std::endl
1000               << std::endl;
1001     std::cout << "List of Monitors in OnlMonClient:" << std::endl;
1002 
1003     for (auto &moniiter : MonitorHostPorts)
1004     {
1005       std::cout << "Monitor " << moniiter.first << " runs on " << moniiter.second.first
1006                 << " listening to port " << moniiter.second.second << std::endl;
1007     }
1008   }
1009   if (!strcmp(what, "ALL") || !strcmp(what, "HISTOS"))
1010   {
1011     // loop over the map and print out the content (name and location in memory)
1012     std::cout << "--------------------------------------" << std::endl
1013               << std::endl;
1014     std::cout << "List of Histograms in OnlMonClient:" << std::endl;
1015 
1016     std::map<const std::string, ClientHistoList *>::const_iterator hiter;
1017     for (hiter = Histo.begin(); hiter != Histo.end(); ++hiter)
1018     {
1019       if (hiter->second)
1020       {
1021       std::cout << hiter->first << " Address " << hiter->second->Histo()
1022                 << " on host " << hiter->second->ServerHost()
1023                 << " port " << hiter->second->ServerPort()
1024                 << ", subsystem " << hiter->second->SubSystem() << std::endl;
1025       }
1026     }
1027     std::cout << std::endl;
1028     for (auto &subs : SubsysHisto)
1029     {
1030       auto subiter = MonitorHostPorts.find(subs.first);
1031       if (subiter != MonitorHostPorts.end())
1032       {
1033         std::cout << "Subsystem " << subs.first << " runs on " << subiter->second.first;
1034         std::cout << " on port " << subiter->second.second << std::endl;
1035       }
1036       for (auto &histos : subs.second)
1037       {
1038         std::cout << histos.first << " @ " << subs.first
1039                   << " Address " << histos.second->Histo()
1040                   << " on host " << histos.second->ServerHost()
1041                   << " port " << histos.second->ServerPort()
1042                   << ", subsystem " << histos.second->SubSystem() << std::endl;
1043       }
1044     }
1045     std::cout << std::endl;
1046   }
1047   if (!strcmp(what, "ALL") || !strcmp(what, "UNKNOWN"))
1048   {
1049     // loop over the map and print out the content (name and location in memory)
1050     std::cout << "--------------------------------------" << std::endl
1051               << std::endl;
1052     std::cout << "List of Unknown Histograms in OnlMonClient:" << std::endl;
1053 
1054     std::map<const std::string, ClientHistoList *>::const_iterator hiter;
1055     for (hiter = Histo.begin(); hiter != Histo.end(); ++hiter)
1056     {
1057       if (hiter->second)
1058       {
1059     if (hiter->second->ServerHost() == "UNKNOWN" ||
1060         hiter->second->SubSystem() == "UNKNOWN")
1061     {
1062       std::cout << hiter->first << " Address " << hiter->second->Histo()
1063             << " on host " << hiter->second->ServerHost()
1064             << " port " << hiter->second->ServerPort()
1065             << ", subsystem " << hiter->second->SubSystem() << std::endl;
1066     }
1067       }
1068     }
1069     std::cout << std::endl;
1070     for (auto &subs : SubsysHisto)
1071     {
1072       for (auto &histos : subs.second)
1073       {
1074     if ( histos.second->ServerHost() == "UNKNOWN" ||
1075          histos.second->SubSystem() == "UNKNOWN")
1076     {
1077       std::cout << histos.first << " @ " << subs.first
1078             << " Address " << histos.second->Histo()
1079             << " on host " << histos.second->ServerHost()
1080             << " port " << histos.second->ServerPort()
1081             << ", subsystem " << histos.second->SubSystem() << std::endl;
1082     }
1083       }
1084     }
1085     std::cout << std::endl;
1086   }
1087   return;
1088 }
1089 
1090 void OnlMonClient::PrintHistos(const std::string &what)
1091 {
1092   std::cout << "--------------------------------------" << std::endl
1093             << std::endl;
1094   std::cout << "List of Histograms in OnlMonClient:" << std::endl;
1095   auto iter = SubsysHisto.find(what);
1096   if (iter == SubsysHisto.end())
1097   {
1098     std::cout << "subsystem " << what << " not found, available: " << std::endl;
1099     for (auto &subs : SubsysHisto)
1100     {
1101       std::cout << subs.first << std::endl;
1102     }
1103     return;
1104   }
1105   auto subiter = MonitorHostPorts.find(iter->first);
1106   if (subiter != MonitorHostPorts.end())
1107   {
1108     std::cout << "Subsystem " << iter->first << " runs on " << subiter->second.first;
1109     std::cout << " on port " << subiter->second.second << std::endl;
1110   }
1111   for (auto &histos : iter->second)
1112   {
1113     std::cout << histos.first << " @ " << iter->first
1114               << " Address " << histos.second->Histo()
1115               << " on host " << histos.second->ServerHost()
1116               << " port " << histos.second->ServerPort()
1117               << ", subsystem " << histos.second->SubSystem() << std::endl;
1118   }
1119   std::cout << std::endl;
1120   return;
1121 }
1122 
1123 int OnlMonClient::UpdateServerHistoMap(const std::string &hname, const std::string &subsys, const std::string &hostname)
1124 {
1125   // Open connection to server
1126   std::string searchstring = subsys + ' ' + hname;
1127   int MoniPort = OnlMonDefs::MONIPORT;
1128   int foundit = 0;
1129   do
1130   {
1131     std::cout << "Connecting to " << hostname << ", if it is frozen here - this is the one you need to restart" << std::endl;
1132     TSocket sock(hostname.c_str(), MoniPort);
1133     TMessage *mess;
1134     if (verbosity > 0)
1135     {
1136       std::cout << "UpdateServerHistoMap: sending cmd HistoList to "
1137                 << hostname << " on port "
1138                 << MoniPort
1139                 << std::endl;
1140     }
1141     if (!sock.Send("HistoList"))
1142     {
1143       std::cout << "Server not running on " << hostname
1144                 << " port " << MoniPort << std::endl;
1145       goto noserver;
1146     }
1147     while (true)
1148     {
1149       if (verbosity > 0)
1150       {
1151         std::cout << "UpdateServerHistoMap: waiting for response on "
1152                   << hostname << " on port "
1153                   << MoniPort
1154                   << std::endl;
1155       }
1156       sock.Recv(mess);
1157       if (!mess)  // if server is not up mess is NULL
1158       {
1159         std::cout << "UpdateServerHistoMap: No Recv, Server not running on "
1160                   << hostname
1161                   << " on port " << MoniPort << std::endl;
1162         goto noserver;
1163       }
1164       if (mess->What() == kMESS_STRING)
1165       {
1166         char strchr[OnlMonDefs::MSGLEN];
1167         mess->ReadString(strchr, OnlMonDefs::MSGLEN);
1168         delete mess;
1169         std::string str = strchr;
1170         if (verbosity > 0)
1171         {
1172           std::cout << "UpdateServerHistoMap Response: " << str << std::endl;
1173         }
1174         if (str == "Finished")
1175         {
1176           break;
1177         }
1178 
1179         if (str == searchstring)
1180         {
1181           std::cout << "found subsystem " << subsys << " histo " << hname << std::endl;
1182           foundit = 1;
1183         }
1184         unsigned int pos_space = str.find(' ');
1185         PutHistoInMap(str.substr(pos_space + 1, str.size()), str.substr(0, pos_space), hostname, MoniPort);
1186         sock.Send("Ack");
1187       }
1188     }
1189     sock.Send("Finished");  // tell server we are finished
1190 
1191     // Close the socket
1192   noserver:
1193     sock.Close();
1194     if (foundit)
1195     {
1196       return foundit;
1197     }
1198     MoniPort++;
1199   } while ((MoniPort - OnlMonDefs::MONIPORT) < OnlMonDefs::NUMMONIPORT);  // no more than NUMMONIPORT parallel servers
1200   return foundit;
1201 }
1202 
1203 void OnlMonClient::PutHistoInMap(const std::string &hname, const std::string &subsys, const std::string &hostname, const int port)
1204 {
1205   auto hiter = SubsysHisto.find(subsys);
1206   if (hiter == SubsysHisto.end())
1207   {
1208     std::map<const std::string, ClientHistoList *> entry;
1209     // c++11 map.insert returns pair<iterator,bool>
1210     hiter = SubsysHisto.insert(std::make_pair(subsys, entry)).first;
1211   }
1212   auto histoiter = hiter->second.find(hname);
1213   if (histoiter != hiter->second.end())
1214   {
1215     histoiter->second->ServerHost(hostname);
1216     histoiter->second->ServerPort(port);
1217   }
1218   else
1219   {
1220     ClientHistoList *newhisto = new ClientHistoList();
1221     newhisto->ServerHost(hostname);
1222     newhisto->ServerPort(port);
1223     hiter->second.insert(std::make_pair(hname, newhisto));
1224   }
1225   return;
1226 }
1227 
1228 void OnlMonClient::AddServerHost(const std::string &hostname)
1229 {
1230   if (find(MonitorHosts.begin(), MonitorHosts.end(), hostname) != MonitorHosts.end())
1231   {
1232     if (Verbosity() > 2)
1233     {
1234       std::cout << "Host " << hostname << " already in list" << std::endl;
1235     }
1236   }
1237   else
1238   {
1239     MonitorHosts.emplace_back(hostname);
1240   }
1241   return;
1242 }
1243 
1244 int OnlMonClient::LocateHistogram(const std::string &hname, const std::string &subsys)
1245 {
1246   for (auto &hostiter : MonitorHosts)
1247   {
1248     if (UpdateServerHistoMap(hname, subsys, hostiter) > 0)
1249     {
1250       return 1;
1251     }
1252   }
1253   return 0;
1254 }
1255 
1256 int OnlMonClient::RunNumber()
1257 {
1258   int runno = -9999;
1259   for (const auto &frwrkiter : m_MonitorFetchedSet)
1260   {
1261     TH1 *frameworkvars = getHisto(frwrkiter, "FrameWorkVars");
1262     if (frameworkvars)
1263     {
1264       runno = std::max(runno, (int) frameworkvars->GetBinContent(RUNNUMBERBIN));
1265     }
1266   }
1267   return (runno);
1268 }
1269 
1270 int OnlMonClient::GetServerInfo()
1271 {
1272   std::map<std::string, int> server_runmap;
1273   int runno = -9999;
1274   for (const auto &frwrkiter : m_MonitorFetchedSet)
1275   {
1276     if (m_ServerStatsMap.find(frwrkiter) == m_ServerStatsMap.end())
1277     {
1278       m_ServerStatsMap[frwrkiter] = std::make_tuple(false, -1, -1, 0, -1);
1279     }
1280     TH1 *frameworkvars = getHisto(frwrkiter, "FrameWorkVars");
1281     if (frameworkvars)
1282     {
1283       int runnumber = frameworkvars->GetBinContent(RUNNUMBERBIN);
1284       time_t currtime = frameworkvars->GetBinContent(CURRENTTIMEBIN);
1285       int eventcounter = frameworkvars->GetBinContent(EVENTCOUNTERBIN);
1286       int gl1foundcounter = frameworkvars->GetBinContent(GL1COUNTERBIN);
1287       if (Verbosity() > 0)
1288       {
1289         std::cout << "Run number for " << frwrkiter << " is "
1290                   << runnumber
1291                   << " events taken: " << eventcounter;
1292     if (gl1foundcounter > -1)
1293       {
1294         std::cout << " gl1 found " << gl1foundcounter; 
1295       }
1296     std::cout  << " time is " << ctime(&currtime);  // ctime adds eol
1297       }
1298       runno = std::max(runno, runnumber);
1299       server_runmap[frwrkiter] = runnumber;
1300         auto &statsiter = m_ServerStatsMap[frwrkiter];
1301         std::get<0>(statsiter) = true;
1302         std::get<1>(statsiter) = runnumber;
1303         std::get<2>(statsiter) = eventcounter;
1304         std::get<3>(statsiter) = currtime;
1305         std::get<4>(statsiter) = gl1foundcounter;
1306     }
1307   }
1308   for (auto const &iter : server_runmap)
1309   {
1310     if (iter.second != runno)
1311     {
1312       std::cout << "server " << iter.first << " has bad run " << iter.second << std::endl;
1313       std::cout << "Resetting histos for " << iter.first << std::endl;
1314       std::get<0>(m_ServerStatsMap[iter.first]) = false;
1315       auto subsysiter = SubsysHisto.find(iter.first);
1316       if (subsysiter == SubsysHisto.end())
1317       {
1318         std::cout << "could not find " << iter.first << " in SubsysHisto map" << std::endl;
1319       }
1320       else
1321       {
1322         for (auto &hiter : subsysiter->second)
1323         {
1324           if (hiter.first != "FrameWorkVars")
1325           {
1326             if (hiter.second->Histo())
1327             {
1328               hiter.second->Histo()->Reset();
1329             }
1330           }
1331         }
1332       }
1333     }
1334   }
1335   return (runno);
1336 }
1337 
1338 std::pair<time_t,int> OnlMonClient::EventTime(const std::string &which)
1339 {
1340   time_t tret = 0;
1341   int color = 1; // default is black
1342   for (const auto &frwrkiter : m_MonitorFetchedSet)
1343   {
1344     tret = std::max(tret, EventTime(frwrkiter, which));
1345   }
1346 
1347   if (verbosity > 0)
1348   {
1349     std::cout << "Time is " << ctime(&tret) << std::endl;
1350   }
1351   if (!make_html)
1352     {
1353       time_t clienttime = time(nullptr);
1354       if ((clienttime - tret) > 600)
1355     {
1356       color = 2; // turn red if time is off
1357     }
1358     }
1359   return (std::make_pair(tret,color));
1360 }
1361 
1362 time_t OnlMonClient::EventTime(const std::string &servername, const std::string &which)
1363 {
1364   time_t tret = 0;
1365   int ibin = 0;
1366   if (which == "BOR")
1367   {
1368     ibin = BORTIMEBIN;
1369   }
1370   else if (which == "CURRENT")
1371   {
1372     ibin = CURRENTTIMEBIN;
1373   }
1374   else if (which == "EOR")
1375   {
1376     ibin = EORTIMEBIN;
1377   }
1378   else
1379   {
1380     std::cout << "Bad Option for Time: " << which
1381               << ", implemented are BOR EOR CURRENT" << std::endl;
1382     ibin = CURRENTTIMEBIN;
1383   }
1384   TH1 *frameworkvars = getHisto(servername, "FrameWorkVars");
1385   if (frameworkvars == nullptr)
1386   {
1387     tret = 0;
1388   }
1389   else
1390   {
1391     tret = (time_t) frameworkvars->GetBinContent(ibin);
1392   }
1393   if (verbosity > 0)
1394   {
1395     std::cout << "Time is " << ctime(&tret) << std::endl;
1396   }
1397   return (tret);
1398 }
1399 
1400 int OnlMonClient::ReadHistogramsFromFile(const std::string &filename, OnlMonDraw *drawer)
1401 {
1402   std::string subsys = ExtractSubsystem(filename, drawer);
1403   std::cout << "Reading histos from " << filename << std::endl;
1404   TFile *histofile = TFile::Open(filename.c_str(), "READ");
1405   if (!histofile)
1406   {
1407     std::cout << "Can't open " << filename << std::endl;
1408     return -1;
1409   }
1410   TIterator *titer = histofile->GetListOfKeys()->MakeIterator();
1411   TObject *obj;
1412   TH1 *histo, *histoptr;
1413   while ((obj = titer->Next()))
1414   {
1415     if (verbosity > 0)
1416     {
1417       std::cout << "TObject at " << obj << std::endl;
1418       std::cout << obj->GetName() << std::endl;
1419       std::cout << obj->ClassName() << std::endl;
1420     }
1421     histofile->GetObject(obj->GetName(), histoptr);
1422     if (histoptr)
1423     {
1424 // this is hokey but it seems to work, the SetDirectory(0) disconnects
1425 // the histo from the TFile and the static cast makes it work with our
1426 // histomap (otherwise something throws an exception)
1427       histoptr->SetDirectory(0);
1428       histo = dynamic_cast<TH1 *>(histoptr);
1429       updateHistoMap(subsys, histo->GetName(), histo);
1430       if (verbosity > 0)
1431       {
1432         std::cout << "HistoName: " << histo->GetName() << std::endl;
1433         std::cout << "HistoClass: " << histo->ClassName() << std::endl;
1434       }
1435     }
1436   }
1437   delete titer;
1438 // this is a fast way to close a file, if you call TFile->Close() it deletes all
1439 // histograms which can take a really long time (hours)
1440   gROOT->GetListOfFiles()->Remove( histofile );
1441   return 0;
1442 }
1443 
1444 int OnlMonClient::SendCommand(const char *hostname, const int port, const char *cmd)
1445 {
1446   // Open connection to server
1447   TSocket sock(hostname, port);
1448   TMessage *mess;
1449   if (!sock.Send(cmd))
1450   {
1451     std::cout << "Server not running on " << hostname
1452               << " port " << port << std::endl;
1453     sock.Close();
1454     return -1;
1455   }
1456   while (true)
1457   {
1458     sock.Recv(mess);
1459     if (!mess)  // if server is not up mess is NULL
1460     {
1461       std::cout << __PRETTY_FUNCTION__ << "No Recv, Server not running on " << hostname
1462                 << " on port " << port << std::endl;
1463       sock.Close();
1464       return -1;
1465     }
1466     if (mess->What() == kMESS_STRING)
1467     {
1468       char str[OnlMonDefs::MSGLEN];
1469       mess->ReadString(str, OnlMonDefs::MSGLEN);
1470       delete mess;
1471       if (verbosity > 1)
1472       {
1473         std::cout << __PRETTY_FUNCTION__ << " Message: " << str << std::endl;
1474       }
1475 
1476       if (!strcmp(str, "Finished"))
1477       {
1478         break;
1479       }
1480     }
1481   }
1482   sock.Send("Finished");  // tell server we are finished
1483 
1484   // Close the socket
1485   sock.Close();
1486   return 0;
1487 }
1488 
1489 //_____________________________________________________________________________
1490 void OnlMonClient::Verbosity(const int v)
1491 {
1492   verbosity = v;
1493   if (fHtml)
1494   {
1495     fHtml->verbosity(v);
1496   }
1497 }
1498 
1499 //_____________________________________________________________________________
1500 void OnlMonClient::htmlAddMenu(const OnlMonDraw &drawer,
1501                                const std::string &path,
1502                                const std::string &relfilename)
1503 {
1504   fHtml->addMenu(drawer.Name(), path, relfilename);
1505 }
1506 
1507 //_____________________________________________________________________________
1508 void OnlMonClient::htmlNamer(const OnlMonDraw &drawer,
1509                              const std::string &basefilename,
1510                              const std::string &ext,
1511                              std::string &fullfilename,
1512                              std::string &filename)
1513 {
1514   fHtml->namer(drawer.Name(), basefilename, ext, fullfilename, filename);
1515 }
1516 
1517 //_____________________________________________________________________________
1518 std::string
1519 OnlMonClient::htmlRegisterPage(const OnlMonDraw &drawer,
1520                                const std::string &path,
1521                                const std::string &basefilename,
1522                                const std::string &ext)
1523 {
1524   return fHtml->registerPage(drawer.Name(), path, basefilename, ext);
1525 }
1526 
1527 int OnlMonClient::CanvasToPng(TCanvas *canvas, std::string const &pngfilename)
1528 {
1529   // in order not to collide when running multiple html generators
1530   // create a unique filename (okay tempnam is not totally safe against
1531   // multiple procs getting the same name but the local /tmp filesystem should
1532   // prevent at least multiple machines colliding)
1533   // returned char array needs to be free'd after use
1534   if (!canvas)
1535   {
1536     std::cout << __PRETTY_FUNCTION__ << " TCanvas is Null Pointer" << std::endl;
1537     return -2;
1538   }
1539   if (pngfilename.empty())
1540   {
1541     std::cout << __PRETTY_FUNCTION__ << " emtpy png filename, not saving TCanvas "
1542               << canvas->GetName() << std::endl;
1543     return -1;
1544   }
1545   // uuid_t uu;
1546   // uuid_generate(uu);
1547   // char uuid[50];
1548   // uuid_unparse(uu, uuid);
1549   // std::string tmpname = "/tmp/TC" + std::string(uuid);
1550   // canvas->Print(tmpname.c_str(), "gif");  // write gif format
1551   // TImage *img = TImage::Open(tmpname.c_str());
1552   // img->WriteImage(pngfilename.c_str());
1553   // delete img;
1554   // if (remove(tmpname.c_str()))
1555   // {
1556   //   std::cout << "Error removing " << tmpname << std::endl;
1557   // }
1558   canvas->SaveAs(pngfilename.c_str());
1559   return 0;
1560 }
1561 
1562 int OnlMonClient::HistoToPng(TH1 *histo, std::string const &pngfilename, const char *drawopt, const int statopt)
1563 {
1564   TCanvas *cgiCanv = new TCanvas("cgiCanv", "cgiCanv", 200, 200, 650, 500);
1565   gStyle->SetOptStat(statopt);
1566   cgiCanv->SetFillColor(0);
1567   cgiCanv->SetBorderMode(0);
1568   cgiCanv->SetBorderSize(2);
1569   cgiCanv->SetFrameFillColor(0);
1570   cgiCanv->SetFrameBorderMode(0);
1571   cgiCanv->SetTickx();
1572   cgiCanv->SetTicky();
1573   cgiCanv->cd();
1574   histo->SetMarkerStyle(8);
1575   histo->SetMarkerSize(0.15);
1576   histo->Draw(drawopt);
1577   uuid_t uu;
1578   uuid_generate(uu);
1579   char uuid[50];
1580   uuid_unparse(uu, uuid);
1581   std::string tmpname = "/tmp/TC" + std::string(uuid);
1582   cgiCanv->Print(tmpname.c_str(), "gif");
1583   TImage *img = TImage::Open(tmpname.c_str());
1584   img->WriteImage(pngfilename.c_str());
1585   if (remove(tmpname.c_str()))
1586   {
1587     std::cout << "Error removing " << tmpname << std::endl;
1588   }
1589   delete cgiCanv;
1590   return 0;
1591 }
1592 
1593 int OnlMonClient::SaveLogFile(const OnlMonDraw &drawer)
1594 {
1595   // sendfile example shamelessly copied from
1596   // http://www.linuxgazette.com/issue91/tranter.html
1597   std::ostringstream logfilename;
1598   const char *logdir = getenv("ONLMON_LOGDIR");
1599   if (logdir)
1600   {
1601     logfilename << logdir << "/";
1602   }
1603   int irun = RunNumber();
1604   logfilename << drawer.Name() << "_" << irun << ".log.gz";
1605   std::ifstream infile(logfilename.str().c_str(), std::ios_base::binary);
1606   if (infile.good())
1607   {
1608     std::string outfilename = htmlRegisterPage(drawer, "Logfile", "log", "txt.gz");
1609     std::ofstream outfile(outfilename.c_str(), std::ios_base::binary);
1610     outfile << infile.rdbuf();
1611     infile.close();
1612     outfile.close();
1613   }
1614   return 0;
1615 }
1616 
1617 int OnlMonClient::SetStyleToDefault()
1618 {
1619   defaultStyle->cd();
1620   defaultStyle->Reset();
1621   defaultStyle->SetFrameBorderMode(0);
1622   defaultStyle->SetCanvasColor(0);
1623   defaultStyle->SetPadBorderMode(0);
1624   defaultStyle->SetCanvasBorderMode(0);
1625   defaultStyle->SetPalette(1, nullptr);
1626   return 0;
1627 }
1628 
1629 void OnlMonClient::CacheRunDB(const int runno)
1630 {
1631   if (runno == cachedrun)
1632   {
1633     return;
1634   }
1635   standalone = 0;
1636   cosmicrun = 0;
1637   runtype = "unknown_runtype";
1638 
1639   odbc::Connection *con {nullptr};
1640   odbc::Statement *query {nullptr};
1641   std::ostringstream cmd;
1642   try
1643   {
1644     con = odbc::DriverManager::getConnection("daq", "phnxrc", "");
1645   }
1646   catch (odbc::SQLException &e)
1647   {
1648     printf(" Exception caught during DriverManager::getConnection, Message: %s\n", e.getMessage().c_str());
1649     return;
1650   }
1651 
1652   query = con->createStatement();
1653   cmd << "select runnumber from run where runnumber = " << runno;
1654   odbc::ResultSet *rs = nullptr;
1655   int ncount = 10;
1656   while (ncount > 0)
1657   {
1658     try
1659     {
1660       rs = query->executeQuery(cmd.str());
1661     }
1662     catch (odbc::SQLException &e)
1663     {
1664       printf("Exception caught for query %s\nMessage: %s", cmd.str().c_str(), e.getMessage().c_str());
1665     }
1666     if (!rs->next())
1667     {
1668       printf("run table query did not give any result, run %d not in DB yet countdown %d\n", runno, ncount);
1669       ncount--;
1670       sleep(10);
1671       delete rs;
1672     }
1673     else
1674     {
1675       delete rs;
1676       break;
1677     }
1678   }
1679   cmd.str("");
1680   cmd << "SELECT runtype FROM RUN  WHERE RUNNUMBER = "
1681       << runno;
1682   if (verbosity > 0)
1683   {
1684     printf("command: %s\n", cmd.str().c_str());
1685   }
1686   try
1687   {
1688     rs = query->executeQuery(cmd.str());
1689   }
1690   catch (odbc::SQLException &e)
1691   {
1692     printf("Exception caught for query %s\nMessage: %s", cmd.str().c_str(), e.getMessage().c_str());
1693   }
1694   if (rs->next())
1695   {
1696     runtype = rs->getString("runtype");
1697     if (runtype == "cosmics")
1698     {
1699       cosmicrun = 1;
1700     }
1701     else
1702     {
1703       cosmicrun = 0;
1704     }
1705   }
1706   delete con;
1707   cachedrun = runno;
1708   //  printf("CacheRunDB: runno: %d\n",runno);
1709   return;
1710 }
1711 
1712 int OnlMonClient::isCosmicRun()
1713 {
1714   CacheRunDB(RunNumber());
1715   return cosmicrun;
1716 }
1717 
1718 int OnlMonClient::isStandalone()
1719 {
1720   CacheRunDB(RunNumber());
1721   return standalone;
1722 }
1723 
1724 std::string
1725 OnlMonClient::RunType()
1726 {
1727   CacheRunDB(RunNumber());
1728   return runtype;
1729 }
1730 
1731 void OnlMonClient::FindAllMonitors()
1732 {
1733   for (auto &hostiter : MonitorHosts)
1734   {
1735     if (Verbosity() > 2)
1736     {
1737       std::cout << "checking " << hostiter << std::endl;
1738     }
1739     for (unsigned int moniport = OnlMonDefs::MONIPORT; moniport < OnlMonDefs::MONIPORT + OnlMonDefs::NUMMONIPORT; ++moniport)
1740     {
1741       requestMonitorList(hostiter, moniport);
1742     }
1743   }
1744   return;
1745 }
1746 
1747 int OnlMonClient::FindMonitor(const std::string &name)
1748 {
1749   // loop over all hosts/ports until we find ours
1750   int iret = 0;
1751   for (auto &hostiter : MonitorHosts)
1752   {
1753     if (Verbosity() > 2)
1754     {
1755       std::cout << "checking " << hostiter << std::endl;
1756     }
1757     for (unsigned int moniport = OnlMonDefs::MONIPORT; moniport < OnlMonDefs::MONIPORT + OnlMonDefs::NUMMONIPORT; ++moniport)
1758     {
1759       requestMonitorList(hostiter, moniport);
1760       if (Verbosity() > 2)
1761       {
1762         std::cout << "looking for " << name << std::endl;
1763       }
1764       auto moniter = MonitorHostPorts.find(name);
1765       if (moniter != MonitorHostPorts.end())
1766       {
1767         if (Verbosity() > 2)
1768         {
1769           std::cout << "found " << name << " running on " << moniter->second.first
1770                     << " listening to port " << moniter->second.second << std::endl;
1771         }
1772         return 1;
1773       }
1774     }
1775   }
1776   return iret;
1777 }
1778 
1779 int OnlMonClient::IsMonitorRunning(const std::string &name)
1780 {
1781   int iret = 0;
1782   std::string command = std::string("ISRUNNING") + ' ' + name;
1783   auto moniter = MonitorHostPorts.find(name);
1784   if (moniter == MonitorHostPorts.end())
1785   {
1786     return iret;
1787   }
1788   TSocket sock(moniter->second.first.c_str(), moniter->second.second);
1789   TMessage *mess;
1790   sock.Send(command.c_str());
1791   sock.Recv(mess);
1792   if (!mess)  // if server is not up mess is NULL
1793   {
1794     std::cout << __PRETTY_FUNCTION__ << "Server not running on " << moniter->second.first << std::endl;
1795     sock.Close();
1796     return iret;
1797   }
1798   if (mess->What() == kMESS_STRING)
1799   {
1800     char str[OnlMonDefs::MSGLEN];
1801     mess->ReadString(str, OnlMonDefs::MSGLEN);
1802     delete mess;
1803     if (verbosity > 1)
1804     {
1805       std::cout << __PRETTY_FUNCTION__ << "Message: " << str << std::endl;
1806     }
1807     if (!strcmp(str, "Yes"))
1808     {
1809       iret = 1;
1810     }
1811   }
1812   sock.Send("Finished");
1813   sock.Close();
1814   return iret;
1815 }
1816 
1817 std::string OnlMonClient::ExtractSubsystem(const std::string &fullfilename, OnlMonDraw *drawer)
1818 {
1819   std::string subsys = std::filesystem::path(fullfilename).filename();
1820   subsys = subsys.substr(subsys.find('-') + 1);
1821   subsys.resize(subsys.find(".root"));
1822   m_MonitorFetchedSet.insert(subsys);
1823   drawer->AddServer(subsys);
1824   return subsys;
1825 }
1826 
1827 OnlMonDraw *OnlMonClient::GetDrawer(const std::string &name)
1828 {
1829   auto iter = DrawerList.find(name);
1830   if (iter != DrawerList.end())
1831   {
1832     return iter->second;
1833   }
1834   std::cout << "Cannot locate Drawer " << name << " in my list" << std::endl;
1835   return nullptr;
1836 }
1837 
1838 void OnlMonClient::SaveServerHistoMap(const std::string &cachefilename)
1839 {
1840   std::ofstream cachefile(cachefilename);
1841   std::cout << "saving histomap to " << cachefilename << std::endl;
1842   for (auto &subs : SubsysHisto)
1843   {
1844     for (auto &histos : subs.second)
1845     {
1846       cachefile << histos.second->SubSystem() << " " << histos.first << " " << histos.second->ServerHost() << " " << histos.second->ServerPort() << std::endl;
1847     }
1848   }
1849   cachefile.close();
1850   return;
1851 }
1852 
1853 void OnlMonClient::ReadServerHistoMap(const std::string &cachefilename)
1854 {
1855   std::ifstream cachefile(cachefilename);
1856   std::string hname;
1857   std::string subsys;
1858   std::string hostname;
1859   int port;
1860   if (cachefile.good())
1861   {
1862     std::cout << "opened histogram map cache file " << cachefilename << std::endl;
1863     std::string line;
1864     while (std::getline(cachefile, line))
1865     {
1866       std::istringstream iss(line);
1867       iss >> subsys;
1868       iss >> hname;
1869       iss >> hostname;
1870       iss >> port;
1871       AddServerHost(hostname);
1872       PutHistoInMap(hname,subsys,hostname,port);
1873       MonitorHostPorts.insert(std::make_pair(subsys, std::make_pair(hostname,port)));
1874     }
1875     cachefile.close();
1876   }
1877   else
1878   {
1879     std::cout << "failed to open histogram map cache file " << cachefilename << std::endl;
1880   }
1881 }