Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:15:35

0001 #include "OnCalServer.h"
0002 #include "OnCal.h"
0003 #include "OnCalDBCodes.h"
0004 #include "OnCalHistoBinDefs.h"
0005 
0006 #include <fun4all/Fun4AllInputManager.h>
0007 #include <fun4all/Fun4AllReturnCodes.h>
0008 #include <fun4all/Fun4AllServer.h>  // for Fun4AllServer, Fun4AllServe...
0009 #include <fun4all/Fun4AllSyncManager.h>
0010 #include <fun4all/Fun4AllUtils.h>
0011 #include <fun4all/SubsysReco.h>  // for SubsysReco
0012 
0013 #include <phool/PHCompositeNode.h>
0014 #include <phool/PHTimeStamp.h>  // for PHTimeStamp, operator<<
0015 #include <phool/phool.h>
0016 #include <phool/recoConsts.h>
0017 
0018 #include <pdbcalbase/RunToTime.h>
0019 
0020 #include <RtypesCore.h>  // for Stat_t
0021 #include <TDirectory.h>  // for TDirectoryAtomicAdapter
0022 #include <TFile.h>
0023 #include <TH1.h>
0024 #include <TNamed.h>  // for TNamed
0025 #include <TROOT.h>
0026 #include <TString.h>  // for TString
0027 
0028 // odbc++ classes
0029 #include <odbc++/connection.h>
0030 #include <odbc++/drivermanager.h>
0031 #include <odbc++/preparedstatement.h>
0032 #include <odbc++/resultset.h>
0033 #include <odbc++/resultsetmetadata.h>
0034 #include <odbc++/statement.h>  // for Statement
0035 #include <odbc++/types.h>      // for SQLException, Timestamp
0036 
0037 #include <unistd.h>
0038 #include <algorithm>
0039 #include <cctype>  // for tolower
0040 #include <cstdlib>
0041 #include <cstring>  // for strcmp
0042 #include <iostream>
0043 #include <iterator>  // for reverse_iterator
0044 #include <list>
0045 #include <map>
0046 #include <sstream>
0047 #include <utility>  // for pair
0048 
0049 namespace
0050 {
0051   const std::string cvstag = "OnCalv86";
0052 
0053   odbc::Connection *DBconnection{nullptr};
0054 }  // namespace
0055 
0056 OnCalServer *OnCalServer::instance()
0057 {
0058   if (__instance)
0059   {
0060     OnCalServer *oncal = dynamic_cast<OnCalServer *>(__instance);
0061     return oncal;
0062   }
0063   __instance = new OnCalServer();
0064   OnCalServer *oncal = dynamic_cast<OnCalServer *>(__instance);
0065   return oncal;
0066 }
0067 
0068 //---------------------------------------------------------------------
0069 
0070 OnCalServer::OnCalServer(const std::string &name)
0071   : Fun4AllServer(name)
0072   , OnCalServerVars(new TH1D("OnCalServerVars", "OnCalServerVars", OnCalHistoBinDefs::LASTBINPLUSONE, -0.5, (int) (OnCalHistoBinDefs::LASTBINPLUSONE) -0.5))
0073 {
0074   beginTimeStamp.setTics(0);
0075   endTimeStamp.setTics(0);
0076 
0077   Fun4AllServer::registerHisto(OnCalServerVars);
0078   return;
0079 }
0080 //---------------------------------------------------------------------
0081 
0082 OnCalServer::~OnCalServer()
0083 {
0084   delete DBconnection;
0085   return;
0086 }
0087 //---------------------------------------------------------------------
0088 
0089 PHTimeStamp *
0090 OnCalServer::GetEndValidityTS()
0091 {
0092   if (endTimeStamp.getTics())
0093   {
0094     PHTimeStamp *ts = new PHTimeStamp(endTimeStamp);
0095     return ts;
0096   }
0097 
0098   std::cout << PHWHERE << "Screwup - the end validity time is not set" << std::endl;
0099   exit(1);
0100 }
0101 //---------------------------------------------------------------------
0102 
0103 PHTimeStamp *OnCalServer::GetBeginValidityTS()
0104 {
0105   if (beginTimeStamp.getTics())
0106   {
0107     PHTimeStamp *ts = new PHTimeStamp(beginTimeStamp);
0108     return ts;
0109   }
0110 
0111   std::cout << PHWHERE << "Screwup - the begin validity time is not set" << std::endl;
0112   exit(1);
0113 }
0114 //---------------------------------------------------------------------
0115 
0116 void OnCalServer::dumpHistos()
0117 {
0118   std::ostringstream filename;
0119   std::string fileprefix = "./";
0120 
0121   if (getenv("ONCAL_SAVEDIR"))
0122   {
0123     fileprefix = getenv("ONCAL_SAVEDIR");
0124     fileprefix += "/";
0125   }
0126 
0127   int compress = 3;
0128   std::map<std::string, std::set<std::string> >::const_iterator iter;
0129   //  std::map<std::string, TH1 *>::const_iterator hiter;
0130   TH1 *histo;
0131   std::set<std::string>::const_iterator siter;
0132   for (iter = calibratorhistomap.begin(); iter != calibratorhistomap.end(); ++iter)
0133   {
0134     filename.str("");
0135     filename << fileprefix << "Run_"
0136              << RunNumber()
0137              << "_" << iter->first << ".root";
0138     TFile *hfile = new TFile(filename.str().c_str(), "RECREATE",
0139                              "Created by Online Calibrator", compress);
0140     std::cout << "OnCalServer::dumpHistos() Output root file: " << filename.str() << std::endl;
0141     for (siter = (iter->second).begin(); siter != (iter->second).end(); ++siter)
0142     {
0143       histo = dynamic_cast<TH1 *>(getHisto(*siter));
0144       if (histo)
0145       {
0146         histo->Write();
0147       }
0148       else
0149       {
0150         std::cout << PHWHERE << "Histogram "
0151                   << *siter << " not found, will not be saved in "
0152                   << filename.str() << std::endl;
0153       }
0154     }
0155     hfile->Close();
0156 
0157     delete hfile;
0158   }
0159   return;
0160 }
0161 
0162 void OnCalServer::registerHisto(TH1 *h1d, OnCal *Calibrator, const int replace)
0163 {
0164   if (Calibrator)
0165   {
0166     std::string calibratorname = Calibrator->Name();
0167     std::map<std::string, std::set<std::string> >::iterator iter;
0168     iter = calibratorhistomap.find(calibratorname);
0169     if (iter != calibratorhistomap.end())
0170     {
0171       (iter->second).insert(h1d->GetName());
0172     }
0173     else
0174     {
0175       std::set<std::string> newset;
0176       newset.insert(h1d->GetName());
0177       newset.insert("OnCalServerVars");
0178       calibratorhistomap[calibratorname] = newset;
0179     }
0180   }
0181   Fun4AllServer::registerHisto(h1d, replace);
0182   return;
0183 }
0184 
0185 void OnCalServer::unregisterHisto(const std::string &calibratorname)
0186 {
0187   calibratorhistomap.erase(calibratorname);
0188   return;
0189 }
0190 
0191 int OnCalServer::process_event()
0192 {
0193   Fun4AllServer::process_event();
0194   int i = 0;
0195   nEvents++;
0196   if ((nEvents % eventcheckfrequency) == 0)  // check every 1000 events
0197   {
0198     std::cout << nEvents << " events, testing" << std::endl;
0199     unsigned int j = 0;
0200     unsigned int ical = 0;
0201     std::vector<std::pair<SubsysReco *, PHCompositeNode *> >::const_iterator iter;
0202     for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter)
0203     {
0204       OnCal *oncal = dynamic_cast<OnCal *>(iter->first);
0205       if (oncal)
0206       {
0207         ical++;
0208         std::cout << "Name: " << oncal->Name()
0209                   << " is " << oncal->AllDone() << std::endl;
0210         j += oncal->AllDone();
0211       }
0212     }
0213     if (j == ical)
0214     {
0215       std::cout << "Everyone is done after "
0216                 << nEvents << " Events" << std::endl;
0217       i = 1;
0218     }
0219   }
0220   return i;
0221 }
0222 
0223 int OnCalServer::BeginRun(const int runno)
0224 {
0225   if (runno <= 0)
0226   {
0227     std::cout << PHWHERE << "Invalid Run Number: " << runno << std::endl;
0228     exit(1);
0229   }
0230   FillRunListFromFileList();
0231   recoConsts *rc = recoConsts::instance();
0232   // we stick to the first runnumber, but after inheriting from
0233   // Fun4All we get a EndRun/BeginRun when the run number changes
0234   // so we have to catch this here
0235   if (RunNumber() != 0)
0236   {
0237     rc->set_IntFlag("RUNNUMBER", RunNumber());  // set rc flag back to previous run
0238     analysed_runs.push_back(runno);
0239     return 0;
0240   }
0241   RunNumber(runno);
0242   std::vector<std::pair<SubsysReco *, PHCompositeNode *> >::iterator iter;
0243   // copy the subsys reco pointers to another set for
0244   // easier search (we only need the pointers to find
0245   // the subsystems with special timestamp/runnumber needs
0246   std::set<SubsysReco *> NeedOtherTimeStamp;
0247   std::map<std::string, std::set<SubsysReco *> >::const_iterator miter;
0248   std::set<SubsysReco *>::const_iterator siter;
0249   for (miter = requiredCalibrators.begin();
0250        miter != requiredCalibrators.end(); ++miter)
0251   {
0252     for (siter = miter->second.begin(); siter != miter->second.end(); ++siter)
0253     {
0254       NeedOtherTimeStamp.insert(*siter);
0255     }
0256   }
0257 
0258   int iret;
0259   int i = 0;
0260   int oncalrun = runno;
0261   int fun4allrun = runno;
0262 
0263   RunToTime *runTime = RunToTime::instance();
0264   PHTimeStamp *ts = runTime->getBeginTime(fun4allrun);
0265   PHTimeStamp OnCalBORTimeStamp = *ts;
0266   PHTimeStamp Fun4AllBORTimeStamp(OnCalBORTimeStamp);
0267   delete ts;
0268   if (!requiredCalibrators.empty())
0269   {
0270     fun4allrun = FindClosestCalibratedRun(runno);
0271     ts = runTime->getBeginTime(fun4allrun);
0272     Fun4AllBORTimeStamp = *ts;
0273     delete ts;
0274   }
0275 
0276   // we have to do the same TDirectory games as in the Init methods
0277   // save the current dir, cd to the subsystem name dir (which was
0278   // created in init) call the InitRun of the module and cd back
0279 
0280   gROOT->cd(default_Tdirectory.c_str());
0281   std::string currdir = gDirectory->GetPath();
0282   std::set<std::string> droplist;
0283   for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter)
0284   {
0285     std::ostringstream newdirname;
0286     newdirname << (*iter).second->getName() << "/" << (*iter).first->Name();
0287     if (!gROOT->cd(newdirname.str().c_str()))
0288     {
0289       std::cout << PHWHERE << "Unexpected TDirectory Problem cd'ing to "
0290                 << (*iter).second->getName()
0291                 << " - send e-mail to off-l with your macro" << std::endl;
0292       exit(1);
0293     }
0294     OnCal *oncal = dynamic_cast<OnCal *>((*iter).first);
0295     if (oncal)
0296     {
0297       std::string table = "OnCal";
0298       table += (*iter).first->Name();
0299       check_create_subsystable(table);
0300       insertRunNumInDB(table, runNum);
0301       std::string calibname = (*iter).first->Name();
0302       add_calibrator_to_statustable(calibname);
0303       std::set<int>::const_iterator runiter;
0304       int calibstatus = GetCalibStatus(calibname, runNum);
0305       if (calibstatus > 0 && testmode == 0)
0306       {
0307         std::cout << calibname << " already ran for run " << runNum << std::endl;
0308         droplist.insert(calibname);
0309         unregisterSubsystem(oncal);
0310         unregisterHisto(calibname);
0311       }
0312       else
0313       {
0314         std::ostringstream stringarg;
0315         stringarg << OnCalDBCodes::STARTED;
0316         for (runiter = runlist.begin(); runiter != runlist.end(); ++runiter)
0317         {
0318           updateDB(successTable, calibname, stringarg.str(), *runiter);
0319         }
0320       }
0321     }
0322     if (NeedOtherTimeStamp.find((*iter).first) != NeedOtherTimeStamp.end())
0323     {
0324       std::cout << "changing timestamp for " << (*iter).first->Name() << std::endl;
0325       rc->set_IntFlag("RUNNUMBER", fun4allrun);
0326       // rc->set_TimeStamp(Fun4AllBORTimeStamp);
0327     }
0328     else
0329     {
0330       rc->set_IntFlag("RUNNUMBER", oncalrun);
0331       // rc->set_TimeStamp(OnCalBORTimeStamp);
0332     }
0333     if (droplist.find((*iter).first->Name()) == droplist.end())
0334     {
0335       iret = (*iter).first->InitRun(TopNode);
0336       if (iret == Fun4AllReturnCodes::ABORTRUN)
0337       {
0338         std::cout << PHWHERE << "Module " << (*iter).first->Name() << " issued Abort Run, exiting" << std::endl;
0339         exit(-1);
0340       }
0341       i += iret;
0342     }
0343   }
0344   gROOT->cd(currdir.c_str());
0345 
0346   rc->set_IntFlag("RUNNUMBER", oncalrun);
0347   //  rc->set_TimeStamp(OnCalBORTimeStamp);
0348   if (OnCalServerVars->GetBinContent(OnCalHistoBinDefs::FIRSTRUNBIN) == 0)
0349   {
0350     OnCalServerVars->SetBinContent(OnCalHistoBinDefs::FIRSTRUNBIN, runno);
0351     OnCalServerVars->SetBinContent(OnCalHistoBinDefs::BORTIMEBIN, (Stat_t) OnCalBORTimeStamp.getTics());
0352   }
0353   OnCalServerVars->SetBinContent(OnCalHistoBinDefs::LASTRUNBIN, (Stat_t) runno);
0354   ts = runTime->getEndTime(runno);
0355   if (ts)
0356   {
0357     OnCalServerVars->SetBinContent(OnCalHistoBinDefs::EORTIMEBIN, (Stat_t) ts->getTics());
0358     delete ts;
0359   }
0360 
0361   // disconnect from DB to save resources on DB machine
0362   // PdbCal leaves the DB connection open (PdbCal will reconnect without
0363   // problem if neccessary)
0364   DisconnectDB();
0365   // finally drop calibrators which have run already from module list
0366   unregisterSubsystemsNow();
0367   return i;
0368 }
0369 
0370 int OnCalServer::End()
0371 {
0372   if (nEvents == 0)
0373   {
0374     std::cout << "No Events read, you probably gave me an empty filelist" << std::endl;
0375     return -1;
0376   }
0377   int i = 0;
0378   std::vector<std::pair<SubsysReco *, PHCompositeNode *> >::iterator iter;
0379   gROOT->cd(default_Tdirectory.c_str());
0380   std::string currdir = gDirectory->GetPath();
0381 
0382   for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter)
0383   {
0384     std::ostringstream newdirname;
0385     newdirname << (*iter).second->getName() << "/" << (*iter).first->Name();
0386     if (!gROOT->cd(newdirname.str().c_str()))
0387     {
0388       std::cout << PHWHERE << "Unexpected TDirectory Problem cd'ing to "
0389                 << (*iter).second->getName()
0390                 << " - send e-mail to off-l with your macro" << std::endl;
0391       exit(1);
0392     }
0393     else
0394     {
0395       if (Verbosity() > 2)
0396       {
0397         std::cout << "End: cded to " << newdirname.str().c_str() << std::endl;
0398       }
0399     }
0400     i += (*iter).first->End((*iter).second);
0401   }
0402 
0403   gROOT->cd(default_Tdirectory.c_str());
0404   currdir = gDirectory->GetPath();
0405   for (iter = Subsystems.begin(); iter != Subsystems.end(); ++iter)
0406   {
0407     OnCal *oncal = dynamic_cast<OnCal *>((*iter).first);
0408     if (!oncal)
0409     {
0410       continue;
0411     }
0412     std::ostringstream newdirname;
0413     newdirname << (*iter).second->getName() << "/" << (*iter).first->Name();
0414     if (!gROOT->cd(newdirname.str().c_str()))
0415     {
0416       std::cout << PHWHERE << "Unexpected TDirectory Problem cd'ing to "
0417                 << (*iter).second->getName()
0418                 << " - send e-mail to off-l with your macro" << std::endl;
0419       exit(1);
0420     }
0421 
0422     std::string CalibratorName = oncal->Name();
0423 
0424     int verificationstatus = oncal->VerificationOK();
0425     int databasecommitstatus = oncal->CommitedToPdbCalOK();
0426 
0427     // report success database the status of the calibration
0428     if (recordDB)
0429     {
0430       std::string table = "OnCal";
0431       table += CalibratorName;
0432 
0433       std::ostringstream stringarg;
0434       if (databasecommitstatus == OnCalDBCodes::SUCCESS)
0435       {
0436         stringarg << OnCalDBCodes::COVERED;
0437       }
0438       else
0439       {
0440         stringarg << OnCalDBCodes::FAILED;
0441       }
0442       std::set<int>::const_iterator runiter;
0443       for (runiter = runlist.begin(); runiter != runlist.end(); ++runiter)
0444       {
0445         updateDB(successTable, CalibratorName, stringarg.str(), *runiter);
0446       }
0447       // update the first run which was used in the calibration
0448       // with the real status
0449       updateDB(successTable, CalibratorName, databasecommitstatus);
0450 
0451       stringarg.str("");
0452       stringarg << databasecommitstatus;
0453       updateDB(table, "committed", stringarg.str(), RunNumber());
0454 
0455       stringarg.str("");
0456       stringarg << verificationstatus;
0457       updateDB(table, "verified", stringarg.str(), RunNumber());
0458 
0459       odbc::Timestamp stp(time(nullptr));
0460       updateDB(table, "date", stp.toString(), RunNumber());
0461       updateDB(table, "comment", oncal->Comment(), RunNumber());
0462       time_t beginticks = beginTimeStamp.getTics();
0463       stringarg.str("");
0464       stringarg << beginticks;
0465       updateDB(table, "startvaltime", stringarg.str(), RunNumber());
0466       stp.setTime(beginticks);
0467       updateDB(table, "begintime", stp.toString(), RunNumber());
0468       time_t endticks = endTimeStamp.getTics();
0469       stringarg.str("");
0470       stringarg << endticks;
0471       updateDB(table, "endvaltime", stringarg.str(), RunNumber());
0472       stp.setTime(endticks);
0473       updateDB(table, "endtime", stp.toString(), RunNumber());
0474 
0475       std::string filelist;
0476       for (Fun4AllSyncManager *sync : SyncManagers)
0477       {
0478         for (Fun4AllInputManager *inmgr : sync->GetInputManagers())
0479         {
0480           for (const std::string &infile : inmgr->GetFileOpenedList())
0481           {
0482             filelist += (infile).substr(((infile).find_last_of('/') + 1), (infile).size());
0483             filelist += " ";  // this needs to be stripped again for last entry
0484           }
0485         }
0486       }
0487       filelist.pop_back();  // strip empty space at end from loop
0488       std::cout << "FileList: " << filelist << std::endl;
0489       updateDB(table, "files", filelist, RunNumber());
0490       updateDB(table, "cvstag", cvstag, RunNumber());
0491     }
0492 
0493     std::cout << "SERVER SUMMARY: " << oncal->Name() << "  "
0494               << (verificationstatus == 1 ? "Verification: SUCCESS  " : "Verification: FAILURE  ")
0495               << (databasecommitstatus == 1 ? "DB commit: SUCCESS  " : "DB commit: FAILURE  ")
0496               << std::endl;
0497 
0498     printStamps();
0499   }
0500   gROOT->cd(currdir.c_str());
0501   dumpHistos();  // save the histograms in files
0502   return i;
0503 }
0504 //---------------------------------------------------------------------
0505 
0506 void OnCalServer::Print(const std::string &what) const
0507 {
0508   Fun4AllServer::Print(what);
0509   if (what == "ALL" || what == "CALIBRATOR")
0510   {
0511     // loop over the map and print out the content
0512     // (name and location in memory)
0513 
0514     std::cout << "--------------------------------------" << std::endl
0515               << std::endl;
0516     std::cout << "List of Calibrators in OnCalServer:" << std::endl;
0517 
0518     std::vector<std::pair<SubsysReco *, PHCompositeNode *> >::const_iterator miter;
0519     for (miter = Subsystems.begin();
0520          miter != Subsystems.end(); ++miter)
0521     {
0522       OnCal *oncal = dynamic_cast<OnCal *>((*miter).first);
0523       if (oncal)
0524       {
0525         std::cout << oncal->Name() << std::endl;
0526       }
0527     }
0528     std::cout << std::endl;
0529   }
0530   if (what == "ALL" || what == "REQUIRED")
0531   {
0532     // loop over the map and print out the content
0533     // (name and location in memory)
0534 
0535     std::cout << "--------------------------------------" << std::endl
0536               << std::endl;
0537     std::cout << "List of required Calibrations in OnCalServer:" << std::endl;
0538 
0539     std::map<std::string, std::set<SubsysReco *> >::const_iterator iter;
0540     std::set<SubsysReco *>::const_iterator siter;
0541     for (iter = requiredCalibrators.begin();
0542          iter != requiredCalibrators.end(); ++iter)
0543     {
0544       std::cout << iter->first << " calibrations are needed by " << std::endl;
0545       for (siter = iter->second.begin(); siter != iter->second.end(); ++siter)
0546       {
0547         std::cout << (*siter)->Name() << std::endl;
0548       }
0549     }
0550     std::cout << std::endl;
0551   }
0552   if (what == "ALL" || what == "FILES")
0553   {
0554     std::cout << "--------------------------------------" << std::endl
0555               << std::endl;
0556     std::cout << "List of PRDF Files in OnCalServer:" << std::endl;
0557     for (Fun4AllSyncManager *sync : SyncManagers)
0558     {
0559       for (Fun4AllInputManager *inmgr : sync->GetInputManagers())
0560       {
0561         for (const std::string &infile : inmgr->GetFileList())
0562         {
0563           std::cout << "File: " << infile << std::endl;
0564         }
0565       }
0566     }
0567   }
0568   if (what == "ALL" || what == "RUNS")
0569   {
0570     std::cout << "--------------------------------------" << std::endl
0571               << std::endl;
0572     std::cout << "List of Run Numbers in OnCalServer:" << std::endl;
0573     std::set<int>::const_iterator liter;
0574     for (liter = runlist.begin(); liter != runlist.end(); ++liter)
0575     {
0576       std::cout << "Run : " << *liter << std::endl;
0577     }
0578   }
0579 
0580   return;
0581 }
0582 
0583 void OnCalServer::printStamps()
0584 {
0585   std::cout << std::endl
0586             << std::endl;
0587   std::cout << "*******************************************" << std::endl;
0588   std::cout << "*    VALIDITY RANGE FOR THIS CALIBRATION  *" << std::endl;
0589   std::cout << "*                                         *" << std::endl;
0590   std::cout << "* Used Run     :   ";
0591   std::cout << runNum << std::endl;
0592   std::cout << std::endl;
0593   std::cout << "* Begin Valid  :   ";
0594   beginTimeStamp.print();
0595   std::cout << std::endl;
0596   std::cout << "* End Valid    :   ";
0597   endTimeStamp.print();
0598   std::cout << std::endl;
0599   std::cout << "*                                         *" << std::endl;
0600   std::cout << "*******************************************" << std::endl;
0601   std::cout << std::endl
0602             << std::endl
0603             << std::endl;
0604 }
0605 
0606 //---------------------------------------------------------------------
0607 
0608 void OnCalServer::RunNumber(const int runnum)
0609 {
0610   runNum = runnum;
0611   SetBorTime(runnum);
0612   if (recordDB)
0613   {
0614     std::set<int>::const_iterator runiter;
0615     time_t beginrunticks;
0616     time_t endrunticks;
0617     std::ostringstream stringarg;
0618     odbc::Timestamp stp;
0619     for (runiter = runlist.begin(); runiter != runlist.end(); ++runiter)
0620     {
0621       insertRunNumInDB(successTable, *runiter);
0622       GetRunTimeTicks(*runiter, beginrunticks, endrunticks);
0623       stringarg.str("");
0624       stringarg << beginrunticks;
0625       updateDB(successTable, "startvaltime", stringarg.str(), *runiter);
0626       stp.setTime(beginrunticks);
0627       updateDB(successTable, "beginrun", stp.toString(), *runiter);
0628       stringarg.str("");
0629       stringarg << endrunticks;
0630       updateDB(successTable, "endvaltime", stringarg.str(), *runiter);
0631       stp.setTime(endrunticks);
0632       updateDB(successTable, "endrun", stp.toString(), *runiter);
0633     }
0634   }
0635   if (!runlist.empty())
0636   {
0637     SetEorTime(*runlist.rbegin());
0638   }
0639   return;
0640 }
0641 
0642 //---------------------------------------------------------------------
0643 
0644 bool OnCalServer::connectDB()
0645 {
0646   if (DBconnection)
0647   {
0648     return true;
0649   }
0650 
0651   bool failure = true;
0652   int countdown = 10;
0653   while (failure && countdown > 0)
0654   {
0655     failure = false;
0656     try
0657     {
0658       DBconnection =
0659           odbc::DriverManager::getConnection(database, "phnxrc", "");
0660     }
0661     catch (odbc::SQLException &e)
0662     {
0663       std::cout << "Cannot connect to " << database.c_str() << std::endl;
0664       std::cout << e.getMessage() << std::endl;
0665       std::cout << "countdown: " << countdown << std::endl;
0666       countdown--;
0667       failure = true;
0668       sleep(100);  // try again in 100 secs
0669     }
0670   }
0671   if (failure)
0672   {
0673     std::cout << "could not connect to DB after 10 tries in 1000 secs, giving up" << std::endl;
0674     exit(-1);
0675   }
0676   std::cout << "connected to " << database.c_str() << " database." << std::endl;
0677   return true;
0678 }
0679 //---------------------------------------------------------------------
0680 
0681 int OnCalServer::DisconnectDB()
0682 {
0683   delete DBconnection;
0684   DBconnection = nullptr;
0685   return 0;
0686 }
0687 //---------------------------------------------------------------------
0688 
0689 bool OnCalServer::insertRunNumInDB(const std::string &DBtable, const int runno)
0690 {
0691   if (findRunNumInDB(DBtable, runno))
0692   {
0693     return true;
0694   }
0695 
0696   std::cout << "new row will be created in DB for run " << runno << std::endl;
0697 
0698   odbc::Statement *statement = nullptr;
0699   statement = DBconnection->createStatement();
0700   std::ostringstream cmd;
0701   cmd << "INSERT INTO "
0702       << DBtable
0703       << " (runnumber) VALUES ("
0704       << runno << ")";
0705 
0706   if (Verbosity() == 1)
0707   {
0708     std::cout << "in function OnCalServer::insertRunNumInDB() ... ";
0709     std::cout << "executing SQL statements ..." << std::endl;
0710     std::cout << cmd.str() << std::endl;
0711   }
0712 
0713   try
0714   {
0715     statement->executeUpdate(cmd.str());
0716   }
0717   catch (odbc::SQLException &e)
0718   {
0719     std::cout << e.getMessage() << std::endl;
0720     return false;
0721   }
0722 
0723   return true;
0724 }
0725 
0726 //---------------------------------------------------------------------
0727 
0728 bool OnCalServer::findRunNumInDB(const std::string &DBtable, const int runno)
0729 {
0730   if (!DBconnection)
0731   {
0732     connectDB();
0733   }
0734   odbc::Statement *statement = nullptr;
0735   odbc::ResultSet *rs = nullptr;
0736   std::ostringstream cmd;
0737   cmd << "SELECT runnumber FROM "
0738       << DBtable
0739       << " WHERE runnumber = "
0740       << runno;
0741 
0742   statement = DBconnection->createStatement();
0743 
0744   if (Verbosity() == 1)
0745   {
0746     std::cout << "in function OnCalServer::findRunNumInDB() ";
0747     std::cout << "executing SQL statement ..." << std::endl
0748               << cmd.str() << std::endl;
0749   }
0750 
0751   try
0752   {
0753     rs = statement->executeQuery(cmd.str());
0754   }
0755   catch (odbc::SQLException &e)
0756   {
0757     std::cout << PHWHERE << " exception caught: " << e.getMessage() << std::endl;
0758     return false;
0759   }
0760 
0761   int entry = 0;
0762   if (rs->next())
0763   {
0764     try
0765     {
0766       entry = rs->getInt("runnumber");
0767     }
0768     catch (odbc::SQLException &e)
0769     {
0770       std::cout << PHWHERE << " exception caught: " << e.getMessage() << std::endl;
0771       return false;
0772     }
0773   }
0774   else
0775   {
0776     return false;
0777   }
0778   std::cout << "run number " << entry << " already exists in DB" << std::endl;
0779   return true;
0780 }
0781 
0782 bool OnCalServer::updateDBRunRange(const std::string &table, const std::string &column, const int entry, const int firstrun, const int lastrun)
0783 {
0784   if (!DBconnection)
0785   {
0786     connectDB();
0787   }
0788 
0789   odbc::Statement *statement = nullptr;
0790 
0791   std::string command = "UPDATE ";
0792   command += table;
0793   command += " SET ";
0794   command += column;
0795   command += " = ";
0796   command += std::to_string(entry);
0797   command += " WHERE runnumber >= ";
0798   command += std::to_string(firstrun);
0799   command += " and runnumber <= ";
0800   command += std::to_string(lastrun);
0801 
0802   if (Verbosity() == 1)
0803   {
0804     std::cout << "in function OnCalServer::updateDB() ... ";
0805     std::cout << "executin SQL statement ... " << std::endl;
0806     std::cout << command << std::endl;
0807   }
0808   statement = DBconnection->createStatement();
0809 
0810   try
0811   {
0812     statement->executeUpdate(command);
0813   }
0814   catch (odbc::SQLException &e)
0815   {
0816     std::cout << e.getMessage() << std::endl;
0817     return false;
0818   }
0819 
0820   return true;
0821 }
0822 
0823 //---------------------------------------------------------------------
0824 
0825 bool OnCalServer::updateDB(const std::string &table, const std::string &column, int entry)
0826 {
0827   if (!DBconnection)
0828   {
0829     connectDB();
0830   }
0831 
0832   odbc::Statement *statement = nullptr;
0833 
0834   TString command = "UPDATE ";
0835   command += table;
0836   command += " SET ";
0837   command += column;
0838   command += " = ";
0839   command += entry;
0840   command += " WHERE runnumber = ";
0841   command += runNum;
0842 
0843   if (Verbosity() == 1)
0844   {
0845     std::cout << "in function OnCalServer::updateDB() ... ";
0846     std::cout << "executin SQL statement ... " << std::endl;
0847     std::cout << command.Data() << std::endl;
0848   }
0849   statement = DBconnection->createStatement();
0850 
0851   try
0852   {
0853     statement->executeUpdate(command.Data());
0854   }
0855   catch (odbc::SQLException &e)
0856   {
0857     std::cout << e.getMessage() << std::endl;
0858     return false;
0859   }
0860 
0861   return true;
0862 }
0863 //---------------------------------------------------------------------
0864 
0865 bool OnCalServer::updateDB(const std::string &table, const std::string &column, bool entry)
0866 {
0867   if (!DBconnection)
0868   {
0869     connectDB();
0870   }
0871   odbc::Statement *statement = nullptr;
0872 
0873   TString command = "UPDATE ";
0874   command += table;
0875   command += " set ";
0876   command += column;
0877   command += " = '";
0878   command += static_cast<int>(entry);
0879   command += "' WHERE runnumber = ";
0880   command += runNum;
0881 
0882   if (Verbosity() == 1)
0883   {
0884     std::cout << "in function OnCalServer::updateDB() ... ";
0885     std::cout << "executin SQL statement ... " << std::endl;
0886     std::cout << command.Data() << std::endl;
0887   }
0888   statement = DBconnection->createStatement();
0889 
0890   try
0891   {
0892     statement->executeUpdate(command.Data());
0893   }
0894   catch (odbc::SQLException &e)
0895   {
0896     std::cout << e.getMessage() << std::endl;
0897     return false;
0898   }
0899 
0900   return true;
0901 }
0902 
0903 //---------------------------------------------------------------------
0904 
0905 int OnCalServer::updateDB(const std::string &table, const std::string &column,
0906                           const time_t ticks)
0907 {
0908   if (!DBconnection)
0909   {
0910     connectDB();
0911   }
0912   odbc::Statement *statement = nullptr;
0913 
0914   std::ostringstream cmd;
0915   statement = DBconnection->createStatement();
0916   cmd << "UPDATE "
0917       << table
0918       << " set "
0919       << column
0920       << " = "
0921       << ticks
0922       << " WHERE runnumber = "
0923       << runNum;
0924 
0925   if (Verbosity() == 1)
0926   {
0927     std::cout << "in function OnCalServer::updateDB() ... ";
0928     std::cout << "executin SQL statement ... " << std::endl;
0929     std::cout << cmd.str() << std::endl;
0930   }
0931 
0932   try
0933   {
0934     statement->executeUpdate(cmd.str());
0935   }
0936   catch (odbc::SQLException &e)
0937   {
0938     std::cout << e.getMessage() << std::endl;
0939     return -1;
0940   }
0941   return 0;
0942 }
0943 //---------------------------------------------------------------------
0944 
0945 bool OnCalServer::updateDB(const std::string &table, const std::string &column,
0946                            const std::string &entry, const int runno, const bool append)
0947 {
0948   if (!DBconnection)
0949   {
0950     connectDB();
0951   }
0952 
0953   odbc::Statement *statement = nullptr;
0954 
0955   statement = DBconnection->createStatement();
0956 
0957   std::string comment;
0958   std::ostringstream cmd;
0959   if (append)
0960   {
0961     odbc::ResultSet *rs = nullptr;
0962     std::ostringstream query;
0963     query << "SELECT * FROM "
0964           << table
0965           << " WHERE runnumber = "
0966           << runno;
0967 
0968     try
0969     {
0970       rs = statement->executeQuery(query.str());
0971     }
0972     catch (odbc::SQLException &e)
0973     {
0974       std::cout << "in function OnCalServer::updateDB() ... ";
0975       std::cout << "run number " << runno << "not found in DB" << std::endl;
0976       std::cout << e.getMessage() << std::endl;
0977     }
0978 
0979     rs->next();
0980     try
0981     {
0982       comment = rs->getString(column);
0983       comment += " ";  // add empty space between comments
0984     }
0985     catch (odbc::SQLException &e)
0986     {
0987       std::cout << "in function OnCalServer::updateDB() ... " << std::endl;
0988       std::cout << "nothing to append." << std::endl;
0989       std::cout << e.getMessage() << std::endl;
0990     }
0991     delete rs;
0992   }
0993 
0994   comment += entry;
0995   cmd << "UPDATE "
0996       << table
0997       << " set "
0998       << column
0999       << " = '"
1000       << comment
1001       << "' WHERE runnumber = "
1002       << runno;
1003 
1004   if (Verbosity() == 1)
1005   {
1006     std::cout << "in function OnCalServer::updateDB() ... ";
1007     std::cout << "executin SQL statement ... " << std::endl;
1008     std::cout << cmd.str() << std::endl;
1009   }
1010 
1011   try
1012   {
1013     statement->executeUpdate(cmd.str());
1014   }
1015   catch (odbc::SQLException &e)
1016   {
1017     std::cout << e.getMessage() << std::endl;
1018     return false;
1019   }
1020   delete statement;
1021   return true;
1022 }
1023 
1024 //---------------------------------------------------------------------
1025 
1026 int OnCalServer::check_create_subsystable(const std::string &tablename)
1027 {
1028   if (!connectDB())
1029   {
1030     std::cout << "could not connect to " << database << std::endl;
1031     return -1;
1032   }
1033   std::vector<std::pair<std::string, std::string> > calibrator_columns;
1034   std::vector<std::pair<std::string, std::string> >::const_iterator coliter;
1035   calibrator_columns.emplace_back("runnumber", "int NOT NULL");
1036   calibrator_columns.emplace_back("verified", "int default -2");
1037   calibrator_columns.emplace_back("committed", "int default -2");
1038   calibrator_columns.emplace_back("date", "timestamp(0) with time zone");
1039   calibrator_columns.emplace_back("comment", "text");
1040   calibrator_columns.emplace_back("files", "text");
1041   calibrator_columns.emplace_back("cvstag", "text");
1042   calibrator_columns.emplace_back("startvaltime", "bigint");
1043   calibrator_columns.emplace_back("endvaltime", "bigint");
1044   calibrator_columns.emplace_back("begintime", "timestamp(0) with time zone");
1045   calibrator_columns.emplace_back("endtime", "timestamp(0) with time zone");
1046 
1047   odbc::Statement *stmt = DBconnection->createStatement();
1048   std::ostringstream cmd;
1049   cmd << "SELECT * FROM " << tablename << " LIMIT 1" << std::ends;
1050   odbc::ResultSet *rs = nullptr;
1051   try
1052   {
1053     rs = stmt->executeQuery(cmd.str());
1054   }
1055   catch (odbc::SQLException &e)
1056   {
1057     std::cout << "Table " << tablename << " does not exist, will create it" << std::endl;
1058     //      std::cout << "Message: " << e.getMessage() << std::endl;
1059   }
1060   if (!rs)
1061   {
1062     cmd.str("");
1063     cmd << "CREATE TABLE "
1064         << tablename
1065         << "(";
1066     for (coliter = calibrator_columns.begin(); coliter != calibrator_columns.end(); ++coliter)
1067     {
1068       cmd << (*coliter).first << " " << (*coliter).second << ", ";
1069     }
1070 
1071     cmd << "primary key(runnumber))";
1072     stmt->executeUpdate(cmd.str());
1073   }
1074   else  // check if the all columns exist
1075   {
1076     for (coliter = calibrator_columns.begin(); coliter != calibrator_columns.end(); ++coliter)
1077     {
1078       try
1079       {
1080         rs->findColumn((*coliter).first);
1081       }
1082       catch (odbc::SQLException &e)
1083       {
1084         const std::string &exceptionmessage = e.getMessage();
1085         if (exceptionmessage.find("not found in result set") != std::string::npos)
1086         {
1087           std::cout << "Column " << (*coliter).first << " does not exist in "
1088                     << tablename << ", creating it" << std::endl;
1089           cmd.str("");
1090           cmd << "ALTER TABLE "
1091               << tablename
1092               << " ADD "
1093               << (*coliter).first
1094               << " "
1095               << (*coliter).second;
1096           try
1097           {
1098             odbc::Statement *stmtup = DBconnection->createStatement();
1099             stmtup->executeUpdate(cmd.str());
1100           }
1101           catch (odbc::SQLException &e1)
1102           {
1103             std::cout << PHWHERE << " Exception caught: " << e1.getMessage() << std::endl;
1104           }
1105         }
1106       }
1107     }
1108     delete rs;
1109   }
1110   return 0;
1111 }
1112 
1113 int OnCalServer::add_calibrator_to_statustable(const std::string &calibratorname)
1114 {
1115   if (!connectDB())
1116   {
1117     std::cout << "could not connect to " << database << std::endl;
1118     return -1;
1119   }
1120   if (check_calibrator_in_statustable(calibratorname) == 0)
1121   {
1122     return 0;
1123   }
1124   const std::string &calibname = calibratorname;
1125   odbc::Statement *stmt = DBconnection->createStatement();
1126   std::ostringstream cmd;
1127   cmd.str("");
1128   cmd << "ALTER TABLE " << successTable << " ADD COLUMN "
1129       << calibname << " int";
1130   try
1131   {
1132     stmt->executeUpdate(cmd.str());
1133   }
1134   catch (odbc::SQLException &e)
1135   {
1136     std::cout << "Message: " << e.getMessage() << std::endl;
1137     std::cout << "cmd: " << cmd.str() << std::endl;
1138     exit(1);
1139   }
1140   cmd.str("");
1141   cmd << "ALTER TABLE " << successTable << " ALTER COLUMN "
1142       << calibname << " SET DEFAULT " << OnCalDBCodes::INIT;
1143   try
1144   {
1145     stmt->executeUpdate(cmd.str());
1146   }
1147   catch (odbc::SQLException &e)
1148   {
1149     std::cout << "Message: " << e.getMessage() << std::endl;
1150     std::cout << "cmd: " << cmd.str() << std::endl;
1151     exit(1);
1152   }
1153   cmd.str("");
1154   cmd << "UPDATE " << successTable << " SET "
1155       << calibname << " = " << OnCalDBCodes::INIT;
1156   try
1157   {
1158     stmt->executeUpdate(cmd.str());
1159   }
1160   catch (odbc::SQLException &e)
1161   {
1162     std::cout << "Message: " << e.getMessage() << std::endl;
1163     std::cout << "cmd: " << cmd.str() << std::endl;
1164     exit(1);
1165   }
1166 
1167   return 0;
1168 }
1169 
1170 int OnCalServer::check_calibrator_in_statustable(const std::string &calibratorname)
1171 {
1172   // replace this contraption by this sql command which returns 1 row if column exists
1173   // select * from information_schema.columns where table_name = 'oncal_status' and column_name = 'svxstripdeadmapcal';
1174   if (!connectDB())
1175   {
1176     std::cout << "could not connect to " << database << std::endl;
1177     return -1;
1178   }
1179   std::string calibname = calibratorname;
1180   odbc::Statement *stmt = DBconnection->createStatement();
1181   std::ostringstream cmd;
1182   cmd << "SELECT * FROM " << successTable << " LIMIT 1" << std::ends;
1183   odbc::ResultSet *rs = nullptr;
1184   try
1185   {
1186     rs = stmt->executeQuery(cmd.str());
1187   }
1188   catch (odbc::SQLException &e)
1189   {
1190     std::cout << "Message: " << e.getMessage() << std::endl;
1191     std::cout << "Table " << successTable << " does not exist, your logic is off" << std::endl;
1192     exit(1);
1193   }
1194   odbc::ResultSetMetaData *meta = rs->getMetaData();
1195   unsigned int nocolumn = rs->getMetaData()->getColumnCount();
1196   // column names are lower case only, so convert string to lowercase
1197   // The bizarre cast here is needed for newer gccs
1198   transform(calibname.begin(), calibname.end(), calibname.begin(), (int (*)(int)) tolower);
1199 
1200   for (unsigned int i = 1; i <= nocolumn; i++)
1201   {
1202     if (meta->getColumnName(i) == calibname)
1203     {
1204       if (Verbosity() > 0)
1205       {
1206         std::cout << calibname << " is in " << successTable << std::endl;
1207       }
1208       return 0;
1209     }
1210   }
1211   // if we get here, the calibrator is not yet in the table
1212   delete rs;
1213   return -1;
1214 }
1215 
1216 int OnCalServer::check_create_successtable(const std::string &tablename)
1217 {
1218   if (!connectDB())
1219   {
1220     std::cout << "could not connect to " << database << std::endl;
1221     return -1;
1222   }
1223   odbc::Statement *stmt = DBconnection->createStatement();
1224   std::ostringstream cmd;
1225   cmd << "SELECT runnumber FROM " << tablename << " LIMIT 1" << std::ends;
1226   odbc::ResultSet *rs = nullptr;
1227   try
1228   {
1229     rs = stmt->executeQuery(cmd.str());
1230   }
1231   catch (odbc::SQLException &e)
1232   {
1233     std::cout << "Table " << tablename << " does not exist, will create it" << std::endl;
1234     //      std::cout << "Message: " << e.getMessage() << std::endl;
1235   }
1236   if (!rs)
1237   {
1238     cmd.str("");
1239     cmd << "CREATE TABLE " << tablename << "(runnumber int NOT NULL, "
1240         << "startvaltime bigint, "
1241         << "endvaltime bigint, "
1242         << "beginrun timestamp(0) with time zone, "
1243         << "endrun timestamp(0) with time zone, "
1244         << "comment text, "
1245         << "primary key(runnumber))";
1246     std::cout << cmd.str() << std::endl;
1247     try
1248     {
1249       stmt->executeUpdate(cmd.str());
1250     }
1251     catch (odbc::SQLException &e)
1252     {
1253       std::cout << "Error, Message: " << e.getMessage() << std::endl;
1254       //      std::cout << "Message: " << e.getMessage() << std::endl;
1255     }
1256   }
1257   return 0;
1258 }
1259 
1260 void OnCalServer::recordDataBase(const bool bookkeep)
1261 {
1262   recordDB = bookkeep;
1263   if (recordDB)
1264   {
1265     check_create_successtable(successTable);
1266   }
1267   return;
1268 }
1269 
1270 void OnCalServer::BeginTimeStamp(const PHTimeStamp &TimeStp)
1271 {
1272   beginTimeStamp = TimeStp;
1273   std::cout << "OnCalServer::BeginTimeStamp: Setting BOR TimeStamp to " << beginTimeStamp << std::endl;
1274 }
1275 
1276 void OnCalServer::EndTimeStamp(const PHTimeStamp &TimeStp)
1277 {
1278   endTimeStamp = TimeStp;
1279   std::cout << "OnCalServer::EndTimeStamp: Setting EOR TimeStamp to " << endTimeStamp << std::endl;
1280 }
1281 
1282 PHTimeStamp *
1283 OnCalServer::GetLastGoodRunTS(OnCal *calibrator, const int irun)
1284 {
1285   PHTimeStamp *ts = nullptr;
1286   if (!connectDB())
1287   {
1288     std::cout << "could not connect to " << database << std::endl;
1289     return ts;
1290   }
1291   odbc::Statement *stmt = DBconnection->createStatement();
1292   std::ostringstream cmd;
1293   std::ostringstream subsystable;
1294   subsystable << "oncal" << calibrator->Name();
1295   cmd << "SELECT runnumber FROM " << successTable << " where runnumber < "
1296       << irun << " and "
1297       << calibrator->Name() << " > 0 order by runnumber desc limit 1";
1298   odbc::ResultSet *rs = nullptr;
1299   try
1300   {
1301     rs = stmt->executeQuery(cmd.str());
1302   }
1303   catch (odbc::SQLException &e)
1304   {
1305     std::cout << "Table " << subsystable.str() << " does not exist" << std::endl;
1306     return ts;
1307   }
1308   if (rs->next())
1309   {
1310     RunToTime *rt = RunToTime::instance();
1311     int oldrun = rs->getInt("runnumber");
1312     ts = rt->getBeginTime(oldrun);
1313     std::cout << "Getting previous good run, current run: " << irun
1314               << ", previous good run: " << oldrun
1315               << " began ";
1316     ts->print();
1317     std::cout << std::endl;
1318   }
1319   else
1320   {
1321     std::cout << PHWHERE << " No previous good run found for run " << irun << std::endl;
1322   }
1323   delete rs;
1324   return ts;
1325 }
1326 
1327 int OnCalServer::SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const int commit)
1328 {
1329   std::vector<std::string> caltab;
1330   calibrator->GetPdbCalTables(caltab);
1331   std::vector<std::string>::const_iterator iter;
1332   for (iter = caltab.begin(); iter != caltab.end(); ++iter)
1333   {
1334     std::cout << "dealing with table: " << *iter << std::endl;
1335     SyncCalibTimeStampsToOnCal(calibrator, *iter, commit);
1336   }
1337   return 0;
1338 }
1339 
1340 int OnCalServer::SyncCalibTimeStampsToOnCal(const OnCal *calibrator, const std::string &table, const int commit)
1341 {
1342   std::string name = calibrator->Name();
1343   odbc::Connection *con = nullptr;
1344   odbc::Connection *concalib = nullptr;
1345   std::ostringstream cmd;
1346   try
1347   {
1348     con = odbc::DriverManager::getConnection(database, "phnxrc", "");
1349   }
1350   catch (odbc::SQLException &e)
1351   {
1352     std::cout << "Cannot connect to " << database.c_str() << std::endl;
1353     std::cout << e.getMessage() << std::endl;
1354     return -1;
1355   }
1356   try
1357   {
1358     concalib = odbc::DriverManager::getConnection("oncal", "phnxrc", "");
1359   }
1360   catch (odbc::SQLException &e)
1361   {
1362     std::cout << "Cannot connect to "
1363               << "oncal" << std::endl;
1364     std::cout << e.getMessage() << std::endl;
1365     return -1;
1366   }
1367   odbc::Statement *stmt = nullptr;
1368   try
1369   {
1370     stmt = con->createStatement();
1371   }
1372   catch (odbc::SQLException &e)
1373   {
1374     std::cout << "Cannot create statement" << std::endl;
1375     std::cout << e.getMessage() << std::endl;
1376     return -1;
1377   }
1378 
1379   odbc::PreparedStatement *stmt1 = nullptr;
1380   odbc::ResultSet *rs1 = nullptr;
1381   try
1382   {
1383     cmd.str("");
1384     cmd << "SELECT * from " << table << " where startvaltime = ?";
1385     stmt1 = concalib->prepareStatement(cmd.str());
1386   }
1387   catch (odbc::SQLException &e)
1388   {
1389     std::cout << "Cannot create statement" << std::endl;
1390     std::cout << e.getMessage() << std::endl;
1391     return -1;
1392   }
1393 
1394   odbc::PreparedStatement *stmtupd = nullptr;
1395   try
1396   {
1397     cmd.str("");
1398     cmd << "update " << table << " set endvaltime = ? where startvaltime = ?";
1399     stmtupd = concalib->prepareStatement(cmd.str());
1400   }
1401   catch (odbc::SQLException &e)
1402   {
1403     std::cout << "Cannot create statement" << std::endl;
1404     std::cout << e.getMessage() << std::endl;
1405     return -1;
1406   }
1407 
1408   cmd.str("");
1409   cmd << "select * from "
1410       << successTable
1411       << " where "
1412       << name
1413       << " > 0";
1414   //      << " > 0 and runnumber < 150000";
1415   odbc::ResultSet *rs = nullptr;
1416   try
1417   {
1418     rs = stmt->executeQuery(cmd.str());
1419   }
1420   catch (odbc::SQLException &e)
1421   {
1422     std::cout << "Message: " << e.getMessage() << std::endl;
1423     return -1;
1424   }
1425   while (rs->next())
1426   {
1427     int run = rs->getInt("runnumber");
1428     int startticks = rs->getLong("startvaltime");
1429     int endticks = rs->getLong("endvaltime");
1430     // int status = rs->getInt(name);
1431     //       std::cout << "run: " << run
1432     //     << ", status: " << status
1433     //     << ", startticks: " << startticks
1434     //     << ", endticks: " << endticks << std::endl;
1435     stmt1->setInt(1, startticks);
1436     try
1437     {
1438       rs1 = stmt1->executeQuery();
1439     }
1440     catch (odbc::SQLException &e)
1441     {
1442       std::cout << "Message: " << e.getMessage() << std::endl;
1443       return -1;
1444     }
1445     int ionce = 0;
1446     int isproblem = 0;
1447     int calibendval = 0;
1448     while (rs1->next())
1449     {
1450       calibendval = rs1->getInt("endvaltime");
1451       if (endticks != rs1->getInt("endvaltime"))
1452       {
1453         if (!isproblem)
1454         {
1455           std::cout << "endvaltime problem with run " << run << std::endl;
1456           std::cout << "endvaltime from oncal_status: " << endticks << std::endl;
1457           std::cout << "startvaltime from oncal_status: " << startticks << std::endl;
1458           std::cout << "endvaltime from calibrations DB: " << rs1->getInt("endvaltime") << std::endl;
1459           if (endticks < rs1->getInt("endvaltime"))
1460           {
1461             std::cout << "ENDTICKS smaller CALIB" << std::endl;
1462             //                      return -1;
1463           }
1464         }
1465         isproblem = 1;
1466       }
1467       else
1468       {
1469         if (isproblem)
1470         {
1471           std::cout << "endvaltime changes, check run " << run << std::endl;
1472           //                  return -1;
1473         }
1474       }
1475       //       std::cout << "starttime: " << rs1->getInt("startvaltime") << std::endl;
1476       //       std::cout << "endtime: " << rs1->getInt("endvaltime") << std::endl;
1477       ionce++;
1478     }
1479     if (isproblem)
1480     {
1481       std::cout << "Adjusting run " << run << std::endl;
1482       std::cout << "changing endvaltime from " << calibendval
1483                 << " to " << endticks << std::endl;
1484       if (commit)
1485       {
1486         stmtupd->setInt(1, endticks);
1487         stmtupd->setInt(2, startticks);
1488         stmtupd->executeUpdate();
1489       }
1490     }
1491     if (!ionce)
1492     {
1493       std::cout << "Run " << run << " not found" << std::endl;
1494     }
1495     delete rs1;
1496   }
1497   delete rs;
1498   delete con;
1499   delete concalib;
1500   return 0;
1501 }
1502 
1503 int OnCalServer::SyncOncalTimeStampsToRunDB(const int commit)
1504 {
1505   odbc::Connection *con = nullptr;
1506   RunToTime *rt = RunToTime::instance();
1507   std::ostringstream cmd;
1508   try
1509   {
1510     con = odbc::DriverManager::getConnection(database, "phnxrc", "");
1511   }
1512   catch (odbc::SQLException &e)
1513   {
1514     std::cout << "Cannot connect to " << database.c_str() << std::endl;
1515     std::cout << e.getMessage() << std::endl;
1516     return -1;
1517   }
1518   odbc::Statement *stmt = nullptr;
1519   try
1520   {
1521     stmt = con->createStatement();
1522   }
1523   catch (odbc::SQLException &e)
1524   {
1525     std::cout << "Cannot create statement" << std::endl;
1526     std::cout << e.getMessage() << std::endl;
1527     return -1;
1528   }
1529 
1530   odbc::PreparedStatement *stmtupd = nullptr;
1531   try
1532   {
1533     cmd.str("");
1534     cmd << "UPDATE oncal_status set endvaltime = ? where runnumber = ?";
1535     stmtupd = con->prepareStatement(cmd.str());
1536   }
1537   catch (odbc::SQLException &e)
1538   {
1539     std::cout << "Cannot create statement" << std::endl;
1540     std::cout << e.getMessage() << std::endl;
1541     return -1;
1542   }
1543 
1544   cmd.str("");
1545   cmd << "select * from "
1546       << successTable;  //<< " where runnumber > 160000";
1547   odbc::ResultSet *rs = nullptr;
1548   try
1549   {
1550     rs = stmt->executeQuery(cmd.str());
1551   }
1552   catch (odbc::SQLException &e)
1553   {
1554     std::cout << "Message: " << e.getMessage() << std::endl;
1555     return -1;
1556   }
1557   while (rs->next())
1558   {
1559     int run = rs->getInt("runnumber");
1560     int startticks = rs->getLong("startvaltime");
1561     int endticks = rs->getLong("endvaltime");
1562     int rtstartticks = 0;
1563     int rtendticks = 0;
1564     PHTimeStamp *rtstart = rt->getBeginTime(run);
1565     PHTimeStamp *rtend = rt->getEndTime(run);
1566     if (rtstart)
1567     {
1568       rtstartticks = rtstart->getTics();
1569       delete rtstart;
1570     }
1571     if (rtend)
1572     {
1573       rtendticks = rtend->getTics();
1574       delete rtend;
1575     }
1576     if (rtstartticks != startticks)
1577     {
1578       std::cout << "Run " << run
1579                 << ": Start mismatch, oncal: " << startticks
1580                 << ", rt: " << rtstartticks << std::endl;
1581     }
1582     if (rtendticks != endticks)
1583     {
1584       // exclude starttime=endtime in runtotime (some crashed calibrations can do this)
1585       // in this case the calibration adds 1 sec to starttime
1586       if (rtstartticks != rtendticks)
1587       {
1588         std::cout << "Run " << run
1589                   << ": End mismatch, oncal: " << endticks
1590                   << ", rt: " << rtendticks << std::endl;
1591         if (endticks > rtendticks)
1592         {
1593           std::cout << "BAD: endticks: " << endticks
1594                     << ", rtendticks: " << rtendticks
1595                     << std::endl;
1596           return -1;
1597         }
1598         if (commit)
1599         {
1600           stmtupd->setLong(1, rtendticks);
1601           stmtupd->setLong(2, run);
1602           stmtupd->executeUpdate();
1603         }
1604       }
1605       else
1606       {
1607         if (startticks != endticks - 1)
1608         {
1609           std::cout << "Run " << run
1610                     << ": Start/End mismatch, Start: " << startticks
1611                     << ", End: " << endticks << std::endl;
1612           endticks = startticks + 1;
1613           if (commit)
1614           {
1615             stmtupd->setLong(1, endticks);
1616             stmtupd->setLong(2, run);
1617             stmtupd->executeUpdate();
1618           }
1619         }
1620         else
1621         {
1622           if (Verbosity() > 0)
1623           {
1624             std::cout << "run " << run << " was twiddled by OnCal" << std::endl;
1625           }
1626         }
1627       }
1628     }
1629     //       std::cout << "run: " << run
1630     //     << ", status: " << status
1631     //     << ", startticks: " << startticks
1632     //     << ", endticks: " << endticks << std::endl;
1633   }
1634   delete rs;
1635   delete con;
1636   return 0;
1637 }
1638 
1639 int OnCalServer::CopyTables(const OnCal *calibrator, const int FromRun, const int ToRun, const int commit)
1640 {
1641   int iret = calibrator->CopyTables(FromRun, ToRun, commit);
1642   return iret;
1643 }
1644 
1645 int OnCalServer::CreateCalibration(OnCal *calibrator, const int myrunnumber, const std::string &what, const int commit)
1646 {
1647   int iret = -1;
1648   runNum = myrunnumber;
1649   SetBorTime(myrunnumber);
1650   SetEorTime(myrunnumber);
1651   if (!connectDB())
1652   {
1653     std::cout << "could not connect to " << database << std::endl;
1654     return -1;
1655   }
1656   add_calibrator_to_statustable(calibrator->Name());
1657   std::string table = "OnCal";
1658   table += calibrator->Name();
1659   check_create_subsystable(table);
1660   odbc::Statement *stmt = DBconnection->createStatement();
1661   std::ostringstream cmd;
1662 
1663   cmd << "SELECT runnumber FROM "
1664       << successTable << " where runnumber = "
1665       << myrunnumber;
1666   odbc::ResultSet *rs = nullptr;
1667   try
1668   {
1669     rs = stmt->executeQuery(cmd.str());
1670   }
1671   catch (odbc::SQLException &e)
1672   {
1673     std::cout << "Table " << successTable << " does not exist" << std::endl;
1674     return -1;
1675   }
1676   if (!rs->next())
1677   {
1678     insertRunNumInDB(successTable, myrunnumber);
1679   }
1680   delete rs;
1681   cmd.str("");
1682   cmd << "SELECT runnumber FROM "
1683       << successTable << " where runnumber = "
1684       << myrunnumber << " and "
1685       << calibrator->Name() << " <= 0";
1686   try
1687   {
1688     rs = stmt->executeQuery(cmd.str());
1689   }
1690   catch (odbc::SQLException &e)
1691   {
1692     std::cout << PHWHERE << " Exception caught, Message: "
1693               << e.getMessage() << std::endl;
1694     return -1;
1695   }
1696   if (rs->next() || testmode)
1697   {
1698     std::string tablecomment = "Subsytem provided";
1699     iret = calibrator->CreateCalibration(runnumber, what, tablecomment, commit);
1700     if (!iret)
1701     {
1702       std::cout << "Comment: " << tablecomment << std::endl;
1703       std::cout << "updating oncal status tables for " << runnumber << std::endl;
1704       if (commit)
1705       {
1706         CreateCalibrationUpdateStatus(calibrator, table, tablecomment, OnCalDBCodes::SUBSYSTEM);
1707       }
1708     }
1709     else
1710     {
1711       std::cout << "Calibratior " << calibrator->Name() << " for run " << runnumber << " failed" << std::endl;
1712       if (commit)
1713       {
1714         CreateCalibrationUpdateStatus(calibrator, table, tablecomment, OnCalDBCodes::FAILED);
1715       }
1716     }
1717   }
1718   else
1719   {
1720     std::cout << PHWHERE << " Run " << runnumber << " is already successfully calibrated for "
1721               << calibrator->Name() << std::endl;
1722   }
1723   return iret;
1724 }
1725 
1726 void OnCalServer::CreateCalibrationUpdateStatus(OnCal *calibrator, const std::string &table, const std::string &tablecomment, const int dbcode)
1727 {
1728   updateDB(successTable, calibrator->Name(), dbcode);
1729   insertRunNumInDB(table, RunNumber());
1730   updateDB(table, "comment", tablecomment, RunNumber(), true);
1731   std::ostringstream stringarg;
1732   stringarg.str("");
1733   stringarg << calibrator->CommitedToPdbCalOK();
1734   updateDB(table, "committed", stringarg.str(), RunNumber());
1735   stringarg.str("");
1736   stringarg << calibrator->VerificationOK();
1737   updateDB(table, "verified", stringarg.str(), RunNumber());
1738   odbc::Timestamp stp(time(nullptr));
1739   updateDB(table, "date", stp.toString(), RunNumber());
1740   time_t beginticks = beginTimeStamp.getTics();
1741   stringarg.str("");
1742   stringarg << beginticks;
1743   updateDB(table, "startvaltime", stringarg.str(), RunNumber());
1744   stp.setTime(beginticks);
1745   updateDB(table, "begintime", stp.toString(), RunNumber());
1746   time_t endticks = endTimeStamp.getTics();
1747   stringarg.str("");
1748   stringarg << endticks;
1749   updateDB(table, "endvaltime", stringarg.str(), RunNumber());
1750   stp.setTime(endticks);
1751   updateDB(table, "endtime", stp.toString(), RunNumber());
1752   updateDB(table, "cvstag", cvstag, RunNumber());
1753   std::vector<std::string> flist = calibrator->GetLocalFileList();
1754   if (!flist.empty())
1755   {
1756     std::string filelist;
1757     for (const std::string &infile : flist)
1758     {
1759       filelist += infile;
1760       filelist += " ";
1761     }
1762     filelist.pop_back();  // strip empty space at end from loop
1763     std::cout << "FileList: " << filelist << std::endl;
1764     updateDB(table, "files", filelist, RunNumber());
1765   }
1766   return;
1767 }
1768 
1769 int OnCalServer::ClosestGoodRun(OnCal *calibrator, const int irun, const int previous)
1770 {
1771   RunToTime *rt = RunToTime::instance();
1772   PHTimeStamp *ts = rt->getBeginTime(irun);
1773   if (!ts)
1774   {
1775     std::cout << PHWHERE << "Unknown Run " << irun << std::endl;
1776     return -1;
1777   }
1778   int curstart = ts->getTics();
1779   delete ts;
1780   ts = rt->getEndTime(irun);
1781   int curend = curstart;
1782   if (ts)
1783   {
1784     curend = ts->getTics();
1785     delete ts;
1786   }
1787   int closestrun = -1;
1788   if (!connectDB())
1789   {
1790     std::cout << "could not connect to " << database << std::endl;
1791     return -1;
1792   }
1793   odbc::Statement *stmt = DBconnection->createStatement();
1794   std::ostringstream cmd;
1795 
1796   // look only for runs which were actually successfully calibrated (status = 1)
1797   cmd << "SELECT runnumber,startvaltime,endvaltime FROM "
1798       << successTable << " where runnumber < "
1799       << irun << " and "
1800       << calibrator->Name() << " = 1 order by runnumber desc limit 1";
1801   odbc::ResultSet *rs = nullptr;
1802   try
1803   {
1804     rs = stmt->executeQuery(cmd.str());
1805   }
1806   catch (odbc::SQLException &e)
1807   {
1808     std::cout << "Table " << successTable << " does not exist" << std::endl;
1809     return -1;
1810   }
1811   int prevrun = -1;
1812   unsigned int prevend = 0;
1813   if (rs->next())
1814   {
1815     prevrun = rs->getInt("runnumber");
1816     unsigned int prevstart = rs->getLong("startvaltime");
1817     prevend = rs->getLong("endvaltime");
1818     std::cout << "previous run: " << prevrun
1819               << ", start: " << prevstart
1820               << ", end: " << prevend
1821               << std::endl;
1822   }
1823   else
1824   {
1825     if (Verbosity() > 0)
1826     {
1827       std::cout << PHWHERE << " No previous good run found for run " << irun << std::endl;
1828     }
1829   }
1830   delete rs;
1831   closestrun = prevrun;
1832   if (previous == fetchrun::PREVIOUS)
1833   {
1834     if (Verbosity() > 0)
1835     {
1836       std::cout << "Closest previous run is " << closestrun << std::endl;
1837     }
1838     return closestrun;
1839   }
1840   cmd.str("");
1841   cmd << "SELECT runnumber,startvaltime,endvaltime FROM "
1842       << successTable << " where runnumber > "
1843       << irun << " and "
1844       << calibrator->Name() << " = 1 order by runnumber asc limit 1";
1845   try
1846   {
1847     rs = stmt->executeQuery(cmd.str());
1848   }
1849   catch (odbc::SQLException &e)
1850   {
1851     std::cout << "Table " << successTable << " does not exist" << std::endl;
1852     return -1;
1853   }
1854   int nextrun = -1;
1855   unsigned int nextstart = 0;
1856   if (rs->next())
1857   {
1858     nextrun = rs->getInt("runnumber");
1859     nextstart = rs->getLong("startvaltime");
1860     unsigned int nextend = rs->getLong("endvaltime");
1861     if (Verbosity() > 0)
1862     {
1863       std::cout << "next run: " << nextrun
1864                 << ", start: " << nextstart
1865                 << ", end: " << nextend
1866                 << std::endl;
1867     }
1868   }
1869   else
1870   {
1871     if (Verbosity() > 0)
1872     {
1873       std::cout << PHWHERE << " No next good run found for run " << irun << std::endl;
1874     }
1875   }
1876   delete rs;
1877   int tdiffprev = curstart - prevend;
1878   int tdiffnext;
1879   if (nextstart > 0)
1880   {
1881     tdiffnext = nextstart - curend;
1882   }
1883   else
1884   {
1885     // just make it larger then previous run time diff
1886     tdiffnext = tdiffprev + 1;
1887   }
1888   if (Verbosity() > 0)
1889   {
1890     std::cout << "diff prev: " << tdiffprev
1891               << ", next: " << tdiffnext
1892               << std::endl;
1893   }
1894   if (tdiffprev < tdiffnext)
1895   {
1896     closestrun = prevrun;
1897   }
1898   else
1899   {
1900     closestrun = nextrun;
1901   }
1902   if (Verbosity() > 0)
1903   {
1904     std::cout << "closest run: " << closestrun << std::endl;
1905   }
1906   return closestrun;
1907 }
1908 
1909 int OnCalServer::OverwriteCalibration(OnCal *calibrator, const int runno, const int commit, const int FromRun)
1910 {
1911   if (FromRun < 0)
1912   {
1913     return -1;
1914   }
1915   int iret = CopyTables(calibrator, FromRun, runno, commit);
1916   return iret;
1917 }
1918 
1919 int OnCalServer::FixMissingCalibration(OnCal *calibrator, const int runno, const int commit, const int fromrun)
1920 {
1921   int iret = -1;
1922   // find this run in oncal_status
1923   if (!connectDB())
1924   {
1925     std::cout << "could not connect to " << database << std::endl;
1926     return -1;
1927   }
1928   runNum = runno;
1929   odbc::Statement *stmt = DBconnection->createStatement();
1930   std::ostringstream cmd;
1931 
1932   cmd << "SELECT runnumber FROM "
1933       << successTable << " where runnumber = "
1934       << runno;
1935   odbc::ResultSet *rs = nullptr;
1936   try
1937   {
1938     rs = stmt->executeQuery(cmd.str());
1939   }
1940   catch (odbc::SQLException &e)
1941   {
1942     std::cout << "Table " << successTable << " does not exist" << std::endl;
1943     return -1;
1944   }
1945   if (!rs->next())
1946   {
1947     insertRunNumInDB(successTable, runNum);
1948   }
1949   delete rs;
1950   cmd.str("");
1951   cmd << "SELECT runnumber FROM "
1952       << successTable << " where runnumber = "
1953       << runno << " and "
1954       << calibrator->Name() << " <= 0";
1955   try
1956   {
1957     rs = stmt->executeQuery(cmd.str());
1958   }
1959   catch (odbc::SQLException &e)
1960   {
1961     std::cout << PHWHERE << " Exception caught, Message: "
1962               << e.getMessage() << std::endl;
1963     return -1;
1964   }
1965   if (rs->next())
1966   {
1967     int FromRun;
1968     if (fromrun > 0)
1969     {
1970       FromRun = fromrun;
1971     }
1972     else
1973     {
1974       FromRun = ClosestGoodRun(calibrator, runno);
1975       if (FromRun < 0)
1976       {
1977         std::cout << "ClosestGoodRun returned bad runnumber: " << FromRun << std::endl;
1978         return -1;
1979       }
1980     }
1981     std::cout << "Going to copy calibration for run " << runno
1982               << " from run " << FromRun << std::endl;
1983 
1984     iret = OverwriteCalibration(calibrator, runno, commit, FromRun);
1985     if (!iret)
1986     {
1987       int newstatus = 0;
1988       if (FromRun < runno)
1989       {
1990         newstatus = OnCalDBCodes::COPIEDPREVIOUS;
1991       }
1992       else
1993       {
1994         newstatus = OnCalDBCodes::COPIEDLATER;
1995       }
1996       std::string table = "OnCal";
1997       table += calibrator->Name();
1998       std::ostringstream comment;
1999       comment << " CopiedRun(" << FromRun << ")";
2000       std::cout << "updating oncal status tables for " << runno << std::endl;
2001       if (commit)
2002       {
2003         updateDB(successTable, calibrator->Name(), newstatus);
2004         insertRunNumInDB(table, runNum);
2005         updateDB(table, "comment", comment.str(), runNum, true);
2006         updateDB(table, "committed", true);
2007       }
2008     }
2009   }
2010   else
2011   {
2012     std::cout << "Run " << runno
2013               << " has a good calibrations, doing nothing" << std::endl;
2014   }
2015   delete rs;
2016   return iret;
2017 }
2018 
2019 int OnCalServer::SetBorTime(const int runno)
2020 {
2021   //  recoConsts *rc = recoConsts::instance();
2022   RunToTime *runTime = RunToTime::instance();
2023 
2024   PHTimeStamp *BorTimeStp(runTime->getBeginTime(runno));
2025   if (!BorTimeStp)
2026   {
2027     std::cout << PHWHERE << "Cannot get begin time for run " << runno << std::endl;
2028     std::cout << "Exiting" << std::endl;
2029     exit(1);
2030   }
2031   BeginTimeStamp(*BorTimeStp);
2032 
2033   // enter begin run timestamp into rc flags
2034   PHTimeStamp BeginRunTimeStamp(*BorTimeStp);
2035   //  rc->set_TimeStamp(BeginRunTimeStamp);
2036   std::cout << "OnCalServer::SetBorTime from RunToTime was found for run : " << runno << " to ";
2037   BeginRunTimeStamp.print();
2038   std::cout << std::endl;
2039 
2040   delete BorTimeStp;
2041   return 0;
2042 }
2043 
2044 int OnCalServer::SetEorTime(const int runno)
2045 {
2046   //  recoConsts *rc = recoConsts::instance();
2047   RunToTime *runTime = RunToTime::instance();
2048 
2049   time_t eorticks = 0;
2050 
2051   time_t borticks = 0;  //(rc->get_TimeStamp()).getTics();
2052   PHTimeStamp *EorTimeStp(runTime->getEndTime(runno));
2053   if (EorTimeStp)
2054   {
2055     eorticks = EorTimeStp->getTics();
2056   }
2057   else
2058   {
2059     EorTimeStp = new PHTimeStamp(eorticks);
2060   }
2061   // if end of run timestamp missing or smaller-equal borstamp eor = bor+1 sec
2062   if (eorticks <= borticks)
2063   {
2064     eorticks = borticks + 1;
2065     EorTimeStp->setTics(eorticks);
2066   }
2067   EndTimeStamp(*EorTimeStp);
2068   std::cout << "OnCalServer::SetEorTime: setting eor time to ";
2069   EorTimeStp->print();
2070   std::cout << std::endl;
2071   delete EorTimeStp;
2072   return 0;
2073 }
2074 
2075 int OnCalServer::GetRunTimeTicks(const int runno, time_t &borticks, time_t &eorticks)
2076 {
2077   RunToTime *runTime = RunToTime::instance();
2078   PHTimeStamp *TimeStp(runTime->getBeginTime(runno));
2079   if (!TimeStp)
2080   {
2081     std::cout << PHWHERE << "Cannot get begin time for run " << runno << std::endl;
2082     std::cout << "Exiting" << std::endl;
2083     exit(1);
2084   }
2085   borticks = TimeStp->getTics();
2086   delete TimeStp;
2087   TimeStp = runTime->getEndTime(runno);
2088   if (TimeStp)
2089   {
2090     eorticks = TimeStp->getTics();
2091     delete TimeStp;
2092   }
2093   else
2094   {
2095     eorticks = 0;
2096   }
2097   // if end of run timestamp missing or smaller-equal borstamp eor = bor+1 sec
2098   if (eorticks <= borticks)
2099   {
2100     eorticks = borticks + 1;
2101   }
2102   return 0;
2103 }
2104 
2105 int OnCalServer::requiredCalibration(SubsysReco *reco, const std::string &calibratorname)
2106 {
2107   std::map<std::string, std::set<SubsysReco *> >::iterator iter;
2108   if (check_calibrator_in_statustable(calibratorname))
2109   {
2110     std::cout << PHWHERE << " the calibrator " << calibratorname << " is unknown to me" << std::endl;
2111     return -1;
2112   }
2113   iter = requiredCalibrators.find(calibratorname);
2114   if (iter != requiredCalibrators.end())
2115   {
2116     iter->second.insert(reco);
2117   }
2118   else
2119   {
2120     std::set<SubsysReco *> subsys;
2121     subsys.insert(reco);
2122     requiredCalibrators[calibratorname] = subsys;
2123   }
2124   return 0;
2125 }
2126 
2127 int OnCalServer::FindClosestCalibratedRun(const int irun)
2128 {
2129   RunToTime *rt = RunToTime::instance();
2130   PHTimeStamp *ts = rt->getBeginTime(irun);
2131   if (!ts)
2132   {
2133     std::cout << PHWHERE << "Unknown Run " << irun << std::endl;
2134     return -1;
2135   }
2136   if (requiredCalibrators.empty())
2137   {
2138     std::cout << PHWHERE << "No required calibrations given" << std::endl;
2139     return irun;
2140   }
2141   int curstart = ts->getTics();
2142   delete ts;
2143   ts = rt->getEndTime(irun);
2144   int curend = curstart;
2145   if (ts)
2146   {
2147     curend = ts->getTics();
2148     delete ts;
2149   }
2150   int closestrun = -1;
2151   if (!connectDB())
2152   {
2153     std::cout << "could not connect to " << database << std::endl;
2154     return -1;
2155   }
2156   odbc::Statement *stmt = DBconnection->createStatement();
2157   std::ostringstream cmd;
2158   std::map<std::string, std::set<SubsysReco *> >::const_iterator iter;
2159   // look only for runs which were actually successfully calibrated (status = 1)
2160   cmd << "SELECT runnumber,startvaltime,endvaltime FROM "
2161       << successTable << " where runnumber <= "
2162       << irun;
2163   for (iter = requiredCalibrators.begin(); iter != requiredCalibrators.end(); ++iter)
2164   {
2165     cmd << " and " << iter->first << " > 0 ";
2166   }
2167 
2168   cmd << " order by runnumber desc limit 1";
2169   odbc::ResultSet *rs = nullptr;
2170   try
2171   {
2172     rs = stmt->executeQuery(cmd.str());
2173   }
2174   catch (odbc::SQLException &e)
2175   {
2176     std::cout << "Table " << successTable << " does not exist" << std::endl;
2177     return -1;
2178   }
2179   int prevrun = 0;
2180   unsigned int prevend = 0;
2181   if (rs->next())
2182   {
2183     prevrun = rs->getInt("runnumber");
2184     unsigned int prevstart = rs->getLong("startvaltime");
2185     prevend = rs->getLong("endvaltime");
2186     if (prevrun != irun)
2187     {
2188       std::cout << "previous run: " << prevrun
2189                 << ", start: " << prevstart
2190                 << ", end: " << prevend
2191                 << std::endl;
2192     }
2193   }
2194   else
2195   {
2196     std::cout << PHWHERE << " No previous good run found for run " << irun << std::endl;
2197   }
2198   delete rs;
2199   // if the current run fullfills requirements return immediately
2200   if (prevrun == irun)
2201   {
2202     std::cout << "closest run with required calibs is current run: " << irun << std::endl;
2203     return irun;
2204   }
2205   cmd.str("");
2206   cmd << "SELECT runnumber,startvaltime,endvaltime FROM "
2207       << successTable << " where runnumber > "
2208       << irun;
2209   for (iter = requiredCalibrators.begin(); iter != requiredCalibrators.end(); ++iter)
2210   {
2211     cmd << " and " << iter->first << " > 0 ";
2212   }
2213 
2214   cmd << " order by runnumber asc limit 1";
2215   try
2216   {
2217     rs = stmt->executeQuery(cmd.str());
2218   }
2219   catch (odbc::SQLException &e)
2220   {
2221     std::cout << "Table " << successTable << " does not exist" << std::endl;
2222     return -1;
2223   }
2224   int nextrun = 0;
2225   unsigned int nextstart = 0;
2226   if (rs->next())
2227   {
2228     nextrun = rs->getInt("runnumber");
2229     nextstart = rs->getLong("startvaltime");
2230     unsigned int nextend = rs->getLong("endvaltime");
2231     std::cout << "next run: " << nextrun
2232               << ", start: " << nextstart
2233               << ", end: " << nextend
2234               << std::endl;
2235   }
2236   else
2237   {
2238     std::cout << PHWHERE << " No next good run found for run " << irun << std::endl;
2239   }
2240   delete rs;
2241   int tdiffprev = curstart - prevend;
2242   int tdiffnext;
2243   if (nextstart > 0)
2244   {
2245     tdiffnext = nextstart - curend;
2246   }
2247   else
2248   {
2249     // just make it larger then previous run time diff
2250     tdiffnext = tdiffprev + 1;
2251   }
2252   if (tdiffprev < tdiffnext)
2253   {
2254     closestrun = prevrun;
2255   }
2256   else
2257   {
2258     closestrun = nextrun;
2259   }
2260   std::cout << "closest run with required calibs: " << closestrun << std::endl;
2261   return closestrun;
2262 }
2263 
2264 int OnCalServer::FillRunListFromFileList()
2265 {
2266   for (Fun4AllSyncManager *sync : SyncManagers)
2267   {
2268     for (Fun4AllInputManager *inmgr : sync->GetInputManagers())
2269     {
2270       for (const std::string &infile : inmgr->GetFileList())
2271       {
2272         std::pair<int, int> runseg = Fun4AllUtils::GetRunSegment(infile);
2273         runlist.insert(runseg.first);
2274       }
2275     }
2276   }
2277   return 0;
2278 }
2279 
2280 int OnCalServer::AdjustRichTimeStampForMultipleRuns()
2281 {
2282   int firstrun = *runlist.begin();
2283   int lastrun = *runlist.rbegin();
2284   time_t dummy;
2285   time_t beginticks;
2286   time_t endticks;
2287   std::string table = "OnCalRichCal";
2288   check_create_subsystable(table);
2289   GetRunTimeTicks(firstrun, beginticks, dummy);
2290   GetRunTimeTicks(lastrun, dummy, endticks);
2291   std::ostringstream stringarg;
2292   stringarg << OnCalDBCodes::COVERED;
2293   //  std::set<int>::const_iterator runiter;
2294   /*
2295     for (runiter = runlist.begin(); runiter != runlist.end(); runiter++)
2296     {
2297     updateDB(successTable, "RichCal", stringarg.str(), *runiter);
2298     }
2299     stringarg.str("");
2300     stringarg << OnCalDBCodes::SUCCESS;
2301 
2302     updateDB(successTable, "RichCal", stringarg.str(), firstrun);
2303   */
2304   odbc::Timestamp stp;
2305   stringarg.str("");
2306   stringarg << beginticks;
2307   updateDB(table, "startvaltime", stringarg.str(), firstrun);
2308   stp.setTime(beginticks);
2309   updateDB(table, "begintime", stp.toString(), firstrun);
2310   stringarg.str("");
2311   stringarg << endticks;
2312   updateDB(table, "endvaltime", stringarg.str(), firstrun);
2313   stp.setTime(endticks);
2314   updateDB(table, "endtime", stp.toString(), firstrun);
2315   /*
2316     std::string tablename = "calibrichadc";
2317     odbc::Connection *con = 0;
2318     std::ostringstream cmd;
2319     try
2320     {
2321     con = odbc::DriverManager::getConnection("oncal", "phnxrc", "");
2322     }
2323     catch (odbc::SQLException& e)
2324     {
2325     std::cout << "Cannot connect to " << database.c_str() << std::endl;
2326     std::cout << e.getMessage() << std::endl;
2327     return -1;
2328     }
2329     odbc::Statement *stmt = 0;
2330     odbc::Statement *stmtup = 0;
2331     try
2332     {
2333     stmt = con->createStatement();
2334     stmtup = con->createStatement();
2335     }
2336     catch (odbc::SQLException& e)
2337     {
2338     std::cout << "Cannot create statement" << std::endl;
2339     std::cout << e.getMessage() << std::endl;
2340     return -1;
2341     }
2342 
2343     odbc::ResultSet *rs1 = 0;
2344     cmd.str("");
2345     cmd << "SELECT  endvaltime from " << tablename
2346     << " where bankid = 1 and startvaltime = " << beginticks;
2347     std::cout << "sql cmd: " << cmd.str() << std::endl;
2348     try
2349     {
2350     rs1 = stmt->executeQuery(cmd.str());
2351     }
2352     catch (odbc::SQLException& e)
2353     {
2354     std::cout << "Cannot create statement" << std::endl;
2355     std::cout << e.getMessage() << std::endl;
2356     return -1;
2357     }
2358     if (rs1->next())
2359     {
2360     std::cout << "Endcaltime: " << rs1->getInt("endvaltime") << std::endl;
2361     std::cout << "future endvaltime: " << endticks << std::endl;
2362     cmd.str("");
2363     cmd << "Update " << tablename
2364     << " set endvaltime = " << endticks
2365     << " where bankid = 1 and startvaltime = "
2366     << beginticks;
2367     stmtup->executeUpdate(cmd.str());
2368 
2369     }
2370     else
2371     {
2372     std::cout << "Could not find startvaltime " << beginticks
2373     << "from run " << firstrun << std::endl;
2374     }
2375 
2376   */
2377 
2378   return 0;
2379 }
2380 
2381 int OnCalServer::GetCalibStatus(const std::string &calibname, const int runno)
2382 {
2383   int iret = -3;
2384   if (!connectDB())
2385   {
2386     std::cout << "could not connect to " << database << std::endl;
2387     return -4;
2388   }
2389   odbc::Statement *stmt = DBconnection->createStatement();
2390   std::ostringstream cmd;
2391 
2392   // look only for runs which were actually successfully calibrated (status = 1)
2393   cmd << "SELECT " << calibname << " FROM "
2394       << successTable << " where runnumber = "
2395       << runno;
2396   std::cout << "exec " << cmd.str() << std::endl;
2397   odbc::ResultSet *rs = nullptr;
2398   try
2399   {
2400     rs = stmt->executeQuery(cmd.str());
2401   }
2402   catch (odbc::SQLException &e)
2403   {
2404     std::cout << "Table " << successTable << " does not exist" << std::endl;
2405     return -5;
2406   }
2407   if (rs->next())
2408   {
2409     iret = rs->getInt(calibname);
2410   }
2411   else
2412   {
2413     std::cout << PHWHERE << " No calib status for " << calibname
2414               << " for " << runno << std::endl;
2415   }
2416   delete rs;
2417   return iret;
2418 }
2419 
2420 void OnCalServer::TestMode(const int i)
2421 {
2422   const char *logname = getenv("LOGNAME");
2423   if (logname)
2424   {
2425     if (strcmp(logname, "sphnxpro") == 0 || strcmp(logname, "anatrain") == 0)
2426     {
2427       std::cout << "phnxcal,anatrain account is not allowed to run in testmode" << std::endl;
2428     }
2429     else
2430     {
2431       testmode = i;
2432     }
2433   }
2434   else
2435   {
2436     std::cout << "could not get account via env var LOGNAME, not setting testmode" << std::endl;
2437   }
2438   return;
2439 }