TDbiValidityRecBuilder.cxx

Go to the documentation of this file.
00001 // $Id: TDbiValidityRecBuilder.cxx,v 1.1 2011/01/18 05:49:20 finch Exp $
00002 
00003 #include "DbiDetector.hxx"
00004 #include "DbiSimFlag.hxx"
00005 #include "TDbiDBProxy.hxx"
00006 #include "TDbiResultSetNonAgg.hxx"
00007 #include "TDbiInRowStream.hxx"
00008 #include "TDbiSimFlagAssociation.hxx"
00009 #include "TDbiValidityRec.hxx"
00010 #include "TDbiValidityRecBuilder.hxx"
00011 #include <TSK_DBI_Log.hxx>
00012 #include <MsgFormat.h>
00013 using std::endl;
00014 #include "TVldContext.hxx"
00015 
00016 ClassImp(TDbiValidityRecBuilder)
00017 
00018 //   Definition of static data members
00019 //   *********************************
00020 
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 TDbiValidityRecBuilder::TDbiValidityRecBuilder(const TDbiDBProxy& proxy,
00030                                              const TVldContext& vc,
00031                                              const TDbi::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 TDbi::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 TDbiValidityRec
00059 //    objects from the resulting TDbiInRowStream.
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 
00074   SK_DBI_Trace( "Creating TDbiValidityRecBuilder" << "  ");
00075 
00076   DbiDetector::Detector_t     det(vc.GetDetector());
00077   DbiSimFlag::SimFlag_t       sim(vc.GetSimFlag());
00078   TVldTimeStamp             ts(vc.GetTimeStamp());
00079   DbiSimFlag::SimFlag_t       simTry(sim);
00080   const string& tableName = proxy.GetTableName();
00081   Int_t sumTimeWindows = 0;
00082   Int_t numTimeWindows = 0;
00083 
00084 //  Contruct a default (gap) validity record fGap.
00085 //  If findFullTimeWindow then gap will be unlimited but will be trimmed
00086 //  after each query.
00087 
00088   this->MakeGapRec(vc, tableName, findFullTimeWindow);
00089 
00090 //  Force aggregate -1 into first slot.
00091   this->AddNewGap(-1);
00092 
00093   const TVldTimeStamp curVTS = vc.GetTimeStamp();
00094 
00095 // Check to see if table exists.
00096 
00097   unsigned int numVRecIn = 0;
00098 
00099   if ( ! proxy.TableExists() ) {
00100        SK_DBI_Warn(  "TDbiValidityRecBuilder::Query for table:"
00101          << proxy.GetTableName()
00102          << ", table does not exist!" << "  ");
00103   }
00104 
00105   else {
00106 
00107 //  Loop over all databases in cascade until valid data found.
00108 
00109 //  Determine the resolution scheme for resolving VLD overlaps.
00110     Bool_t resolveByCreationDate = ! proxy.HasEpoch();
00111 
00112     UInt_t numDb     = proxy.GetNumDb();
00113     Bool_t foundData = kFALSE;
00114 
00115     for ( UInt_t dbNo = 0; dbNo < numDb && ! foundData; ++dbNo ) {
00116 
00117       // Skip if cascade entry does not have this table or selection in force and not the required one.
00118       if ( ! proxy.TableExists(dbNo) ) continue;
00119       if ( selectDbNo >= 0 && selectDbNo != (int) dbNo ) continue;
00120 
00121 //    Loop over all associated SimFlags.
00122 
00123       TDbiSimFlagAssociation::SimList_t simList
00124                     = TDbiSimFlagAssociation::Instance().Get(sim);
00125 
00126       TDbiSimFlagAssociation::SimList_t::iterator listItr    = simList.begin();
00127       TDbiSimFlagAssociation::SimList_t::iterator listItrEnd = simList.end();
00128       while ( listItr !=  listItrEnd && ! foundData ) {
00129 
00130         simTry = *listItr;
00131         ++listItr;
00132         TVldContext vcTry(det,simTry,ts);
00133 
00134 //      Apply validity query and build result set.
00135 
00136         TDbiInRowStream* rs = proxy.QueryValidity(vcTry,fTask,dbNo);
00137 
00138 //      Build a result from the result set and drop result set.
00139 
00140         TDbiValidityRec tr;
00141         TDbiResultSetNonAgg result(rs,&tr,0,kFALSE);
00142         delete rs;
00143 
00144 //      Loop over all entries in TDbiResultSet and, for each Aggregate,
00145 //      find effective validity range of best, or of gap if none.
00146 
00147 //      Initialise lowest priority VLD to a gap. It will be used by FindTimeBoundaries.
00148         const TDbiValidityRec* lowestPriorityVrec = &fGap;
00149 
00150         UInt_t numRows = result.GetNumRows();
00151         for (UInt_t row = 0; row < numRows; ++row) {
00152           const TDbiValidityRec* vr = dynamic_cast<const TDbiValidityRec*>(
00153                                             result.GetTableRow(row));
00154 
00155           Int_t aggNo = vr->GetAggregateNo();
00156 
00157 //        If starting a new aggregate prime it as a gap.
00158           Int_t index = this->IndexOfAggno(aggNo);
00159           if ( index < 0 ) index = this->AddNewGap(aggNo);
00160 
00161 //        Trim the validity record for the current aggregate
00162 //        number by this record and see if we have found valid
00163 //        data yet.
00164 
00165           TDbiValidityRec& curRec = fVRecs[index];
00166           curRec.Trim(curVTS, *vr);
00167           if ( ! curRec.IsGap() ) {
00168             foundData = kTRUE;
00169 
00170 //          Fill in entry's database number - its not stored in the
00171 //          database table!
00172             curRec.SetDbNo(dbNo);
00173           }
00174 
00175 //        Find the lowest priority non-gap VLD  that is used
00176           if (    lowestPriorityVrec->IsGap()
00177                || lowestPriorityVrec->IsHigherPriority(curRec,resolveByCreationDate)
00178                   )lowestPriorityVrec = &curRec;
00179 
00180 //        Count the number used and sum the time windows
00181           ++numVRecIn;
00182           const TVldRange range = vr->GetVldRange();
00183           Int_t timeInterval =   range.GetTimeEnd().GetSec()
00184                                - range.GetTimeStart().GetSec();
00185           if ( timeInterval < 5 ) {
00186                SK_DBI_Warn(  "Detected suspiciously small validity time interval in \n"
00187             << "table " << tableName << " validity rec " << *vr << "  ");
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           TVldTimeStamp start, end;
00198           proxy.FindTimeBoundaries(vcTry,fTask,dbNo,*lowestPriorityVrec,resolveByCreationDate,start,end);
00199      SK_DBI_Debug("Trimming validity records to "
00200     << start << " .. " << end << "  ");
00201           std::vector<TDbiValidityRec>::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 TDbiValidityRec are valid for the request.
00215   if ( sim != simTry ) {
00216     SK_DBI_Log( "Imposing SimFlag of " << sim << " on TDbiValidityRecs which matched " << simTry << "  ");
00217     for ( unsigned int irec = 0; irec < GetNumValidityRec(); ++irec ) {
00218       TDbiValidityRec& vrec = const_cast<TDbiValidityRec&>(GetValidityRec(irec));
00219       const TVldRange& vr(vrec.GetVldRange());
00220       TVldRange vr_mod(vr.GetDetectorMask(),sim,vr.GetTimeStart(),vr.GetTimeEnd(),vr.GetDataSource());
00221       vrec.SetVldRange(vr_mod);
00222     }
00223   }
00224 
00225   // hand edit applied 
00226   
00227   SK_DBI_Verbose("TDbiValidityRecBuilder:" << endl
00228                << " Query: " << vc.AsString() << endl
00229                << " using associated SimFlag: " << DbiSimFlag::AsString(simTry)
00230                << " for " << DbiSimFlag::AsString(sim)
00231                << " found " << numVRecIn
00232                << " vrecs in database, for " << fVRecs.size()
00233                << " aggregates:-.");
00234   
00235   for ( unsigned int irec = 0; irec < GetNumValidityRec(); ++irec ) {
00236     const TDbiValidityRec& vrec = GetValidityRec(irec);
00237     if ( vrec.GetAggregateNo() != -2)   
00238       SK_DBI_Verbose(" " << irec << " " << GetValidityRec(irec));
00239   }
00240 
00241 
00242 
00243 // Adjust the time gate if grossly wrong.
00244   if ( numTimeWindows > 0 ) {
00245     Int_t timeGateCalc = 3 * fVRecs.size() * sumTimeWindows/numTimeWindows;
00246     // Limit to 100 days and allow for overflow.
00247     if ( timeGateCalc > 100*24*60*60 || timeGateCalc < 0
00248        ) timeGateCalc = 100*24*60*60;
00249     Int_t timeGateCurr = TDbi::GetTimeGate(tableName);
00250     if (    timeGateCurr < timeGateCalc/10
00251          || timeGateCurr > timeGateCalc*10
00252             ) {
00253       TDbi::SetTimeGate(tableName,timeGateCalc);
00254       if ( timeGateCalc != TDbi::GetTimeGate(tableName) ) {
00255            SK_DBI_Warn(  "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() << "  ");
00260       }
00261     }
00262   }
00263 
00264   return;
00265 
00266 }
00267 
00268 //.....................................................................
00269 
00270 TDbiValidityRecBuilder::TDbiValidityRecBuilder(const TDbiDBProxy& proxy,
00271                                              const string& context,
00272                                              const TDbi::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 TDbiValidityRec
00293 //    objects from the resulting TDbiInRowStream.
00294 
00295 
00296 //  Program Notes:-
00297 //  =============
00298 
00299 //  None.
00300 
00301 
00302   SK_DBI_Trace( "Creating TDbiValidityRecBuilder"
00303                             << " for extended context " << context << "  ");
00304 
00305 // Prime fVRecs with a gap that will not be used but makes the result
00306 // look like an aggregated result.
00307 
00308   SK_DBI_Verbose( "Initialising with gap record " << fGap << "  ");
00309   this->AddNewGap(-1);
00310 
00311 // Check to see if table exists.
00312 
00313   unsigned int numVRecIn = 0;
00314 
00315   if ( ! proxy.TableExists() ) {
00316     SK_DBI_Warn(  "TDbiValidityRecBuilder::Query for table:"
00317          << proxy.GetTableName()
00318          << ", table does not exist!" << "  ");
00319   }
00320 
00321   else if ( context == "" ) {
00322     SK_DBI_Warn(  "TDbiValidityRecBuilder::Null query for table:"
00323          << proxy.GetTableName() << "  ");
00324   }
00325 
00326   else {
00327 
00328 //  Loop over all databases in cascade until valid data found.
00329 
00330     UInt_t numDb     = proxy.GetNumDb();
00331     Bool_t foundData = kFALSE;
00332 
00333     for ( UInt_t dbNo = 0; dbNo < numDb && ! foundData; ++dbNo ) {
00334 
00335 //    Apply validity query and build result set.
00336 
00337       TDbiInRowStream* rs = proxy.QueryValidity(context,fTask,dbNo);
00338 
00339 //    Build a result from the result set and drop result set.
00340 
00341       TDbiValidityRec tr;
00342       TDbiResultSetNonAgg result(rs,&tr,0,kFALSE);
00343       delete rs;
00344 
00345 //    Loop over all entries in TDbiResultSet and add them all to set.
00346 
00347       UInt_t numRows = result.GetNumRows();
00348       for (UInt_t row = 0; row < numRows; ++row) {
00349         const TDbiValidityRec* vr = dynamic_cast<const TDbiValidityRec*>(
00350                                           result.GetTableRow(row));
00351 
00352 //      Cannot use AddNewAgg - aggregate numbers may be duplicated.
00353         Int_t index = fVRecs.size();
00354         fVRecs.push_back(TDbiValidityRec(*vr));
00355         fAggNoToIndex[vr->GetAggregateNo()] = index;
00356         foundData = kTRUE;
00357         
00358 //      Fill in entry's database number - its not stored in the
00359 //      database table!
00360         fVRecs[index].SetDbNo(dbNo);
00361 
00362 //      Count the number used.
00363         ++numVRecIn;
00364       }
00365     }
00366   }
00367 
00368   // hand edit required
00369   // if( TSK_DBI_Log::GetLogLevel() >= TSK_DBI_Log::kLogLevel
00370   //    std::ostream& msg=TSK_DBI_Log::GetLogStream();
00371 
00372   SK_DBI_Verbose("TDbiValidityRecBuilder:" << endl
00373       << " Extended context query: " << context << endl
00374       << " found " << numVRecIn
00375       << " vrecs in database, for " << fVRecs.size()
00376                << " records:-.");
00377 
00378   for ( unsigned int irec = 0; irec < GetNumValidityRec(); ++irec ) {
00379     SK_DBI_Verbose(" " << irec << " " << GetValidityRec(irec));
00380   }
00381   return;
00382 
00383 
00384 
00385 }
00386 
00387 //.....................................................................
00388 
00389 TDbiValidityRecBuilder::TDbiValidityRecBuilder(const TDbiValidityRec& 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 TDbiValidityRec from the query.
00399 //    tableName    in    The name of the table that satisfied the query
00400 
00401 
00402   SK_DBI_Trace( "Creating TDbiValidityRecBuilder" << "  ");
00403 
00404   const TVldRange&          vrange(vr.GetVldRange());
00405   // This is the only way I can find to handle Detector and SimFlag!
00406   TVldContext vc( (DbiDetector::Detector_t) vrange.GetDetectorMask(),
00407                  (DbiSimFlag::SimFlag_t) vrange.GetSimMask(),
00408                  vrange.GetTimeStart());
00409   this->MakeGapRec(vc,tableName);
00410   this->AddNewAgg(vr,vr.GetAggregateNo());
00411 
00412 }
00413 //.....................................................................
00414 
00415 TDbiValidityRecBuilder::~TDbiValidityRecBuilder() {
00416 //
00417 //
00418 //  Purpose: Destructor
00419 //
00420 //  Arguments:
00421 //    None.
00422 //
00423 //  Return:    n/a
00424 //
00425 //  Contact:   N. West
00426 //
00427 //  Specification:-
00428 //  =============
00429 //
00430 //  o  Destroy ValidityRecBuilder.
00431 
00432 
00433 //  Program Notes:-
00434 //  =============
00435 
00436 //  None.
00437 
00438 
00439   SK_DBI_Trace(  "Destroying TDbiValidityRecBuilder" << "  ");
00440 
00441 }
00442 
00443 //.....................................................................
00444 
00445 std::string TDbiValidityRecBuilder::GetL2CacheName() const {
00446 //
00447 //
00448 //  Purpose:  Return the associated Level 2 Cache Name.
00449 //
00450 //  Specification:-
00451 //  =============
00452 //
00453 //  o For format see static TDbiValidityRec::GetL2CacheName.
00454 //
00455 //  Gaps are excluded (and if all are gaps the returned name is empty).
00456 
00457 
00458 // Extended Context queries are not L2 cached.
00459   if ( this->IsExtendedContext() ) return "";
00460 
00461   UInt_t seqLo = 0;
00462   UInt_t seqHi = 0;
00463   TVldTimeStamp ts;
00464   std::vector<TDbiValidityRec>::const_iterator itr = fVRecs.begin();
00465   std::vector<TDbiValidityRec>::const_iterator end = fVRecs.end();
00466 
00467   for (; itr != end; ++itr) {
00468     const TDbiValidityRec& vr = *itr;
00469     if ( ! vr.IsGap() ) {
00470       if ( seqLo == 0 ) {
00471         seqLo = vr.GetSeqNo();
00472         seqHi = vr.GetSeqNo();
00473         ts    = vr.GetCreationDate();
00474       }
00475       else {
00476         if ( seqLo < vr.GetSeqNo() )        seqLo = vr.GetSeqNo();
00477         if ( seqHi > vr.GetSeqNo() )        seqHi = vr.GetSeqNo();
00478         if ( ts    < vr.GetCreationDate() ) ts    = vr.GetCreationDate();
00479       }
00480     }
00481   }
00482 
00483   if ( seqLo == 0 ) return "";
00484 
00485   return TDbiValidityRec::GetL2CacheName(seqLo,seqHi,ts);
00486 
00487 }
00488 
00489 //.....................................................................
00490 
00491 UInt_t TDbiValidityRecBuilder::AddNewAgg(const TDbiValidityRec& vrec,Int_t aggNo) {
00492 //
00493 //
00494 //  Purpose:   Add new aggregate into tables and return its index.
00495 //
00496 //  Program Notes:-
00497 //  =============
00498 //
00499 //  aggNo is passed in and not obtained from vrec, so that it can be the gap.
00500 
00501   //  Make sure it really doesn't exist.
00502   int index = this->IndexOfAggno(aggNo);
00503   if ( index >=0 ) return index;
00504 
00505   // It doesn't so add it.
00506   index = fVRecs.size();
00507   fVRecs.push_back(vrec);
00508   fAggNoToIndex[aggNo] = index;
00509   return index;
00510 
00511 }
00512 
00513 //.....................................................................
00514 
00515 UInt_t TDbiValidityRecBuilder::AddNewGap(Int_t aggNo) {
00516 //
00517 //
00518 //  Purpose:  Add new aggregate gap into tables and return its index
00519 
00520   UInt_t index = this->AddNewAgg(fGap,aggNo);
00521   fVRecs[index].SetAggregateNo(aggNo);
00522   return index;
00523 
00524 }
00525 
00526 //.....................................................................
00527 
00528 const TDbiValidityRec&
00529               TDbiValidityRecBuilder::GetValidityRec(Int_t rowNo) const {
00530 //
00531 //
00532 //  Purpose: Return validity record for supplied row number.
00533 
00534   return (rowNo < 0 || rowNo >= (int) fVRecs.size()) ? fGap : fVRecs[rowNo];
00535 }
00536 
00537 //.....................................................................
00538 
00539 const TDbiValidityRec&
00540               TDbiValidityRecBuilder::GetValidityRecFromSeqNo(UInt_t SeqNo) const {
00541 //
00542 //
00543 //  Purpose: Return validity record for supplied SeqNo.
00544 
00545   std::vector<TDbiValidityRec>::const_iterator itr = fVRecs.begin();
00546   std::vector<TDbiValidityRec>::const_iterator end = fVRecs.end();
00547 
00548   for (; itr != end; ++itr) if ( itr->GetSeqNo() == SeqNo ) return *itr;
00549   return fGap;
00550 }
00551 
00552 //.....................................................................
00553 
00554 Int_t TDbiValidityRecBuilder::IndexOfAggno(Int_t aggNo) const {
00555 //
00556 //
00557 //  Purpose:   Get index of AggNo or -1 if missing.
00558 
00559   std::map<Int_t,UInt_t>::const_iterator itr = fAggNoToIndex.find(aggNo);
00560   if ( itr == fAggNoToIndex.end() ) return -1;
00561   return itr->second;
00562 
00563 }
00564 
00565 //.....................................................................
00566 
00567 void TDbiValidityRecBuilder::MakeGapRec(const TVldContext& vc,
00568                                        const string& tableName,
00569                                        Bool_t findFullTimeWindow) {
00570 //
00571 //
00572 //  Purpose:  Construct Gap Record
00573 //
00574 //  Arguments:
00575 //    vc           in    The Validity Context for the query.
00576 //    tableName    in    The name of the table being queried.
00577 //    findFullTimeWindow
00578 //                 in    Attempt to find full validity of query
00579 //                        i.e. beyond TDbi::GetTimeGate
00580 //
00581 //  Return:        None.
00582 //
00583 //  Contact:   N. West
00584 //
00585 //  Specification:-
00586 //  =============
00587 //
00588 //  o Create the data member gap record fGap centered on the current
00589 //    query time.
00590 
00591 //  Program Notes:-
00592 //  =============
00593 
00594 //  None.
00595 
00596   Int_t timeGate = TDbi::GetTimeGate(tableName);
00597   time_t contextSec = vc.GetTimeStamp().GetSec() - timeGate;
00598   TVldTimeStamp startGate(contextSec,0);
00599   contextSec += 2*timeGate;
00600   TVldTimeStamp endGate(contextSec,0);
00601   if ( findFullTimeWindow ) {
00602     startGate = TVldTimeStamp(0,0);
00603     endGate   = TVldTimeStamp(0x7FFFFFFF,0);
00604   }
00605   TVldRange gapVR(vc.GetDetector(), vc.GetSimFlag(), startGate, endGate, "Gap");
00606   fGap =  TDbiValidityRec(gapVR, fTask, -2, 0, 0, kTRUE,TVldTimeStamp(0));
00607 }
00608 
00609 

Generated on 11 Aug 2013 for SKDatabase by  doxygen 1.6.1