Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

DbuDaqMonitorModule.cxx

Go to the documentation of this file.
00001 
00002 // $Id: DbuDaqMonitorModule.cxx,v 1.30 2007/04/26 14:21:39 west Exp $
00004 #include "DatabaseInterface/DbiExceptionLog.h"
00005 
00006 #include "DatabaseUpdater/DbuDaqMonitorModule.h"
00007 #include "DatabaseUpdater/DbuSignalHandler.h"
00008 
00009 #include "DatabaseUpdater/DbuSubRunSummary.h"
00010 #include "DatabaseUpdater/DbuVaChipPeds.h"
00011 #include "DatabaseUpdater/DbuVaChipSpars.h"
00012 
00013 #include "DatabaseUpdater/DbuBits.h"
00014 #include "DatabaseUpdater/RunTypeName.h"
00015 
00016 #include <cstdio>
00017 // ROOT include files
00018 #include "TObject.h"
00019 #include "TCollection.h"
00020 #include "TObjectTable.h"
00021 // TString for Form function
00022 #include "TString.h"  
00023 #include "TSystem.h"
00024 
00025 // MINOS include files
00026 #include "DatabaseInterface/Dbi.h"
00027 #include "DatabaseInterface/DbiCascader.h"
00028 #include "DatabaseInterface/DbiStatement.h"
00029 #include "DatabaseInterface/DbiTableProxy.h"
00030 #include "DatabaseInterface/DbiTableProxyRegistry.h"
00031 #include "DatabaseInterface/DbiOutRowStream.h"
00032 #include "DatabaseInterface/DbiWriter.h"
00033 #include "DatabaseInterface/DbiCache.h"
00034 #include "DatabaseInterface/DbiResultPtr.h"
00035 #include "DatabaseInterface/DbiString.h"
00036 
00037 
00038 #include "RawData/RawRecord.h"
00039 #include "RawData/RawDaqSnarlHeader.h"
00040 #include "RawData/RawLIAdcSummaryBlock.h"
00041 #include "RawData/RawLITimingSummaryBlock.h"
00042 #include "RawData/RawRunStartBlock.h"
00043 #include "RawData/RawRunCommentBlock.h"
00044 #include "RawData/RawRunEndBlock.h"
00045 #include "RawData/RawPedestalTableBlock.h"
00046 #include "RawData/RawSparsifierTableBlock.h"
00047 
00048 #include "JobControl/JobCommand.h"
00049 #include "JobControl/JobCModuleRegistry.h"
00050 #include "MinosObjectMap/MomNavigator.h"
00051 #include "MessageService/MsgService.h"
00052 #include "Util/UtilString.h"
00053 
00054 #include <signal.h>
00055 #include "OnlineUtil/msgLogLib/msgLog.h"
00056 
00057 CVSID("$Id: DbuDaqMonitorModule.cxx,v 1.30 2007/04/26 14:21:39 west Exp $");
00058 JOBMODULE(DbuDaqMonitorModule, 
00059           "DbuDaqMonitor", "Generate SubRunSummary entries in database.");
00060 
00061 //......................................................................
00062 
00063 const Int_t sec_twoweeks = 2*7*24*60*60;
00064 const Int_t sec_fivemin = 5*60;
00065 
00066 //......................................................................
00067 
00068 DbuDaqMonitorModule::DbuDaqMonitorModule() :
00069    fURL(""), fDbNo(0), fDbiStatement(0), 
00070    fHeartbeatIntervalSec(sec_fivemin),
00071    fCurrentSubRun(0), fRecSubRunSummary(true), fRecAtStart(true),
00072    fCommentFieldName(""), fHasRowCounter(false),
00073    fRecVaChipPeds(false), fRecVaChipSpars(false), fVaChipVldSec(sec_twoweeks)
00074 {}
00075 
00076 //......................................................................
00077 
00078 DbuDaqMonitorModule::~DbuDaqMonitorModule() {}
00079 
00080 //......................................................................
00081   
00082 JobCResult DbuDaqMonitorModule::Ana(const MomNavigator* mom)
00083 {
00084    
00085    JobCResult result = JobCResult::kPassed;
00086 
00087    // Get any and all raw records attached to the data record pointed 
00088    // to by "mom".  The dynamic cast from TObject is ugly but necessary
00089    TObject   *tobj   = 0;
00090    TIter reciter = const_cast<MomNavigator*>(mom)->FragmentIter();
00091    while ( (tobj = reciter() ) ) {
00092       RawRecord *rawrec = dynamic_cast<RawRecord *>(tobj);
00093       JobCResult aresult = ProcessRawRecord(rawrec);
00094       if (aresult.Failed()) result = aresult;
00095    }
00096 
00097    return result;
00098 }
00099 
00100 //......................................................................
00101 
00102 void DbuDaqMonitorModule::BeginJob()
00103 {
00104    // 
00105 
00106    MSG("Dbu",Msg::kInfo)
00107      << "DbuDaqMonitorModule::BeginJob() " << endl;
00108 
00109    logInfo("DbuDaqMonitorModule::BeginJob()");
00110 
00111    Update_ENV_TSQL();
00112 
00113    InitTSQLConnection();
00114 
00115    GetCommentFieldName();
00116    CheckForRowCounterColumn();
00117 
00118    MSG("Dbu",Msg::kInfo) 
00119       << "DbuDaqMonitorModule::BeginJob  " << endl
00120       << " SubRunSummary: " << (fRecSubRunSummary  ? "on":"off") << endl
00121       << " RecordAtStart: " << (fRecAtStart        ? "on":"off") << endl
00122       << " HeartbeatInterval: " << fHeartbeatIntervalSec << " sec" << endl
00123       << " VaChipPeds: "    << (fRecVaChipPeds     ? "on":"off") << endl
00124       << " VaChipSpars: "   << (fRecVaChipSpars    ? "on":"off") << endl
00125       << " VaChipVldSec: "  << fVaChipVldSec << "s" << endl
00126       << " CommentFieldName: \"" << fCommentFieldName << "\"" << endl
00127       << " RowCounter column?  " << (fHasRowCounter?"yes":"no") << endl
00128       << endl;
00129 
00130    if (fRecSubRunSummary) {
00131      logInfo("DbuDaqMonitorModule::BeginJob() %s %s heartbeat %d sec",
00132             ((fRecSubRunSummary)?"SubRunSummary":" "),
00133             ((fRecAtStart)?"RecAtStart":" "),
00134             fHeartbeatIntervalSec);
00135      logInfo("DbuDaqMonitorModule::BeginJob() field name \"%s\"",
00136              fCommentFieldName.c_str());
00137    }
00138 
00139    if (fRecVaChipPeds||fRecVaChipSpars) {
00140      logInfo("DbuDaqMonitorModule::BeginJob() %s %s",
00141              ((fRecVaChipPeds)?"VaChipPeds":" "),
00142              ((fRecVaChipSpars)?"VaChipSpars":" "));
00143      logInfo("DbuDaqMonitorModule::BeginJob() VaChipVldSec = %d",
00144              fVaChipVldSec);
00145    }
00146 
00147 
00148 }
00149 
00150 //......................................................................
00151 
00152 void DbuDaqMonitorModule::EndJob()
00153 {
00154    // this should make sure all entries are flushed
00155 
00156   MSG("Dbu",Msg::kInfo)
00157     << "DbuDaqMonitorModule::EndJob() " << endl;
00158 
00159   logInfo("DbuDaqMonitorModule::EndJob() processing begun");
00160 
00161   if (fCurrentSubRun) {
00162     if (fCurrentSubRun->fConsistency & DbuBits::kInProgress)
00163       fCurrentModified = true;
00164 
00165     fCurrentSubRun->fConsistency &= ~DbuBits::kInProgress;
00166 
00167     logDebug(2,"EndJob() writing summary for %c%8.8d_%4.4d",
00168            Detector::AsString(fCurrentSubRun->fDetector)[0],
00169            fCurrentSubRun->fRun,fCurrentSubRun->fSubRun);
00170 
00171     WriteSubRunSummaryEntry(true);
00172 
00173   }
00174 
00175   logInfo("DbuDaqMonitorModule::EndJob() finished");
00176 }
00177 
00178 //......................................................................
00179 
00180 const Registry& DbuDaqMonitorModule::DefaultConfig() const 
00181 {
00182 //======================================================================
00183 // The default configuration for this module
00184 //======================================================================
00185   static Registry r;
00186   
00187   std::string name = this->GetName();
00188   name += ".config.default";
00189   r.SetName(name.c_str());
00190   
00191   r.UnLockValues();
00192   r.Set("SubRunSummary",true);
00193   r.Set("RecordAtStart",true);
00194   r.Set("HeartbeatIntervalSec",sec_fivemin);
00195   r.Set("VaChipPeds",true);
00196   r.Set("VaChipSpars",true);
00197   r.Set("VaChipVldSec",sec_twoweeks);
00198   r.Set("CommentFieldName","");  //"RUN_COMMENT");
00199   r.LockValues();
00200 
00201   return r;
00202 }
00203 
00204 //......................................................................
00205 
00206 void DbuDaqMonitorModule::Config(const Registry& r) 
00207 {
00208 //======================================================================
00209 // Configure the module using the registry r
00210 //======================================================================
00211 
00212    int tmpi;
00213    const char* tmps;
00214 
00215    if (r.Get("SubRunSummary",tmpi)) fRecSubRunSummary = tmpi;
00216 
00217    if (r.Get("RecordAtStart",tmpi)) fRecAtStart       = tmpi;
00218 
00219    if (r.Get("HeartbeatIntervalSec",tmpi)) fHeartbeatIntervalSec = tmpi;
00220 
00221    if (r.Get("VaChipPeds",tmpi))    fRecVaChipPeds    = tmpi;
00222 
00223    if (r.Get("VaChipSpars",tmpi))   fRecVaChipSpars   = tmpi;
00224 
00225    if (r.Get("VaChipVldSec",tmpi))  fVaChipVldSec     = tmpi;
00226 
00227    if (r.Get("CommentFieldName",tmps)) fCommentFieldName = tmps;
00228 
00229 }
00230 
00231 //......................................................................
00232 void DbuDaqMonitorModule::Update_ENV_TSQL()
00233 {
00234 //======================================================================
00235 // copy ENV_TSQL_UPDATE_XXX to ENV_TSQL_XXX
00236 //======================================================================
00237 
00238    fURL  = "";
00239    fDbNo = 0;   // This won't change as we will force "offline" to the start of the cascade.
00240 
00241    // find the "offline" DB from the URL (not the "temp" one)
00242 
00243    const char* strUrlUsed      = gSystem->Getenv("ENV_TSQL_UPDATE_URL");
00244    if (!strUrlUsed) strUrlUsed = gSystem->Getenv("ENV_TSQL_URL");
00245    string urlList = (strUrlUsed) ? strUrlUsed : "";
00246    while ( urlList != "") {
00247      UInt_t maxStringPos = urlList.size();
00248      string url = urlList;
00249      UInt_t nextStringPos = urlList.find(";");
00250      if ( nextStringPos < maxStringPos ) {
00251        url = urlList.substr(0,nextStringPos);
00252        urlList.erase(0,nextStringPos+1);
00253      }
00254      else urlList = "";
00255      
00256      maxStringPos = url.size();
00257      
00258      if (url.find("offline") < maxStringPos) {
00259        fURL = url;
00260        break;
00261      }
00262      
00263      // if not "offline" move along to next possibility
00264    }
00265 
00266    // Override ENV_TSQL_UPDATE_URL (the Dbi preferrentially 
00267    // takes the ENV_TSQL_UPDATE_* variables).
00268    gSystem->Setenv("ENV_TSQL_UPDATE_URL",fURL.c_str());
00269 
00270 }
00271 
00272 
00273 //......................................................................
00274 
00275 void DbuDaqMonitorModule::InitTSQLConnection()
00276 {
00277 //======================================================================
00278 // Obtain a DbiStatement to the first entry in the Cascade
00279 //======================================================================
00280 
00281    // assume ENV_TSQL_UPDATE_XXX have been adjusted so the "Offline" is the first entry
00282    if (fDbiStatement)  { delete fDbiStatement;  fDbiStatement  = 0; }
00283    fDbiStatement = DbiTableProxyRegistry::Instance().GetCascader().CreateStatement(fDbNo);
00284 
00285    if ( ! fDbiStatement ) {
00286      MSG("Dbu",Msg::kError)
00287        << "Failed to create DbiStatement for: " << fURL << endl;
00288      logWarn("InitTSQLConnection failed to create DBU TSQL_Statement for %s",fURL.c_str());
00289    }
00290 
00291    MSG("Dbu",Msg::kInfo)
00292      << "Successfully created DbiStatement to: " << fURL << endl;
00293    logDebug(4,"InitTSQLConnection created DBU statement to %s",fURL.c_str());
00294 
00295 }
00296 
00297 //......................................................................
00298 
00299 void DbuDaqMonitorModule::HandleCommand(JobCommand* cmd) 
00300 {
00301 
00302    const char* c = cmd->PopCmd();
00303    if (c) {
00304       string sc(c);
00305       if (sc == "Record" || sc == "Disregard" ) {
00306          bool on = (sc=="Record");
00307          while (const char* opt = cmd->PopOpt()) {
00308             string sopt(opt);
00309             if      (sopt == "SubRunSummary") fRecSubRunSummary = on;
00310             else if (sopt == "RecordAtStart") fRecAtStart       = on;
00311             else if (sopt == "VaChipPeds")    fRecVaChipPeds    = on;
00312             else if (sopt == "VaChipSpars")   fRecVaChipSpars   = on;
00313             else {
00314                MSG("Dbu",Msg::kWarning) 
00315                   << "No " << sc << " available for '" << opt << "'." << endl;
00316             }
00317          }
00318       }
00319       else if (sc == "Set" ) {
00320          const char* opt = cmd->PopOpt();
00321          string sopt(opt);
00322          if      (sopt == "VaChipVldSec") fVaChipVldSec = cmd->PopIntOpt();
00323          else
00324                MSG("Dbu",Msg::kWarning) 
00325                   << "No " << sc << " available for '" << opt << "'." << endl;
00326       }
00327       else {
00328          MSG("Dbu",Msg::kInfo) 
00329             << "No Valid DbuDaqMonitorModule command '" << sc <<"'." << endl;
00330       }
00331    }
00332    else {
00333       MSG("Dbu",Msg::kInfo)
00334          << "Valid commands are: 'Record' and 'Disregard'" << endl
00335          << "Valid options are: SubRunSummary, AtStart, VaChipPeds, VaChipSpars" 
00336          << "  Also /Set VaChipVldSec [nsec]" << endl
00337          << endl;
00338    }
00339 }
00340 
00341 //......................................................................
00342 
00343 void DbuDaqMonitorModule::GetCommentFieldName()
00344 {
00345 
00346   // determine the name of the "comment" field (column) of the table
00347 
00348   // incantation from Nick
00349 
00350   // Get the Singleton manager
00351   DbiTableProxyRegistry& tpr = DbiTableProxyRegistry::Instance();
00352   // Crate a "pet" object (needed if reading in order to create rows)
00353   DbuSubRunSummary srs;
00354   // Get a proxy to DBUSUBRUNSUMMARY
00355   DbiTableProxy& tp = tpr.GetTableProxy("DBUSUBRUNSUMMARY",&srs);
00356   // Acess the table's meta-data
00357   const DbiTableMetaData& md = tp.GetMetaData();
00358   // Find the right column 
00359   UInt_t numCols = md.NumCols();  // column numbers from 1 not zero
00360   for (UInt_t iCol = 1;  iCol <= numCols; ++iCol ) {
00361     std::string guess = md.ColName(iCol);
00362     if (guess.find("COMMENT") != std::string::npos)
00363       fCommentFieldName = guess;
00364   }
00365 
00366   // final default if all else failed
00367   if ( "" == fCommentFieldName ) 
00368     fCommentFieldName = "RUN_COMMENT"; 
00369 }
00370 
00371 //......................................................................
00372 
00373 void DbuDaqMonitorModule::CheckForRowCounterColumn()
00374 {
00375 
00376   // determine if the table has a "ROW_COUNTER" column
00377 
00378   // Get the Singleton manager
00379   DbiTableProxyRegistry& tpr = DbiTableProxyRegistry::Instance();
00380   // Crate a "pet" object (needed if reading in order to create rows)
00381   DbuSubRunSummary srs;
00382   // Get a proxy to DBUSUBRUNSUMMARY
00383   DbiTableProxy& tp = tpr.GetTableProxy("DBUSUBRUNSUMMARY",&srs);
00384   // Acess the table's meta-data
00385   const DbiTableMetaData& md = tp.GetMetaData();
00386   // Find the right column 
00387   UInt_t numCols = md.NumCols();  // column numbers from 1 not zero
00388   for (UInt_t iCol = 1;  iCol <= numCols; ++iCol ) {
00389     std::string guess = md.ColName(iCol);
00390     if (guess.find("ROW_COUNTER") != std::string::npos)
00391       fHasRowCounter = true;
00392   }
00393 }
00394 
00395 //......................................................................
00396 
00397 JobCResult DbuDaqMonitorModule::ProcessRawRecord(const RawRecord* rawrec)
00398 {
00399 
00400    JobCResult result = JobCResult::kPassed;
00401    static VldTimeStamp nullTime((time_t)0,0);
00402 
00403    // test if the RawRecord was from the DAQ
00404    const RawDaqHeader* header = 
00405       dynamic_cast<const RawDaqHeader*>(rawrec->GetRawHeader());
00406    if (!header) {
00407       MSG("Dbu",Msg::kError)
00408          << "RawRecord lacked RawDaqHeader:" 
00409          << *(rawrec->GetRawHeader())
00410          << endl;
00411       logWarn("RawRecord lacked RawDaqHeader");
00412       return JobCResult::kFailed;
00413    }
00414        
00415    VldContext           vldc   = header->GetVldContext();
00416    Detector::Detector_t det    = vldc.GetDetector();
00417    Int_t                run    = header->GetRun();
00418    Short_t              subrun = header->GetSubRun();
00419 
00420    // this section is some (optional) heartbeat/debugging output
00421    const char* strmname = rawrec->GetTempTags().GetCharString("stream");
00422    const int   strmindx = rawrec->GetTempTags().GetInt("index");
00423    const char* fname    = rawrec->GetTempTags().GetCharString("file");
00424 
00425    Int_t this_time = vldc.GetTimeStamp().GetSec();
00426    static Int_t last_heartbeat = 0;
00427    bool pulse = ( this_time - last_heartbeat > fHeartbeatIntervalSec );
00428 
00429    string this_file = fname;
00430    static string last_file = "";
00431    bool newfile = ( last_file != this_file );
00432 
00433    if ( pulse || newfile ) {
00434      // send out heart beat signal
00435      const char* fmttime = vldc.GetTimeStamp().AsString("c");
00436      const char* why = ((newfile) ? "new file" : "heartbeat");
00437      MSG("Dbu",Msg::kDebug) 
00438        << why << ": " 
00439        << this_file << " (" << strmname << " " << strmindx << ") "
00440        << endl << " " << *header << endl;
00441 
00442      logDebug(3,"heartbeat: %c%8.8d_%4.4d %s (%s %d)",
00443               Detector::AsString(det)[0],
00444               run,subrun,fmttime,strmname,strmindx);
00445 
00446      last_heartbeat = this_time;
00447      last_file      = this_file;
00448    }
00449 
00450    if (fCurrentSubRun && !fCurrentSubRun->IsSameSubRun(det,run,subrun)) {
00451      // starting new subrun -- flush what we have for previous entry
00452      if (fCurrentSubRun->fConsistency&DbuBits::kInProgress)
00453        fCurrentModified = true;
00454 
00455      fCurrentSubRun->fConsistency &= ~DbuBits::kInProgress;
00456 
00457      if ( ! WriteSubRunSummaryEntry(true) ) result = JobCResult::kFailed;
00458 
00459    }
00460 
00461    if (!fCurrentSubRun) {
00462       // first time for this run/subrun
00463       fCurrentModified = true;
00464       fWrittenNTimes   = 0;
00465       fCurrentSubRun = new DbuSubRunSummary;
00466       fCurrentSubRun->fDetector     = det;
00467       fCurrentSubRun->fSimFlag      = vldc.GetSimFlag();
00468       fCurrentSubRun->fRun          = run;
00469       fCurrentSubRun->fSubRun       = subrun;
00470       fCurrentSubRun->fRunType      = header->GetRunType();
00471       fCurrentSubRun->fStartTime    = vldc.GetTimeStamp();
00472       fCurrentSubRun->fConsistency |= DbuBits::kRecCountUnverified;
00473       fCurrentSubRun->fConsistency |= DbuBits::kSawNoRunStart;
00474       fCurrentSubRun->fConsistency |= DbuBits::kSawNoRunComment;
00475       fCurrentSubRun->fConsistency |= DbuBits::kSawNoRunEnd;
00476       fCurrentSubRun->fConsistency |= DbuBits::kInProgress;
00477       MSG("Dbu",Msg::kDebug) 
00478         << " create new CurrentSubRun from RawDaqHeader: " << endl
00479         << " Run " << run << " SubRun " << subrun << endl
00480         << " " << *header << endl;
00481    }
00482 
00483    // continually update end time (in case of missing RunEnd)
00484    fCurrentSubRun->fEndTime      = vldc.GetTimeStamp();
00485 
00486    // For each RawBlock in the RawRecord extract what we can
00487    // The dynamic cast from TObject is ugly but necessary
00488    TIter itr = rawrec->GetRawBlockIter();
00489    RawDataBlock*            rdb           = 0;
00490    RawRunEndBlock*          runendblk     = 0;
00491    RawRunStartBlock*        runstartblk   = 0;
00492    RawRunCommentBlock*      runcommentblk = 0;
00493    RawLIAdcSummaryBlock*    liadcblk      = 0;
00494    RawLITimingSummaryBlock* litimingblk   = 0;
00495 
00496    // The dynamic cast from TObject is ugly but necessary
00497    // Careful! the itr() advances the iterator as a side effect!
00498    while ((rdb = dynamic_cast<RawDataBlock*>(itr()))) {
00499 
00500       if (!runendblk)   runendblk   = dynamic_cast<RawRunEndBlock*>(rdb);
00501       if (!runstartblk) runstartblk = dynamic_cast<RawRunStartBlock*>(rdb);
00502 
00503       runcommentblk = dynamic_cast<RawRunCommentBlock*>(rdb);
00504       liadcblk      = dynamic_cast<RawLIAdcSummaryBlock*>(rdb);
00505       litimingblk   = dynamic_cast<RawLITimingSummaryBlock*>(rdb);
00506 
00507       RawPedestalTableBlock* pedtblblk = 
00508          dynamic_cast<RawPedestalTableBlock*>(rdb);
00509       RawSparsifierTableBlock* sparstblblk = 
00510          dynamic_cast<RawSparsifierTableBlock*>(rdb);
00511 
00512       if      ( runstartblk ) {                 
00513          // this is a RunStart block
00514         fCurrentModified = true;
00515         fCurrentSubRun->fConsistency &= ~DbuBits::kSawNoRunStart;
00516         VldTimeStamp startTime = runstartblk->GetStartTime();
00517 
00518         MSG("Dbu",Msg::kDebug) << *runstartblk << endl;
00519         const char* fmttime = runstartblk->GetStartTime().AsString("c");
00520         logInfo("%-16s RUN %d SUB %d @ %s (%s %d)",
00521                 "RunStartBlk",run,subrun,fmttime,strmname,strmindx);
00522       }
00523       else if ( runcommentblk ) {
00524         // this is a RunComment block
00525         fCurrentModified = true;
00526         fCurrentSubRun->fConsistency &= ~DbuBits::kSawNoRunComment;
00527         fCurrentSubRun->fComment = runcommentblk->GetRunComment();
00528 
00529          MSG("Dbu",Msg::kDebug) << *runcommentblk << endl;
00530          const char* fmttime = runcommentblk->GetTime().AsString("c");
00531          logInfo("%-16s RUN %d SUB %d @ %s (%s %d)",
00532                  "RunCommentBlk",run,subrun,fmttime,strmname,strmindx);
00533       }
00534       else if (pedtblblk && fRecVaChipPeds) {
00535          if ( ! WriteVaChipPedsEntry(pedtblblk) ) 
00536            result = JobCResult::kFailed;
00537       }
00538       else if (sparstblblk && fRecVaChipSpars) {
00539          if ( ! WriteVaChipSparsEntry(sparstblblk) ) 
00540            result = JobCResult::kFailed;
00541       }
00542 
00543    }
00544 
00545    // perform our own counts for records
00546    const RawDaqSnarlHeader* snarlheader = 
00547       dynamic_cast<const RawDaqSnarlHeader*>(header);
00548    if (snarlheader) {
00549       if (fCurrentSubRun->fSnarlRec<0) fCurrentSubRun->fSnarlRec=0;
00550       fCurrentModified = true;
00551       fCurrentSubRun->fSnarlRec++;
00552    }
00553    else {
00554       if (fCurrentSubRun->fMonitorRec<0) fCurrentSubRun->fMonitorRec=0;
00555       fCurrentModified = true;
00556       fCurrentSubRun->fMonitorRec++;
00557    }
00558 
00559    if (liadcblk || litimingblk) {
00560       if (fCurrentSubRun->fLightInjRec<0) fCurrentSubRun->fLightInjRec=0;
00561       fCurrentModified = true;
00562       fCurrentSubRun->fLightInjRec++;
00563    }
00564 
00565    // if we saw a run end block process it here after
00566    // any other blocks in the record
00567    if (runendblk) {
00568       //RawDataBlock::SetForceHexDump(true);
00569       //cout << *runendblk << endl;
00570       //RawDataBlock::SetForceHexDump(false);
00571 
00572       MSG("Dbu",Msg::kDebug) << *runendblk << endl;
00573       const char* fmttime = runendblk->GetEndTime().AsString("c");
00574       logInfo("%-16s RUN %d SUB %d @ %s (%s %d)",
00575               "RunEndBlk",run,subrun,fmttime,strmname,strmindx);
00576 
00577       fCurrentModified = true;
00578       fCurrentSubRun->fConsistency &= ~DbuBits::kSawNoRunEnd;
00579 
00580       Int_t runEndSnarls  = runendblk->GetNumberOfSnarls();
00581       Int_t runEndMonitor = runendblk->GetNumberOfNonSnarls();
00582       if (fCurrentSubRun->fSnarlRec   != runEndSnarls ||
00583           fCurrentSubRun->fMonitorRec != runEndMonitor   ) {
00584          // flag that what we saw doesn't match RunEnd
00585          fCurrentSubRun->fConsistency |= DbuBits::kRecCountUnverified;
00586          MSG("Dbu",Msg::kDebug) 
00587            << "Counted/Expected " 
00588            << fCurrentSubRun->fSnarlRec << "/" << runEndSnarls
00589            << " SnarlRec, "
00590            << fCurrentSubRun->fMonitorRec << "/" << runEndMonitor
00591            << " MonitorRec "
00592            << endl;
00593       }
00594       else
00595         fCurrentSubRun->fConsistency &= ~DbuBits::kRecCountUnverified;
00596 
00597       // no matter what, pick the larger count
00598       // (not necessarily replace them with "official" counts)
00599       // any mismatch is probably due to Dispatcher not serving all streams
00600       if (fCurrentSubRun->fSnarlRec   < runEndSnarls )
00601           fCurrentSubRun->fSnarlRec   = runEndSnarls;
00602       if (fCurrentSubRun->fMonitorRec < runEndMonitor )
00603           fCurrentSubRun->fMonitorRec = runEndMonitor;
00604       
00605       VldTimeStamp startTime = runendblk->GetStartTime();
00606       VldTimeStamp endTime   = runendblk->GetEndTime();
00607 
00608       bool bogus_time = false;
00609 
00610       if (startTime != nullTime)
00611         fCurrentSubRun->fStartTime = startTime;
00612       else
00613         bogus_time = true;
00614 
00615       if (endTime   != nullTime)
00616         fCurrentSubRun->fEndTime   = endTime;
00617       else
00618         bogus_time = true;
00619       
00620       if (bogus_time) {
00621         MSG("Dbu",Msg::kError) 
00622           << "RunEnd block for " << fCurrentSubRun->fRun
00623           << " had either a bad start or end time " << endl
00624           << *runendblk << endl;
00625       } 
00626       
00627       fCurrentSubRun->fTermCode      = runendblk->GetTerminationCode();
00628       fCurrentSubRun->fNErr          = runendblk->GetNumberOfErrors();
00629       fCurrentSubRun->fTimeFrames    = runendblk->GetTotalTimeFrames();
00630       fCurrentSubRun->fDroppedFrames = runendblk->GetDroppedTimeFrames();
00631       
00632       // one can NOT!! assume that RunEnd is the last record 
00633       // for this run/subrun (based on empirical evidence)
00634       //
00635       // so don't even bother? ... just wait until start of next
00636       // run or end of job? -- no, that could be a long wait
00637       //
00638       if ( ! WriteSubRunSummaryEntry(false) ) result = JobCResult::kFailed;
00639 
00640    }
00641    else if (runstartblk && fRecAtStart) {
00642       // if recording on RunStart don't delete the entry
00643       if (!WriteSubRunSummaryEntry(false) ) 
00644          result = JobCResult::kFailed;
00645    }
00646    return result;
00647 }
00648 
00649 //......................................................................
00650 Bool_t DbuDaqMonitorModule::WriteSubRunSummaryEntry(Bool_t remove)
00651 {
00652    // Make (or update) entry in the database
00653    // optionally remove the current entry if requested
00654 
00655    // Because SubRunSummary is "special" we'll not use the std DBI
00656    // writer mechanism.  DBI doesn't allow user control of the SEQNO
00657    // and we want a very special value for that (to ease browsing
00658    // by users) so excute update using the low level DbiStatement.
00659 
00660    // automagically successful if we're not supposed to write
00661    // or if there's nothing to write
00662    if (!fRecSubRunSummary) return true;
00663    if (!fCurrentSubRun)    return true;
00664    // and unsuccessful if statement wasn't made
00665    if (!fDbiStatement)   return false;
00666 
00667    char tmpbuf[1024];
00668    sprintf(tmpbuf,"writing SubRunSummary for %c%8.8d_%4.4d",
00669            Detector::AsString(fCurrentSubRun->fDetector)[0],
00670            fCurrentSubRun->fRun,fCurrentSubRun->fSubRun);
00671 
00672    if (!fCurrentModified) {
00673      logDebug(4,"%s unmodified",tmpbuf);
00674      MSG("Dbu",Msg::kDebug) 
00675        << tmpbuf << " is unmodified" << endl;;
00676 
00677      // remove the fCurrentSubRun if requested
00678      if (remove) { delete fCurrentSubRun; fCurrentSubRun = 0; }
00679      return true;
00680    }
00681 
00682    logDebug(2,"%s started",tmpbuf);
00683    
00684    // protect ODBC code against signals
00685    DbuSignalHandler::Instance().Delay();
00686    
00687    
00688    // prepare to make a DBI entry
00689    // const char* tblName  = "DBURUNSUMMARY";
00690    // const char* tblDescr = DbuSubRunSummary::GetTableDescr();
00691    
00692    Int_t seqno = fCurrentSubRun->GetSeqNo();
00693    
00694    // entries are valid from time when run started to
00695    // the end of time (2038-01-19)
00696    
00697    string tbl  = "DBUSUBRUNSUMMARY";
00698    string tblv = "DBUSUBRUNSUMMARYVLD";
00699    
00700    // just blast away any existing entry
00701    DbiString sqlrm, sqlrmv;
00702    
00703    sqlrmv  << "delete from " << tblv << " where SEQNO=" << seqno << ";\0";
00704    sqlrm   << "delete from " << tbl  << " where SEQNO=" << seqno << ";\0";
00705    Bool_t rmv = fDbiStatement->ExecuteUpdate(sqlrmv.c_str());
00706    Bool_t rm  = fDbiStatement->ExecuteUpdate(sqlrm.c_str());
00707    
00708    // make sure the comment doesn't have stray " or ' characters
00709    std::string quoted_comment;
00710    UtilString::MakePrintable(fCurrentSubRun->fComment.c_str(),quoted_comment);
00711 
00712    // 
00713    DbiString sqlcol, sqlval;
00714    sqlcol << " SEQNO";
00715    sqlval << seqno;
00716    if (fHasRowCounter) {
00717        sqlcol << ", ROW_COUNTER";
00718        sqlval << "," << 0;
00719    }
00720    sqlcol << ", DETECTOR ";
00721    sqlval << ",'" << Detector::AsString(fCurrentSubRun->fDetector) <<"'";
00722    sqlcol << ", RUN ";
00723    sqlval << "," << fCurrentSubRun->fRun;
00724    sqlcol << ", SUBRUN ";
00725    sqlval << "," << fCurrentSubRun->fSubRun;
00726    sqlcol << ", RUNTYPE ";
00727    sqlval << "," << fCurrentSubRun->fRunType;
00728    sqlcol << ", RUNTYPENAME ";
00729    sqlval << ",'" << RunTypeName(fCurrentSubRun->fRunType,fCurrentSubRun->fDetector,fCurrentSubRun->fRun) <<"'";
00730    sqlcol << ", STARTTIME ";
00731    sqlval << ",'" << fCurrentSubRun->fStartTime.AsString("s") << "'";
00732    sqlcol << ", ENDTIME ";
00733    sqlval << ",'" << fCurrentSubRun->fEndTime.AsString("s") << "'";
00734    sqlcol << ", TERMCODE ";
00735    sqlval << "," << fCurrentSubRun->fTermCode;
00736    sqlcol << ", SNARLREC ";
00737    sqlval << "," << fCurrentSubRun->fSnarlRec;
00738    sqlcol << ", MONITORREC ";
00739    sqlval << "," << fCurrentSubRun->fMonitorRec;
00740    sqlcol << ", LIGHTINJREC ";
00741    sqlval << "," << fCurrentSubRun->fLightInjRec;
00742    sqlcol << ", NERR ";
00743    sqlval << "," << fCurrentSubRun->fNErr;
00744    sqlcol << ", TIMEFRAMES ";
00745    sqlval << "," << fCurrentSubRun->fTimeFrames;
00746    sqlcol << ", DROPPEDFRAMES ";
00747    sqlval << "," << fCurrentSubRun->fDroppedFrames;
00748    sqlcol << ", CONSISTENCY ";
00749    sqlval << "," << fCurrentSubRun->fConsistency;
00750    //sqlcol << ", COMMENT ";
00751    sqlcol << ", " << fCommentFieldName << " ";
00752    sqlval << ",'" << quoted_comment << "'";
00753    
00754    DbiString sqlinsert;
00755    sqlinsert << "insert into " << tbl
00756              << " ( " << sqlcol.c_str() << " ) "
00757              << " VALUES ( " << sqlval.c_str() << " ) ;\0";
00758       
00759    MSG("Dbu",Msg::kDebug) 
00760      << "insert into " << tbl
00761      << " ( " << sqlcol.c_str() << " ) "
00762      << " VALUES ( " << sqlval.c_str() << " ) ;"
00763      << endl;
00764 
00765    VldTimeStamp  now;
00766    if (fWrittenNTimes) {
00767      // if writing multiple times, advance time by sec each time
00768      // to avoid using the same CREATIONDATE
00769      VldTimeStamp offset((time_t)fWrittenNTimes,0);
00770      offset.Add(offset);
00771    }
00772    fWrittenNTimes++;
00773 
00774    VldTimeStamp& runstart = fCurrentSubRun->fStartTime;
00775    const VldTimeStamp endoftime(0x7fffffff,999999999);
00776    const Int_t task = 0;
00777    Int_t aggrno = -1;
00778 #ifdef MULTIAGGREGATE
00779    aggrno = seqno;
00780 #endif
00781    
00782    DbiString sqlcolv, sqlvalv;
00783    sqlcolv << " SEQNO";
00784    sqlvalv << seqno;
00785    sqlcolv << ", TIMESTART ";
00786    sqlvalv << ",'" << runstart.AsString("s") << "'";
00787    sqlcolv << ", TIMEEND ";
00788    sqlvalv << ",'" << endoftime.AsString("s") << "'";
00789    sqlcolv << ", DETECTORMASK ";
00790    sqlvalv << "," << fCurrentSubRun->fDetector;
00791    sqlcolv << ", SIMMASK ";
00792    sqlvalv << "," << fCurrentSubRun->fSimFlag;
00793    sqlcolv << ", TASK ";
00794    sqlvalv << "," << task;
00795    sqlcolv << ", AGGREGATENO ";
00796    sqlvalv << "," << aggrno;
00797    sqlcolv << ", CREATIONDATE ";
00798    sqlvalv << ",'" << now.AsString("s") << "'" ;
00799    sqlcolv << ", INSERTDATE ";
00800    sqlvalv << ",'" << now.AsString("s") << "'";
00801    
00802    DbiString sqlinsertv;
00803    sqlinsertv << "insert into " << tblv
00804               << " ( " << sqlcolv.c_str() << " ) "
00805               << " VALUES ( " << sqlvalv.c_str() << " ) ;\0";
00806    
00807    MSG("Dbu",Msg::kDebug) 
00808      << "insert into " << tblv
00809      << " ( " << sqlcolv.c_str() << " ) "
00810      << " VALUES ( " << sqlvalv.c_str() << " ) ;"
00811      << endl;
00812 
00813    Bool_t insert  = fDbiStatement->ExecuteUpdate(sqlinsert.c_str());
00814    Bool_t insertv = fDbiStatement->ExecuteUpdate(sqlinsertv.c_str());
00815 
00816    
00817    MSG("Dbu",Msg::kVerbose)
00818      << sqlinsert.c_str() << endl;
00819    MSG("Dbu",Msg::kVerbose)
00820      << sqlinsertv.c_str() << endl;
00821    
00822    MSG("Dbu",Msg::kDebug) 
00823      << tmpbuf
00824      << " Cbits " << fCurrentSubRun->fConsistency 
00825      << " rm/in " 
00826      << rm << "," << rmv << "/"
00827      << insert << "," << insertv 
00828      << endl;
00829    logDebug(3,"%s rm=%d,%d in=%d,%d @ %s",
00830             tmpbuf,rm,rmv,insert,insertv,now.AsString("s"));
00831 
00832    bool success = (insert && insertv);
00833    if (success) fCurrentModified = false;
00834    
00835    // remove the fCurrentSubRun if requested
00836    if (remove) { delete fCurrentSubRun; fCurrentSubRun = 0; }
00837    
00838    // done protecting ODBC code against signals
00839    DbuSignalHandler::Instance().HandleDelayedSignal();
00840    
00841    return success;
00842 }
00843 
00844 
00845 //......................................................................
00846 
00847 Bool_t DbuDaqMonitorModule::WriteVaChipPedsEntry(const RawPedestalTableBlock* pedblk)
00848 {
00849    // unpack block, build db entries
00850    // send entries off to database
00851 
00852    RawBlockId rbid = pedblk->GetBlockId();
00853    Detector::Detector_t     det = rbid.GetDetector();
00854    SimFlag::SimFlag_t   simflag = rbid.GetSimFlag();
00855 
00856    Int_t crate = pedblk->GetCrateStatus()->GetCrate();
00857    VldTimeStamp loadTime = pedblk->GetLoadTime();
00858 
00859    // loaded values should be good for fVaChipVldSec seconds
00860    const VldTimeStamp timeVld(fVaChipVldSec,0);
00861    VldTimeStamp guessEndTime = loadTime;
00862    guessEndTime.Add(timeVld);
00863 
00864    VldRange vldr(det,simflag,loadTime,guessEndTime,"DBU");
00865    VldTimeStamp creationTime;
00866 
00867    // protect ODBC code against signals
00868    DbuSignalHandler::Instance().Delay();
00869    logInfo("DbuDaqMonitorModule::WriteVaChipPedsEntry() started crate %d",crate);
00870    
00871    // create a DbiWriter
00872    Int_t aggrno = crate;  // aggregate by crate (natural)
00873    Dbi::Task task = 0;
00874    DbiWriter<DbuVaChipPeds> writer(vldr,aggrno,task,creationTime,fDbNo);
00875 
00876    // prepare to loop
00877    DbuVaChipPeds* chip_peds = 0;
00878 
00879    Int_t nvalues = pedblk->GetNumberOfValues();
00880    // go one too far to ensure that last entry gets flushed
00881    // this approach assumes that entries for same chip are consecutive
00882    for (Int_t indx=0; indx<nvalues+1; indx++) {
00883       RawChannelId current_rcid;
00884       Int_t value;
00885       pedblk->GetPedValue(indx,current_rcid,value);
00886       if (chip_peds && !chip_peds->fRawChannelId.IsSameVAChip(current_rcid)) {
00887          // saw new chip, output the current entry
00888          // cout << *chip_peds << endl;
00889 
00890          writer << *chip_peds;
00891 
00892          // destroy this one now that we're done with it
00893          delete chip_peds; chip_peds = 0;
00894       }
00895       
00896       // if we just flushed old entry, build new one
00897       if (!chip_peds) chip_peds = new DbuVaChipPeds(current_rcid);
00898 
00899       // set the value
00900       Int_t vachan = current_rcid.GetVaChannel();
00901       if (vachan>=0 && vachan<=21) chip_peds->fChanPed[vachan] = value;
00902       else MSG("Dbu",Msg::kWarning) 
00903          << "Bad Channel on " << current_rcid.AsString()
00904          << " " << current_rcid.AsString("e") << endl;
00905    }
00906    
00907    if (chip_peds) {
00908       RawChannelId current_rcid = chip_peds->fRawChannelId;
00909       if (!current_rcid.IsNull()) {
00910          // this shouldn't happen
00911          MSG("Dbu",Msg::kWarning) 
00912             << "Orphan DbuVaChipPeds on " << current_rcid.AsString()
00913             << " " << current_rcid.AsString("e") << endl;
00914          cout << *chip_peds << endl;
00915 
00916          cout << *pedblk << endl;
00917 
00918          writer << *chip_peds;
00919       }
00920       // avoid any memory leaks
00921       delete chip_peds; chip_peds = 0;
00922    }
00923 
00924    bool success = writer.Close();
00925 
00926    logInfo("DbuDaqMonitorModule::WriteVaChipPedsEntry() success=%d",(int)success);
00927 
00928    // done protecting ODBC code against signals
00929    DbuSignalHandler::Instance().HandleDelayedSignal();
00930 
00931    return success;
00932 
00933 }
00934 
00935 //......................................................................
00936 
00937 Bool_t DbuDaqMonitorModule::WriteVaChipSparsEntry(const RawSparsifierTableBlock* pedblk)
00938 {
00939    // unpack block, build db entries
00940    // send entries off to database
00941 
00942    RawBlockId rbid = pedblk->GetBlockId();
00943    Detector::Detector_t     det = rbid.GetDetector();
00944    SimFlag::SimFlag_t   simflag = rbid.GetSimFlag();
00945 
00946    Int_t crate = pedblk->GetCrateStatus()->GetCrate();
00947    VldTimeStamp loadTime = pedblk->GetLoadTime();
00948 
00949    // loaded values should be good for fVaChipVldSec seconds
00950    const VldTimeStamp timeVld(fVaChipVldSec,0);
00951    VldTimeStamp guessEndTime = loadTime;
00952    guessEndTime.Add(timeVld);
00953 
00954    VldRange vldr(det,simflag,loadTime,guessEndTime,"DBU");
00955    VldTimeStamp creationTime;
00956 
00957    // protect ODBC code against signals
00958    DbuSignalHandler::Instance().Delay();
00959    logInfo("DbuDaqMonitorModule::WriteVaChipSparsEntry() started crate %d",crate);
00960 
00961    // create a DbiWriter
00962    Int_t aggrno = crate;  // aggregate by crate (natural)
00963    Dbi::Task task = 0;
00964    DbiWriter<DbuVaChipSpars> writer(vldr,aggrno,task,creationTime,fDbNo);
00965 
00966    // prepare to loop
00967    DbuVaChipSpars* chip_spars = 0;
00968 
00969    Int_t nvalues = pedblk->GetNumberOfValues();
00970    // go one too far to ensure that last entry gets flushed
00971    // this approach assumes that entries for same chip are consecutive
00972    for (Int_t indx=0; indx<nvalues+1; indx++) {
00973       RawChannelId current_rcid;
00974       Int_t value;
00975       pedblk->GetThresholdValue(indx,current_rcid,value);
00976       if (chip_spars && !chip_spars->fRawChannelId.IsSameVAChip(current_rcid)) {
00977          // saw new chip, output the current entry
00978          // cout << *chip_spars << endl;
00979 
00980          writer << *chip_spars;
00981 
00982          // destroy this one now that we're done with it
00983          delete chip_spars; chip_spars = 0;
00984       }
00985       
00986       // if we just flushed old entry, build new one
00987       if (!chip_spars) chip_spars = new DbuVaChipSpars(current_rcid);
00988 
00989       // set the value
00990       Int_t vachan = current_rcid.GetVaChannel();
00991       if (vachan>=0 && vachan<=21) chip_spars->fChanPed[vachan] = value;
00992       else MSG("Dbu",Msg::kWarning) 
00993          << "Bad Channel on " << current_rcid.AsString()
00994          << " " << current_rcid.AsString("e") << endl;
00995    }
00996    
00997    if (chip_spars) {
00998       RawChannelId current_rcid = chip_spars->fRawChannelId;
00999       if (!current_rcid.IsNull()) {
01000          // this shouldn't happen
01001          MSG("Dbu",Msg::kWarning) 
01002             << "Orphan DbuVaChipSpars on " << current_rcid.AsString()
01003             << " " << current_rcid.AsString("e") << endl;
01004          cout << *chip_spars << endl;
01005 
01006          cout << *pedblk << endl;
01007 
01008          writer << *chip_spars;
01009       }
01010       // avoid any memory leaks
01011       delete chip_spars; chip_spars = 0;
01012    }
01013 
01014    bool success = writer.Close();
01015 
01016    logInfo("DbuDaqMonitorModule::WriteVaChipSparsEntry() success=%d",(int)success);
01017 
01018    // done protecting ODBC code against signals
01019    DbuSignalHandler::Instance().HandleDelayedSignal();
01020 
01021    return success;
01022 
01023 }
01024 
01025 //......................................................................
01026 
01027 void DbuDaqMonitorModule::Help()
01028 {
01029   const char* n = this->GetName();
01030 
01031   MSG("Dbu",Msg::kInfo)
01032      << "Help for module " << n << endl
01033      << endl
01034      << "  A Dbu for generating RunSummary, VaChipPeds, and VaChipSpars entries" << endl
01035      << endl
01036      << "  /" << n << "/Record [which] ..." << endl
01037      << "  /" << n << "/Disregard [which] ..." << endl
01038      << "     controls which information to DBU" << endl
01039      << "     [which] is: " << endl
01040      << "        SubRunSummary - make DbuSubRunSummary entries" << endl
01041      << "        AtStart       - record upon seeing RunStart as well as RunEnd" << endl
01042      << "        VaChipPeds    - make VA chip pedestals" << endl
01043      << "        VaChipSpars   - make VA chip sparsification thersholds" << endl
01044      << "  /" << n << "/Set VaChipVldSec [nsec]" << endl
01045      << "     control the VLD TimeEnd validity beyond load time" << endl
01046      << endl;
01047   
01048 }
01049 

Generated on Mon Nov 23 05:26:34 2009 for loon by  doxygen 1.3.9.1