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

DbiValidityRecBuilder.cxx

Go to the documentation of this file.
00001 // $Id: DbiValidityRecBuilder.cxx,v 1.34 2009/03/12 08:49:05 nwest Exp $
00002 
00003 #include "Conventions/Detector.h"
00004 #include "Conventions/SimFlag.h"
00005 #include "DatabaseInterface/DbiDBProxy.h"
00006 #include "DatabaseInterface/DbiResultNonAgg.h"
00007 #include "DatabaseInterface/DbiResultSet.h"
00008 #include "DatabaseInterface/DbiSimFlagAssociation.h"
00009 #include "DatabaseInterface/DbiValidityRec.h"
00010 #include "DatabaseInterface/DbiValidityRecBuilder.h"
00011 #include "LeakChecker/Lea.h"
00012 #include "MessageService/MsgService.h"
00013 #include "Validity/VldContext.h"
00014 
00015 ClassImp(DbiValidityRecBuilder)
00016 
00017 //   Definition of static data members
00018 //   *********************************
00019 
00020 CVSID("$Id: DbiValidityRecBuilder.cxx,v 1.34 2009/03/12 08:49:05 nwest Exp $");
00021 
00022 //    Definition of all member functions (static or otherwise)
00023 //    *******************************************************
00024 //
00025 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00026 
00027 //.....................................................................
00028 
00029 DbiValidityRecBuilder::DbiValidityRecBuilder(const DbiDBProxy& proxy,
00030                                              const VldContext& vc, 
00031                                              const Dbi::Task& task,
00032                                              Int_t selectDbNo     /* Default: -1 */,
00033                                              Bool_t findFullTimeWindow /* Default: true*/
00034                                              ):
00035 fIsExtendedContext(kFALSE),
00036 fTask(task)
00037 {
00038 //
00039 //  Purpose:  Constructor for specific context queries.
00040 //
00041 //  Arguments:  
00042 //    proxy        in    Database proxy for this table.
00043 //    vc           in    The Validity Context for the query.
00044 //    task         in    The task of the query.
00045 //    selectDbNo   in    If >=0 only look in selected DB.
00046 //    findFullTimeWindow
00047 //                 in    Attempt to find full validity of query 
00048 //                        i.e beyond Dbi::GetTimeGate
00049 //
00050 //  Return:    n/a
00051 //
00052 //  Contact:   N. West
00053 //
00054 //  Specification:-
00055 //  =============
00056 //
00057 //  o Create ValidityRecBuilder by applying a validity query to
00058 //    the database table and building a set of DbiValidityRec
00059 //    objects from the resulting DbiResultSet.
00060 //
00061 // o  Try each member of the cascade in turn until a query succeeds or the 
00062 //    cascade is exhausted.
00063 //
00064 // o  For each member of the cascade try each associated SimFlag in turn 
00065 //    until a query succeeds or the list of associated SimFlags is exhausted.
00066 
00067 
00068 //  Program Notes:-
00069 //  =============
00070 
00071 //  None.
00072 
00073   LEA_CTOR    //Leak Checker
00074 
00075   MSG("Dbi", Msg::kVerbose) << "Creating DbiValidityRecBuilder" << endl;
00076 
00077   Detector::Detector_t     det(vc.GetDetector());
00078   SimFlag::SimFlag_t       sim(vc.GetSimFlag());
00079   VldTimeStamp             ts(vc.GetTimeStamp());
00080   SimFlag::SimFlag_t       simTry(sim);
00081   const string& tableName = proxy.GetTableName();
00082   Int_t sumTimeWindows = 0;
00083   Int_t numTimeWindows = 0;
00084 
00085 //  Contruct a default (gap) validity record fGap.
00086 //  If findFullTimeWindow then gap will be unlimited but will be trimmed
00087 //  after each query.
00088 
00089   this->MakeGapRec(vc, tableName, findFullTimeWindow);
00090 
00091 //  Force aggregate -1 into first slot.
00092   this->AddNewGap(-1);
00093 
00094   const VldTimeStamp curVTS = vc.GetTimeStamp();
00095 
00096 // Check to see if table exists.
00097 
00098   unsigned int numVRecIn = 0;
00099 
00100   if ( ! proxy.TableExists() ) {
00101     MAXMSG("Dbi", Msg::kWarning,10) 
00102          << "DbiValidityRecBuilder::Query for table:" 
00103          << proxy.GetTableName() 
00104          << ", table does not exist!" << endl;
00105   }
00106 
00107   else {
00108     
00109 //  Loop over all databases in cascade until valid data found.
00110 
00111     UInt_t numDb     = proxy.GetNumDb();
00112     Bool_t foundData = kFALSE;
00113 
00114     for ( UInt_t dbNo = 0; dbNo < numDb && ! foundData; ++dbNo ) {
00115 
00116       // Skip if cascade entry does not have this table or selection in force and not the required one.
00117       if ( ! proxy.TableExists(dbNo) ) continue;
00118       if ( selectDbNo >= 0 && selectDbNo != (int) dbNo ) continue;
00119 
00120 //    Loop over all associated SimFlags.
00121 
00122       DbiSimFlagAssociation::SimList_t simList 
00123                     = DbiSimFlagAssociation::Instance().Get(sim);
00124 
00125       DbiSimFlagAssociation::SimList_t::iterator listItr    = simList.begin();
00126       DbiSimFlagAssociation::SimList_t::iterator listItrEnd = simList.end();
00127       while ( listItr !=  listItrEnd && ! foundData ) {
00128 
00129         simTry = *listItr;
00130         ++listItr;
00131         VldContext vcTry(det,simTry,ts);
00132 
00133 //      Apply validity query and build result set.
00134 
00135         DbiResultSet* rs = proxy.QueryValidity(vcTry,fTask,dbNo);
00136 
00137 //      Build a result from the result set and drop result set.
00138 
00139         DbiValidityRec tr;
00140         DbiResultNonAgg result(rs,&tr,0,kFALSE);
00141         delete rs;
00142 
00143 //      Loop over all entries in DbiResult and, for each Aggregate, 
00144 //      find effective validity range of best, or of gap if none.
00145 
00146 //      Set earliest creation date to infinite past - the right value if in a gap.
00147         VldTimeStamp earliestCreate(0);
00148         UInt_t numRows = result.GetNumRows();
00149         for (UInt_t row = 0; row < numRows; ++row) {
00150           const DbiValidityRec* vr = dynamic_cast<const DbiValidityRec*>(
00151                                             result.GetTableRow(row));
00152 
00153           Int_t aggNo = vr->GetAggregateNo();
00154       
00155 //        If starting a new aggregate prime it as a gap.
00156           Int_t index = this->IndexOfAggno(aggNo);
00157           if ( index < 0 ) index = this->AddNewGap(aggNo);
00158 
00159 //        Trim the validity record for the current aggregate
00160 //        number by this record and see if we have found valid
00161 //        data yet.
00162   
00163           DbiValidityRec& curRec = fVRecs[index];
00164           curRec.Trim(curVTS, *vr);
00165           if ( ! curRec.IsGap() ) {
00166             foundData = kTRUE;
00167 
00168 //          Fill in entry's database number - its not stored in the 
00169 //          database table!
00170             curRec.SetDbNo(dbNo);
00171           }
00172 
00173 //        Find the earliest non-gap creation date that is used
00174           if (     curRec.GetSeqNo() ==   vr->GetSeqNo()
00175                    &&  (    earliestCreate > vr->GetCreationDate() 
00176                          || earliestCreate.GetSec() == 0 )
00177              ) earliestCreate = vr->GetCreationDate();
00178 
00179 //        Count the number used and sum the time windows
00180           ++numVRecIn;
00181           const VldRange range = vr->GetVldRange();
00182           Int_t timeInterval =   range.GetTimeEnd().GetSec() 
00183                                - range.GetTimeStart().GetSec();
00184           if ( timeInterval < 5 ) {
00185             MAXMSG("Dbi",Msg::kWarning,20) 
00186             << "Detected suspiciously small validity time interval in \n"
00187             << "table " << tableName << " validity rec " << *vr << endl;
00188           }
00189           sumTimeWindows += timeInterval;
00190           ++numTimeWindows;
00191         }
00192 
00193 //      If finding findFullTimeWindow then find bounding limits 
00194 //      for the cascade and sim flag and trim all validity records
00195 //      and the default (gap) validity record.
00196         if ( findFullTimeWindow ) {
00197           VldTimeStamp start, end;
00198           proxy.FindTimeBoundaries(vcTry,fTask,dbNo,earliestCreate,start,end);
00199           MSGSTREAM("Dbi",Msg::kDebug) << "Trimming validity records to " 
00200                                       << start << " .. " << end << endl;
00201           std::vector<DbiValidityRec>::iterator itr(fVRecs.begin()), itrEnd(fVRecs.end());
00202           for( ; itr != itrEnd; ++itr ) itr->AndTimeWindow(start,end);
00203           fGap.AndTimeWindow(start,end);
00204         }
00205       }
00206 
00207     }
00208   }
00209 
00210 //  If the query found no records in any database then
00211 //  the tables will still have something - the aggno = -1 gap
00212 
00213 // If the associated SimFlag is different to the original request make
00214 // sure that all the DbiValidityRec are valid for the request.
00215   if ( sim != simTry ) {
00216     MSG("Dbi",Msg::kSynopsis) << "Imposing SimFlag of " << sim << " on DbiValidityRecs which matched " << simTry << endl; 
00217     for ( unsigned int irec = 0; irec < GetNumValidityRec(); ++irec ) {
00218       DbiValidityRec& vrec = const_cast<DbiValidityRec&>(GetValidityRec(irec));
00219       const VldRange& vr(vrec.GetVldRange());
00220       VldRange vr_mod(vr.GetDetectorMask(),sim,vr.GetTimeStart(),vr.GetTimeEnd(),vr.GetDataSource());
00221       vrec.SetVldRange(vr_mod);
00222     }
00223   }
00224 
00225   MsgStream& msg =  MSGSTREAM("Dbi",Msg::kSynopsis);
00226   msg << "DbiValidityRecBuilder:" << endl 
00227       << " Query: " << vc.AsString() << endl
00228       << " using associated SimFlag: " << SimFlag::AsString(simTry)
00229       << " for " << SimFlag::AsString(sim)
00230       << " found " << numVRecIn 
00231       << " vrecs in database, for " << fVRecs.size()
00232       << " aggregates:-." << endl;
00233 
00234   for ( unsigned int irec = 0; irec < GetNumValidityRec(); ++irec ) {
00235     const DbiValidityRec& vrec = GetValidityRec(irec);
00236     if ( vrec.GetAggregateNo() != -2 
00237          )   msg << " " << irec << " " << GetValidityRec(irec) << endl;
00238   }
00239 
00240 
00241 
00242 // Adjust the time gate if grossly wrong.
00243   if ( numTimeWindows > 0 ) {
00244     Int_t timeGateCalc = 3 * fVRecs.size() * sumTimeWindows/numTimeWindows;
00245     // Limit to 100 days and allow for overflow.
00246     if ( timeGateCalc > 100*24*60*60 || timeGateCalc < 0 
00247        ) timeGateCalc = 100*24*60*60;
00248     Int_t timeGateCurr = Dbi::GetTimeGate(tableName);
00249     if (    timeGateCurr < timeGateCalc/10 
00250          || timeGateCurr > timeGateCalc*10 
00251             ) {
00252       Dbi::SetTimeGate(tableName,timeGateCalc);
00253       if ( timeGateCalc != Dbi::GetTimeGate(tableName) ) {
00254         MAXMSG("Dbi",Msg::kWarning,20) 
00255           << "The ignored time gate setting was calculated with the following data:-" 
00256           << "\n   Context: " << vc << " task " << task  << " findFullTimeWindow " << findFullTimeWindow
00257           << "\n   Number of vrecs " << numTimeWindows 
00258           << " total time (secs) of all vrecs " << sumTimeWindows
00259           << " Number of aggregates " << fVRecs.size() << endl;
00260       }
00261     }
00262   }
00263 
00264   return;
00265 
00266 }
00267 
00268 //.....................................................................
00269 
00270 DbiValidityRecBuilder::DbiValidityRecBuilder(const DbiDBProxy& proxy,
00271                                              const string& context,
00272                                              const Dbi::Task& task):
00273 fIsExtendedContext(kTRUE),
00274 fTask(task)
00275 {
00276 //
00277 //  Purpose:  Constructor for extended context queries.
00278 //
00279 //  Arguments:  
00280 //    proxy        in    Database proxy for this table.
00281 //    context      in    The SQL corresponding to the extended context for the query.
00282 //    task         in    The task of the query.
00283 //
00284 //  Return:    n/a
00285 //
00286 //  Contact:   N. West
00287 //
00288 //  Specification:-
00289 //  =============
00290 //
00291 //  o Create ValidityRecBuilder by applying a validity query to
00292 //    the database table and building a set of DbiValidityRec
00293 //    objects from the resulting DbiResultSet.
00294 
00295 
00296 //  Program Notes:-
00297 //  =============
00298 
00299 //  None.
00300 
00301   LEA_CTOR    //Leak Checker
00302 
00303   MSG("Dbi", Msg::kVerbose) << "Creating DbiValidityRecBuilder" 
00304                             << " for extended context " << context << endl;
00305 
00306 // Prime fVRecs with a gap that will not be used but makes the result
00307 // look like an aggregated result.
00308 
00309   MSG("Dbi", Msg::kVerbose) << "Initialising with gap record " << fGap << endl;
00310   this->AddNewGap(-1);
00311 
00312 // Check to see if table exists.
00313 
00314   unsigned int numVRecIn = 0;
00315 
00316   if ( ! proxy.TableExists() ) {
00317     MSG("Dbi", Msg::kWarning) 
00318          << "DbiValidityRecBuilder::Query for table:" 
00319          << proxy.GetTableName() 
00320          << ", table does not exist!" << endl;
00321   }
00322 
00323   else if ( context == "" ) {
00324     MSG("Dbi", Msg::kWarning) 
00325          << "DbiValidityRecBuilder::Null query for table:" 
00326          << proxy.GetTableName() << endl;
00327   }
00328 
00329   else {
00330     
00331 //  Loop over all databases in cascade until valid data found.
00332 
00333     UInt_t numDb     = proxy.GetNumDb();
00334     Bool_t foundData = kFALSE;
00335  
00336     for ( UInt_t dbNo = 0; dbNo < numDb && ! foundData; ++dbNo ) {
00337 
00338 //    Apply validity query and build result set.
00339 
00340       DbiResultSet* rs = proxy.QueryValidity(context,fTask,dbNo);
00341 
00342 //    Build a result from the result set and drop result set.
00343 
00344       DbiValidityRec tr;
00345       DbiResultNonAgg result(rs,&tr,0,kFALSE);
00346       delete rs;
00347 
00348 //    Loop over all entries in DbiResult and add them all to set.
00349 
00350       UInt_t numRows = result.GetNumRows();
00351       for (UInt_t row = 0; row < numRows; ++row) {
00352         const DbiValidityRec* vr = dynamic_cast<const DbiValidityRec*>(
00353                                           result.GetTableRow(row));
00354         
00355 //      Cannot use AddNewAgg - aggregate numbers may be duplicated.
00356         Int_t index = fVRecs.size();
00357         fVRecs.push_back(DbiValidityRec(*vr));
00358         fAggNoToIndex[vr->GetAggregateNo()] = index;
00359         foundData = kTRUE;
00360         
00361 //      Fill in entry's database number - its not stored in the 
00362 //      database table!
00363         fVRecs[index].SetDbNo(dbNo);
00364 
00365 //      Count the number used.
00366         ++numVRecIn;
00367       }
00368     }
00369   }
00370 
00371   MsgStream& msg =  MSGSTREAM("Dbi",Msg::kSynopsis);
00372   msg << "DbiValidityRecBuilder:" << endl 
00373       << " Extended context query: " << context << endl
00374       << " found " << numVRecIn 
00375       << " vrecs in database, for " << fVRecs.size()
00376       << " records:-." << endl;
00377 
00378   for ( unsigned int irec = 0; irec < GetNumValidityRec(); ++irec ) {
00379     msg << " " << irec << " " << GetValidityRec(irec) << endl;
00380   }
00381   return;
00382 
00383 
00384   
00385 }
00386 
00387 //.....................................................................
00388 
00389 DbiValidityRecBuilder::DbiValidityRecBuilder(const DbiValidityRec& vr,
00390                                              const std::string tableName):
00391 fIsExtendedContext(kFALSE),
00392 fTask(vr.GetTask())
00393 {
00394 //
00395 //  Purpose:  Constructor for an existing query result.
00396 //
00397 //  Arguments:  
00398 //    vr           in    The DbiValidityRec from the query.
00399 //    tableName    in    The name of the table that satisfied the query 
00400 
00401   LEA_CTOR    //Leak Checker
00402 
00403   MSG("Dbi", Msg::kVerbose) << "Creating DbiValidityRecBuilder" << endl;
00404 
00405   const VldRange&          vrange(vr.GetVldRange());
00406   // This is the only way I can find to handle Detector and SimFlag!
00407   VldContext vc( (Detector::Detector_t) vrange.GetDetectorMask(),
00408                  (SimFlag::SimFlag_t) vrange.GetSimMask(),
00409                  vrange.GetTimeStart());
00410   this->MakeGapRec(vc,tableName);
00411   this->AddNewAgg(vr,vr.GetAggregateNo());
00412 
00413 }
00414 //.....................................................................
00415 
00416 DbiValidityRecBuilder::~DbiValidityRecBuilder() {
00417 //
00418 //
00419 //  Purpose: Destructor
00420 //
00421 //  Arguments: 
00422 //    None.
00423 //
00424 //  Return:    n/a
00425 //
00426 //  Contact:   N. West
00427 //
00428 //  Specification:-
00429 //  =============
00430 //
00431 //  o  Destroy ValidityRecBuilder.
00432 
00433 
00434 //  Program Notes:-
00435 //  =============
00436 
00437 //  None.
00438 
00439   LEA_DTOR    //Leak Checker
00440 
00441   MSG("Dbi", Msg::kVerbose)
00442     << "Destroying DbiValidityRecBuilder" << endl;
00443 
00444 }
00445 
00446 //.....................................................................
00447 
00448 std::string DbiValidityRecBuilder::GetL2CacheName() const {
00449 //
00450 //
00451 //  Purpose:  Return the associated Level 2 Cache Name.
00452 //
00453 //  Specification:-
00454 //  =============
00455 //
00456 //  o For format see static DbiValidityRec::GetL2CacheName.
00457 //
00458 //  Gaps are excluded (and if all are gaps the returned name is empty).
00459 
00460 
00461 // Extended Context queries are not L2 cached.
00462   if ( this->IsExtendedContext() ) return "";
00463 
00464   UInt_t seqLo = 0;
00465   UInt_t seqHi = 0;
00466   VldTimeStamp ts;
00467   std::vector<DbiValidityRec>::const_iterator itr = fVRecs.begin();
00468   std::vector<DbiValidityRec>::const_iterator end = fVRecs.end();
00469   
00470   for (; itr != end; ++itr) {
00471     const DbiValidityRec& vr = *itr;
00472     if ( ! vr.IsGap() ) {
00473       if ( seqLo == 0 ) {
00474         seqLo = vr.GetSeqNo();
00475         seqHi = vr.GetSeqNo();
00476         ts    = vr.GetCreationDate();
00477       }
00478       else {
00479         if ( seqLo < vr.GetSeqNo() )        seqLo = vr.GetSeqNo();
00480         if ( seqHi > vr.GetSeqNo() )        seqHi = vr.GetSeqNo();
00481         if ( ts    < vr.GetCreationDate() ) ts    = vr.GetCreationDate(); 
00482       }
00483     }
00484   }
00485 
00486   if ( seqLo == 0 ) return "";
00487   
00488   return DbiValidityRec::GetL2CacheName(seqLo,seqHi,ts);
00489 
00490 }
00491   
00492 //.....................................................................
00493 
00494 UInt_t DbiValidityRecBuilder::AddNewAgg(const DbiValidityRec& vrec,Int_t aggNo) {
00495 //
00496 //
00497 //  Purpose:   Add new aggregate into tables and return its index.
00498 //
00499 //  Program Notes:-
00500 //  =============
00501 //
00502 //  aggNo is passed in and not obtained from vrec, so that it can be the gap.
00503 
00504   //  Make sure it really doesn't exist.
00505   int index = this->IndexOfAggno(aggNo);
00506   if ( index >=0 ) return index;
00507 
00508   // It doesn't so add it.
00509   index = fVRecs.size();
00510   fVRecs.push_back(vrec);
00511   fAggNoToIndex[aggNo] = index;
00512   return index;
00513 
00514 }
00515 
00516 //.....................................................................
00517 
00518 UInt_t DbiValidityRecBuilder::AddNewGap(Int_t aggNo) {
00519 //
00520 //
00521 //  Purpose:  Add new aggregate gap into tables and return its index
00522 
00523   UInt_t index = this->AddNewAgg(fGap,aggNo);
00524   fVRecs[index].SetAggregateNo(aggNo);
00525   return index;
00526 
00527 }
00528    
00529 //.....................................................................
00530 
00531 const DbiValidityRec& 
00532               DbiValidityRecBuilder::GetValidityRec(Int_t rowNo) const {
00533 //
00534 //
00535 //  Purpose: Return validity record for supplied row number. 
00536 
00537   return (rowNo < 0 || rowNo >= (int) fVRecs.size()) ? fGap : fVRecs[rowNo];
00538 }
00539 
00540 //.....................................................................
00541 
00542 const DbiValidityRec& 
00543               DbiValidityRecBuilder::GetValidityRecFromSeqNo(UInt_t SeqNo) const {
00544 //
00545 //
00546 //  Purpose: Return validity record for supplied SeqNo. 
00547 
00548   std::vector<DbiValidityRec>::const_iterator itr = fVRecs.begin();
00549   std::vector<DbiValidityRec>::const_iterator end = fVRecs.end();
00550   
00551   for (; itr != end; ++itr) if ( itr->GetSeqNo() == SeqNo ) return *itr;
00552   return fGap;
00553 }
00554 
00555 //.....................................................................
00556 
00557 Int_t DbiValidityRecBuilder::IndexOfAggno(Int_t aggNo) const {
00558 //
00559 //
00560 //  Purpose:   Get index of AggNo or -1 if missing.
00561 
00562   std::map<Int_t,UInt_t>::const_iterator itr = fAggNoToIndex.find(aggNo);
00563   if ( itr == fAggNoToIndex.end() ) return -1;
00564   return itr->second;
00565 
00566 }
00567 
00568 //.....................................................................
00569 
00570 void DbiValidityRecBuilder::MakeGapRec(const VldContext& vc, 
00571                                        const string& tableName,
00572                                        Bool_t findFullTimeWindow) {
00573 //
00574 //
00575 //  Purpose:  Construct Gap Record
00576 //
00577 //  Arguments: 
00578 //    vc           in    The Validity Context for the query.
00579 //    tableName    in    The name of the table being queried.
00580 //    findFullTimeWindow
00581 //                 in    Attempt to find full validity of query 
00582 //                        i.e. beyond Dbi::GetTimeGate
00583 //
00584 //  Return:        None.
00585 //
00586 //  Contact:   N. West
00587 //
00588 //  Specification:-
00589 //  =============
00590 //
00591 //  o Create the data member gap record fGap centered on the current
00592 //    query time.
00593 
00594 //  Program Notes:-
00595 //  =============
00596 
00597 //  None.
00598 
00599   Int_t timeGate = Dbi::GetTimeGate(tableName);
00600   time_t contextSec = vc.GetTimeStamp().GetSec() - timeGate;
00601   VldTimeStamp startGate(contextSec,0);
00602   contextSec += 2*timeGate;
00603   VldTimeStamp endGate(contextSec,0);
00604   if ( findFullTimeWindow ) {
00605     startGate = VldTimeStamp(0,0);
00606     endGate   = VldTimeStamp(0x7FFFFFFF,0);
00607   }
00608   VldRange gapVR(vc.GetDetector(), vc.GetSimFlag(), startGate, endGate, "Gap");
00609   fGap =  DbiValidityRec(gapVR, fTask, -2, 0, 0, kTRUE);
00610 
00611 }
00612 

Generated on Sat Nov 21 22:45:53 2009 for loon by  doxygen 1.3.9.1