Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OnlMonServer.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file OnlMonServer.cc
1 #include "OnlMonServer.h"
2 
3 #include "OnlMon.h"
4 #include "OnlMonStatusDB.h"
5 
6 #include "MessageSystem.h"
7 
8 #include <Event/msg_profile.h> // for MSG_SEV_ERROR, MSG_SEV...
9 
10 #include <TFile.h>
11 #include <TH1.h>
12 #include <TROOT.h>
13 
14 #include <odbc++/connection.h>
15 #include <odbc++/drivermanager.h>
16 #include <odbc++/resultset.h>
17 #include <odbc++/statement.h> // for Statement
18 #include <odbc++/types.h> // for SQLException
19 
20 #include <zlib.h>
21 
22 #include <sys/utsname.h>
23 #include <unistd.h> // for sleep
24 #include <algorithm> // for max
25 #include <cstdio> // for printf
26 #include <cstdlib>
27 #include <cstring> // for strcmp
28 #include <fstream>
29 #include <iostream>
30 #include <map>
31 #include <sstream>
32 #include <string>
33 #include <utility> // for pair
34 #include <vector>
35 
37 
38 // root TFile compression level
39 static const int compression_level = 3;
40 
42 {
43  if (__instance)
44  {
45  return __instance;
46  }
47  __instance = new OnlMonServer("OnlMonServer");
48  return __instance;
49 }
50 
52  : OnlMonBase(name)
53 {
54 #ifdef USE_MUTEX
55  pthread_mutex_init(&mutex, nullptr);
56 #endif
58  statusDB = new OnlMonStatusDB();
59  RunStatusDB = new OnlMonStatusDB("onlmonrunstatus");
60  InitAll();
61  return;
62 }
63 
65 {
66 #ifdef USE_MUTEX
67  pthread_mutex_lock(&mutex);
68 #endif
69  if (int tret = pthread_cancel(serverthreadid))
70  {
71  std::cout << __PRETTY_FUNCTION__ << "pthread cancel returned error: " << tret << std::endl;
72  }
73  delete serverrunning;
74 
75 #ifdef USE_MUTEX
76  pthread_mutex_destroy(&mutex);
77 #endif
78  while (MonitorList.begin() != MonitorList.end())
79  {
80  delete MonitorList.back();
81  MonitorList.pop_back();
82  }
83  delete statusDB;
84  delete RunStatusDB;
85  while(MonitorHistoSet.begin() != MonitorHistoSet.end())
86  {
87  while(MonitorHistoSet.begin()->second.begin() != MonitorHistoSet.begin()->second.end())
88  {
89  if (CommonHistoMap.find(MonitorHistoSet.begin()->second.begin()->second->GetName()) == CommonHistoMap.end())
90  {
91  delete MonitorHistoSet.begin()->second.begin()->second;
92  }
93  else
94  {
95  if (Verbosity() > 2)
96  {
97  std::cout << "not deleting " << MonitorHistoSet.begin()->second.begin()->second->GetName() << std::endl;
98  }
99  }
100  MonitorHistoSet.begin()->second.erase(MonitorHistoSet.begin()->second.begin());
101  }
102  MonitorHistoSet.erase(MonitorHistoSet.begin());
103  }
104  while(CommonHistoMap.begin() != CommonHistoMap.end())
105  {
106  delete CommonHistoMap.begin()->second;
107  CommonHistoMap.erase(CommonHistoMap.begin());
108  }
109  while (MsgSystem.begin() != MsgSystem.end())
110  {
111  delete MsgSystem.begin()->second;
112  MsgSystem.erase(MsgSystem.begin());
113  }
114  return;
115 }
116 
118 {
119  if (gROOT->FindObject("ClientRunning"))
120  {
121  std::ostringstream msg;
122  msg << "Don't run Server and Client in same session, exiting";
123  send_message(MSG_SEV_FATAL, msg.str(), 1);
124  exit(1);
125  }
126  serverrunning = new TH1F("ServerRunning", "ServerRunning", 1, 0, 1);
127  return;
128 }
129 
131 {
132  TFile *hfile = TFile::Open(filename.c_str(), "RECREATE", "Created by Online Monitor");
133  for (auto &moniiter : MonitorHistoSet)
134  {
135  std::cout << "saving " << moniiter.first << std::endl;
136  for (auto &histiter : moniiter.second)
137  {
138  std::cout << "saving " << histiter.first << std::endl;
139  histiter.second->Write();
140  }
141  }
142  hfile->Close();
143  delete hfile;
144  return;
145 }
146 
148 {
149  CommonHistoMap.insert(std::make_pair(h1d->GetName(), h1d));
150  return;
151 }
152 
153 void OnlMonServer::registerHisto(const OnlMon *monitor, TH1 *h1d)
154 {
155  registerHisto(monitor->Name(), h1d->GetName(), h1d, 0);
156  return;
157 }
158 
159 void OnlMonServer::registerHisto(const std::string &monitorname, const std::string &hname, TH1 *h1d, const int replace)
160 {
161  if (hname.find(' ') != std::string::npos)
162  {
163  std::cout << "No empty spaces in registered histogram names : " << hname << std::endl;
164  exit(1);
165  }
166  auto moniiter = MonitorHistoSet.find(monitorname);
167  if (moniiter == MonitorHistoSet.end())
168  {
169  std::map<std::string, TH1 *> histo;
170  histo[hname] = h1d;
171  std::cout << __PRETTY_FUNCTION__ << " inserting " << monitorname << " hname " << hname << std::endl;
172  MonitorHistoSet.insert(std::make_pair(monitorname, histo));
173  return;
174  }
175  auto histoiter = moniiter->second.find(hname);
176  if (histoiter == moniiter->second.end())
177  {
178  moniiter->second.insert(std::make_pair(hname, h1d));
179  }
180  else
181  {
182  if (replace)
183  {
184  delete histoiter->second;
185  histoiter->second = h1d;
186  }
187  else
188  {
189  std::cout << "Histogram " << hname << " already registered with " << monitorname
190  << ", it will not be overwritten" << std::endl;
191  }
192  }
193  return;
194 }
195 
196 void OnlMonServer::registerHisto(const std::string &hname, TH1 *h1d, const int replace)
197 {
198  if (hname.find(' ') != std::string::npos)
199  {
200  std::cout << "No empty spaces in registered histogram names : " << hname << std::endl;
201  exit(1);
202  }
203  const std::string &tmpstr = hname;
204  std::map<const std::string, TH1 *>::const_iterator histoiter = CommonHistoMap.find(tmpstr);
205  std::ostringstream msg;
206  int histoexist;
207  TH1 *delhis;
208  if (histoiter != CommonHistoMap.end())
209  {
210  delhis = histoiter->second;
211  histoexist = 1;
212  }
213  else
214  {
215  delhis = nullptr;
216  histoexist = 0;
217  }
218  if (histoexist && replace == 0)
219  {
220  msg << "Histogram " << hname << " already registered, I won't overwrite it";
221  send_message(MSG_SEV_WARNING, msg.str(), 2);
222  msg.str("");
223  msg << "Use a different name and try again" << std::endl;
224  send_message(MSG_SEV_WARNING, msg.str(), 2);
225  }
226  else
227  {
228  if (verbosity > 1)
229  {
230  if (strcmp(h1d->GetName(), tmpstr.c_str()))
231  {
232  msg.str("");
233  msg << __PRETTY_FUNCTION__ << "Histogram " << h1d->GetName()
234  << " at " << h1d << " renamed to " << tmpstr;
235  send_message(MSG_SEV_INFORMATIONAL, msg.str(), 3);
236  }
237  }
238  CommonHistoMap[tmpstr] = h1d;
239  if (delhis)
240  {
241  delete delhis;
242  }
243  h1d->SetName(tmpstr.c_str());
244  }
245  return;
246 }
247 
248 OnlMon *
250 {
251  for (OnlMon *mon : MonitorList)
252  {
253  if (name == mon->Name())
254  {
255  return mon;
256  }
257  }
258  std::cout << "Could not locate monitor" << name << std::endl;
259  return nullptr;
260 }
261 
263 {
264  for (OnlMon *mon : MonitorList)
265  {
266  if (Monitor->Name() == mon->Name())
267  {
268  std::ostringstream msg;
269  msg << "Monitor " << Monitor->Name() << " already registered, I won't overwrite it";
270  send_message(MSG_SEV_SEVEREERROR, msg.str(), 4);
271  msg.str("");
272  msg << "Use a different name and try again";
273  send_message(MSG_SEV_SEVEREERROR, msg.str(), 4);
274  return;
275  }
276  }
277  MonitorList.push_back(Monitor);
278  MsgSystem[Monitor->Name()] = new MessageSystem(Monitor->Name());
279  Monitor->InitCommon(this);
280  Monitor->Init();
281  return;
282 }
283 
284 TH1 *OnlMonServer::getHisto(const unsigned int ihisto) const
285 {
286  std::map<const std::string, TH1 *>::const_iterator histoiter = CommonHistoMap.begin();
287  unsigned int size = CommonHistoMap.size();
288  if (Verbosity() > 3)
289  {
290  std::ostringstream msg;
291 
292  msg << "Map contains " << size << " Elements";
293  send_message(MSG_SEV_INFORMATIONAL, msg.str(), 5);
294  }
295  if (ihisto < size)
296  {
297  for (unsigned int i = 0; i < ihisto; i++)
298  {
299  ++histoiter;
300  }
301  return histoiter->second;
302  }
303  else
304  {
305  std::ostringstream msg;
306  msg << "OnlMonServer::getHisto: ERROR Invalid histogram number: "
307  << ihisto << ", maximum number is " << size;
308  send_message(MSG_SEV_ERROR, msg.str(), 6);
309  }
310  return nullptr;
311 }
312 
313 const std::string
314 OnlMonServer::getHistoName(const unsigned int ihisto) const
315 {
316  std::map<const std::string, TH1 *>::const_iterator histoiter = CommonHistoMap.begin();
317  unsigned int size = CommonHistoMap.size();
318  if (verbosity > 3)
319  {
320  std::ostringstream msg;
321  msg << "Map contains " << size << " Elements";
322  send_message(MSG_SEV_INFORMATIONAL, msg.str(), 5);
323  }
324  if (ihisto < size)
325  {
326  for (unsigned int i = 0; i < ihisto; i++)
327  {
328  ++histoiter;
329  }
330  return histoiter->first.c_str();
331  }
332  else
333  {
334  std::ostringstream msg;
335  msg << "OnlMonServer::getHisto: ERROR Invalid histogram number: "
336  << ihisto << ", maximum number is " << size;
337  send_message(MSG_SEV_ERROR, msg.str(), 6);
338  }
339  return nullptr;
340 }
341 
342 TH1 *OnlMonServer::getHisto(const std::string &subsys, const std::string &hname) const
343 {
344  if (Verbosity() > 2)
345  {
346  std::cout << __PRETTY_FUNCTION__ << " checking for subsys " << subsys << ", hname " << hname << std::endl;
347  }
348  auto moniiter = MonitorHistoSet.find(subsys);
349  if (moniiter != MonitorHistoSet.end())
350  {
351  auto histoiter = moniiter->second.find(hname);
352  if (histoiter != moniiter->second.end())
353  {
354  return histoiter->second;
355  }
356  }
357  std::ostringstream msg;
358 
359  msg << "OnlMonServer::getHisto: ERROR Unknown Histogram " << hname
360  << ", The following are implemented: ";
361  send_message(MSG_SEV_ERROR, msg.str(), 7);
362  Print("HISTOS");
363  return nullptr;
364 }
365 
367 {
368  std::map<const std::string, TH1 *>::const_iterator histoiter = CommonHistoMap.find(hname);
369  if (histoiter != CommonHistoMap.end())
370  {
371  return histoiter->second;
372  }
373  std::ostringstream msg;
374 
375  msg << "OnlMonServer::getHisto: ERROR Unknown Histogram " << hname
376  << ", The following are implemented: ";
377  send_message(MSG_SEV_ERROR, msg.str(), 7);
378  Print("HISTOS");
379  return nullptr;
380 }
381 
383 {
384  int iret = 0;
385  for (int i = 0; i < nevents; i++)
386  {
387  iret = process_event(nullptr);
388  if (iret)
389  {
390  break;
391  }
392  }
393  return iret;
394 }
395 
397 {
398  int i = 0;
399  std::vector<OnlMon *>::iterator iter;
400 
401  for (iter = MonitorList.begin(); iter != MonitorList.end(); ++iter)
402  {
403  i += (*iter)->process_event_common(evt);
404  }
405  for (iter = MonitorList.begin(); iter != MonitorList.end(); ++iter)
406  {
407  i += (*iter)->ResetEvent();
408  }
409 
410  return i;
411 }
412 
414 {
415  int i = 0;
416  std::vector<OnlMon *>::iterator iter;
417  for (iter = MonitorList.begin(); iter != MonitorList.end(); ++iter)
418  {
419  i += (*iter)->Reset();
420  }
421  std::map<const std::string, TH1 *>::const_iterator hiter;
422  for (auto &moniiter : MonitorHistoSet)
423  {
424  for (auto &histiter : moniiter.second)
425  {
426  histiter.second->Reset();
427  }
428  }
429 
430  for (hiter = CommonHistoMap.begin(); hiter != CommonHistoMap.end(); ++hiter)
431  {
432  hiter->second->Reset();
433  }
434  eventnumber = 0;
435  std::map<std::string, MessageSystem *>::const_iterator miter;
436  for (miter = MsgSystem.begin(); miter != MsgSystem.end(); ++miter)
437  {
438  miter->second->Reset();
439  }
440  return i;
441 }
442 
443 int OnlMonServer::BeginRun(const int runno)
444 {
445  int i = 0;
446  i = CacheRunDB(runno);
447  if (i)
448  {
449  printf("bad return code from CacheRunDB(%d): %d\n", runno, i);
450  i = 0;
451  }
452 
453  std::vector<OnlMon *>::iterator iter;
454  activepacketsinit = 0;
455  for (iter = MonitorList.begin(); iter != MonitorList.end(); ++iter)
456  {
457  (*iter)->BeginRunCommon(runno, this);
458  i += (*iter)->BeginRun(runno);
459  }
460  return i;
461 }
462 
463 int OnlMonServer::EndRun(const int runno)
464 {
465  int i = 0;
466  std::vector<OnlMon *>::iterator iter;
467  for (iter = MonitorList.begin(); iter != MonitorList.end(); ++iter)
468  {
469  i += (*iter)->EndRun(runno);
470  }
471  return i;
472 }
473 
474 void OnlMonServer::Print(const std::string &what, std::ostream& os) const
475 {
476  if (what == "ALL" || what == "PORT")
477  {
478  utsname ThisNode;
479  uname(&ThisNode);
480  os << "--------------------------------------" << std::endl << std::endl;
481  os << "Server running on " << ThisNode.nodename
482  << " and is listening on port " << PortNumber() << std::endl
483  << std::endl;
484  }
485  if (what == "ALL" || what == "HISTOS")
486  {
487  os << "--------------------------------------" << std::endl << std::endl;
488  os << "List of Assigned histograms in OnlMonServer:" << std::endl << std::endl;
489  for (auto &moniiter : MonitorHistoSet)
490  {
491  os << "Monitor " << moniiter.first << std::endl;
492  for (auto &histiter : moniiter.second)
493  {
494  os << moniiter.first << " " << histiter.first
495  << " at " << histiter.second << std::endl;
496  }
497  }
498  // loop over the map and print out the content (name and location in memory)
499  os << std::endl << "--------------------------------------" << std::endl << std::endl;
500  os << "List of Common Histograms in OnlMonServer" << std::endl;
501  for (auto &hiter : CommonHistoMap)
502  {
503  os << hiter.first << std::endl;
504  }
505  os << std::endl;
506  }
507  if (what == "ALL" || what == "MONITOR")
508  {
509  // loop over the map and print out the content (name and location in memory)
510  os << "--------------------------------------" << std::endl << std::endl;
511  os << "List of Monitors with registered histos in OnlMonServer:" << std::endl;
512 
513  for (auto &miter : MonitorList)
514  {
515  os << miter->Name() << std::endl;
516  }
517  os << std::endl;
518  }
519  if (what == "ALL" || what == "ACTIVE")
520  {
521  os << "--------------------------------------" << std::endl << std::endl;
522  os << "List of active packets:" << std::endl;
523  std::set<unsigned int>::const_iterator iter;
524  for (iter = activepackets.begin(); iter != activepackets.end(); ++iter)
525  {
526  os << *iter << std::endl;
527  }
528  }
529 return;
530 }
531 
533 {
534  std::ofstream fout(fname);
535  Print("ALL",fout);
536  fout.close();
537 }
538 
539 void OnlMonServer::RunNumber(const int irun)
540 {
541  runnumber = irun;
542  // recoConsts *rc = recoConsts::instance();
543  // rc->set_IntFlag("RUNNUMBER", irun);
544  return;
545 }
546 
548 {
549  for (auto &moniiter : MonitorHistoSet)
550  {
551  std::string dirname = "./";
552  if (getenv("ONLMON_SAVEDIR"))
553  {
554  dirname = std::string(getenv("ONLMON_SAVEDIR")) + "/";
555  }
556  std::string filename = dirname + "Run_" + std::to_string(RunNumber()) + "-" + moniiter.first + ".root";
557  if (Verbosity() > 2)
558  {
559  std::cout << "saving histos for " << moniiter.first << " in " << filename << std::endl;
560  }
561  TFile *hfile = TFile::Open(filename.c_str(), "RECREATE", "Created by Online Monitor");
562  for (auto &histiter : moniiter.second)
563  {
564  histiter.second->Write();
565  }
566  hfile->Close();
567  delete hfile;
568  }
569  return 0;
570 }
571 
572 int OnlMonServer::send_message(const OnlMon *Monitor, const int msgsource, const int severity, const std::string &err_message, const int msgtype) const
573 {
574  int iret = -1;
575  std::map<std::string, MessageSystem *>::const_iterator iter = MsgSystem.find(Monitor->Name());
576  std::ostringstream msg("Run ");
577  int irun = RunNumber();
578  msg << "Run " << irun << " Event# " << eventnumber << ": " << err_message;
579  if (iter != MsgSystem.end())
580  {
581  iret = iter->second->send_message(msgsource, severity, msg.str(), msgtype);
582  }
583  else
584  {
585  // in case there are messages from the ctor before the subsystem is registered
586  // print them out from the server
587  iter = MsgSystem.find(ThisName);
588  iret = iter->second->send_message(msgsource, severity, msg.str(), 0);
589  }
590  if (severity > MSG_SEV_WARNING)
591  {
592  WriteLogFile(Monitor->Name(), err_message);
593  }
594  return iret;
595 }
596 
597 int OnlMonServer::send_message(const int severity, const std::string &err_message, const int msgtype) const
598 {
599  std::map<std::string, MessageSystem *>::const_iterator iter = MsgSystem.find(ThisName);
600  int iret = iter->second->send_message(MSG_SOURCE_UNSPECIFIED, severity, err_message, msgtype);
601  return iret;
602 }
603 
605 {
606  int irun = RunNumber();
607  // if no run is opened yet, I don't want to produce a -1 file which will
608  // increase in size indefinitely
609  if (irun <= 0)
610  {
611  return 0;
612  }
613  // no logifles for junk and calibration runs
614  if (RunType == "JUNK" || RunType == "CALIBRATION")
615  {
616  return 0;
617  }
618  std::ostringstream logfilename, msg;
619  const char *logdir = getenv("ONLMON_LOGDIR");
620  if (logdir)
621  {
622  logfilename << logdir << "/";
623  }
624  logfilename << name << "_" << irun << ".log.gz";
625  gzFile fout = gzopen(logfilename.str().c_str(), "a9");
626  time_t curticks = CurrentTicks();
627  std::string timestr = ctime(&curticks);
628  std::string::size_type backslpos;
629  // get rid of this damn end line of ctime
630  if ((backslpos = timestr.find('\n')) != std::string::npos)
631  {
632  timestr.erase(backslpos);
633  }
634  msg << timestr
635  << ", EventNo " << eventnumber
636  << ": " << message;
637  gzprintf(fout, "%s\n", msg.str().c_str());
638  gzclose(fout);
639  return 0;
640 }
641 
642 int OnlMonServer::CacheRunDB(const int runnoinput)
643 {
644  int runno = -1;
645  if (runnoinput == 221)
646  {
647  runno = runnoinput;
648  }
649  else
650  {
651  runno = 221;
652  }
653  RunType = "PHYSICS";
654  standalone = 0;
655  cosmicrun = 0;
656  borticks = 0;
657  return 0;
658  odbc::Connection *con = nullptr;
659  odbc::Statement *query = nullptr;
660  std::ostringstream cmd;
661  int iret = 0;
662  try
663  {
664  con = odbc::DriverManager::getConnection("daq", "phnxrc", "");
665  }
666  catch (odbc::SQLException &e)
667  {
668  printf(" Exception caught during DriverManager::getConnection, Message: %s\n", e.getMessage().c_str());
669  return -1;
670  }
671 
672  query = con->createStatement();
673  cmd << "select runnumber from run where runnumber = " << runno;
674  odbc::ResultSet *rs = nullptr;
675  int ncount = 10;
676  while (ncount > 0)
677  {
678  try
679  {
680  rs = query->executeQuery(cmd.str());
681  }
682  catch (odbc::SQLException &e)
683  {
684  printf("Exception caught for query %s\nMessage: %s", cmd.str().c_str(), e.getMessage().c_str());
685  }
686  if (!rs->next())
687  {
688  printf("run table query did not give any result, run %d not in DB yet countdown %d\n", runno, ncount);
689  ncount--;
690  sleep(10);
691  delete rs;
692  }
693  else
694  {
695  delete rs;
696  break;
697  }
698  }
699  cmd.str("");
700  cmd << "SELECT runtype,triggerconfig,brunixtime FROM RUN WHERE RUNNUMBER = "
701  << runno;
702  if (verbosity > 0)
703  {
704  printf("command: %s\n", cmd.str().c_str());
705  }
706  try
707  {
708  rs = query->executeQuery(cmd.str());
709  }
710  catch (odbc::SQLException &e)
711  {
712  printf("Exception caught for query %s\nMessage: %s", cmd.str().c_str(), e.getMessage().c_str());
713  }
714  if (rs->next())
715  {
716  RunType = rs->getString("runtype");
717  TriggerConfig = rs->getString("triggerconfig");
718  borticks = rs->getInt("brunixtime");
719  if (TriggerConfig == "StandAloneMode")
720  {
721  standalone = 1;
722  }
723  else
724  {
725  standalone = 0;
726  }
727  if (TriggerConfig.find("Cosmic") != std::string::npos)
728  {
729  cosmicrun = 1;
730  }
731  else
732  {
733  cosmicrun = 0;
734  }
735  }
736  else
737  {
738  iret = -1;
739  }
740  delete con;
741  // printf("CacheRunDB: runno: %d, RunType %s\n",runno,RunType.c_str());
742  return iret;
743 }
744 
746 {
747  if (GetRunType() != "JUNK")
748  {
749  statusDB->UpdateStatus(Monitor->Name(), runnumber, status);
750  }
751  return 0;
752 }
753 
755 {
756  if (GetRunType() == "PHYSICS")
757  {
759  }
760  return 0;
761 }
762 
763 int OnlMonServer::LookAtMe(OnlMon *Monitor, const int level, const std::string &message)
764 {
765  std::cout << "got a LookAtMe from " << Monitor->Name()
766  << ", level: " << level
767  << ", message: " << message
768  << std::endl;
769  return 0;
770 }