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

DbiCache.cxx

Go to the documentation of this file.
00001 // $Id: DbiCache.cxx,v 1.25 2006/08/08 10:51:32 west Exp $
00002 
00003 #include "DatabaseInterface/DbiCache.h"
00004 #include "DatabaseInterface/DbiResult.h"
00005 #include "DatabaseInterface/DbiResultKey.h"
00006 #include "DatabaseInterface/DbiResultNonAgg.h"
00007 #include "DatabaseInterface/DbiSimFlagAssociation.h"
00008 #include "DatabaseInterface/DbiValidityRec.h"
00009 #include "LeakChecker/Lea.h"
00010 #include "MessageService/MsgFormat.h"
00011 #include "MessageService/MsgService.h"
00012 #include "Validity/VldContext.h"
00013 
00014 ClassImp(DbiCache)
00015 
00016 // Typedefs
00017 
00018   typedef DbiCache::ResultList_t ResultList_t;
00019   typedef map<Int_t,ResultList_t>::const_iterator ConstCacheItr_t;
00020   typedef map<Int_t,ResultList_t>::iterator CacheItr_t;
00021   typedef ResultList_t::const_iterator ConstSubCacheItr_t;
00022   typedef ResultList_t::iterator SubCacheItr_t;
00023 
00024 
00025 //   Definition of static data members
00026 //   *********************************
00027 
00028 CVSID("$Id: DbiCache.cxx,v 1.25 2006/08/08 10:51:32 west Exp $");
00029 
00030 //    Definition of all member functions (static or otherwise)
00031 //    *******************************************************
00032 //
00033 //    -  ordered: ctors, dtor, operators then in alphabetical order.
00034 
00035 
00036 
00037 //.....................................................................
00038 
00039 DbiCache::DbiCache(DbiTableProxy& qp,const string& tableName) :
00040 fTableProxy(qp),
00041 fTableName(tableName),
00042 fCurSize(0),
00043 fMaxSize(0),
00044 fNumAdopted(0),
00045 fNumReused(0)
00046 {
00047 //
00048 //
00049 //  Purpose:  Constructor
00050 //
00051 //  Arguments:   
00052 //             in  qp         Owning DbiTableProxy.
00053 //             in  tableName  Name of associated table
00054 //
00055 //  Return:    n/a
00056 //
00057 //  Contact:   N. West
00058 //
00059 //  Specification:-
00060 //  =============
00061 //
00062 //  o Create empty cache.
00063 
00064 
00065 //  Program Notes:-
00066 //  =============
00067 
00068 //  None.
00069 
00070   LEA_CTOR    //Leak Checker
00071 
00072   MSG("Dbi", Msg::kVerbose) << "Creating DbiCache" << endl;
00073 
00074 }
00075 
00076 //.....................................................................
00077 
00078 DbiCache::~DbiCache() {
00079 //
00080 //
00081 //  Purpose: Destructor
00082 //
00083 //  Arguments: 
00084 //    None.
00085 //
00086 //  Return:    n/a
00087 //
00088 //  Contact:   N. West
00089 //
00090 //  Specification:-
00091 //  =============
00092 //
00093 //  o  Destroy cache and all owned DbiResults.
00094 
00095 
00096 //  Program Notes:-
00097 //  =============
00098 
00099 //  None.
00100 
00101   LEA_DTOR    //Leak Checker
00102 
00103   MSG("Dbi", Msg::kVerbose) << "Destroying DbiCache" << endl;
00104 
00105   // Purge the AggNo == -1 cache before deleting.  For extended
00106   // context queries it can have DbiResultAggs that are clients of 
00107   // DbiResultNonAggs in the same cache, so purging will remove clientless
00108   // DbiResultAggs which should in turn make their DbiResultNonAggs 
00109   // clientless.
00110   if ( this->GetSubCache(-1) ) this->Purge(fCache[-1]);
00111 
00112   for ( CacheItr_t itr = fCache.begin(); itr != fCache.end(); ++itr) {
00113     ResultList_t& subCache = itr->second;
00114     for ( SubCacheItr_t sitr = subCache.begin();
00115           sitr != subCache.end();
00116           ++sitr) delete *sitr;
00117   }
00118 
00119 }
00120 
00121 //.....................................................................
00122 
00123 void DbiCache::Adopt(DbiResult* res,bool registerKey) {
00124 //
00125 //
00126 //  Purpose:  Adopt and own a DbiResult
00127 //
00128 //  Arguments: 
00129 //    res          in    The DbiResiult to be adopted.
00130 //    registerKey  in    If true, register key with DbiRecord.
00131 //
00132 //  Return:  None.
00133 //
00134 //  Contact:   N. West
00135 //
00136 //  Specification:-
00137 //  =============
00138 //
00139 //  o Create new sub-cache for aggregate if necessary.
00140 //
00141 //  o Purge sub-cache of unwanted data and adopt new result.
00142 
00143 //  Program Notes:-
00144 //  =============
00145 
00146 //  New entries are added to the end of the sub-cache unwanted entries
00147 //  are always removed from the beginning so sub-cache is a FIFO.
00148 
00149   if ( ! res ) return;
00150   int aggNo = res->GetValidityRec().GetAggregateNo();
00151 
00152 //  Prime sub-cache if necessary.
00153   if ( ! this->GetSubCache(aggNo) ) {
00154     ResultList_t emptyList;
00155     fCache[aggNo] = emptyList;
00156   }
00157 
00158 //  Purge expired entries and add new result to cache.
00159   ResultList_t& subCache = fCache[aggNo];
00160   Purge(subCache, res);
00161   subCache.push_back(res);
00162   ++fCurSize;
00163   ++fNumAdopted;
00164   MSG("Dbi",Msg::kDebug) << "Adopting result for " << res->TableName()
00165                          << "  " <<   res->GetValidityRecGlobal() 
00166                          << "\nCache size now " << fCurSize << endl;
00167   if ( fCurSize > fMaxSize ) fMaxSize = fCurSize;
00168   // If required register key with DbiRecord
00169   if ( registerKey ) {
00170     res->RegisterKey();
00171     MSG("Dbi",Msg::kInfo) << "Caching new results: ResultKey: " <<  *res->GetKey();
00172   }
00173 }
00174 
00175 //.....................................................................
00176 
00177 const ResultList_t* DbiCache::GetSubCache(Int_t aggNo) const {
00178 //
00179 //
00180 //  Purpose:  Return sub-cache for aggregate or 0 if none..
00181 
00182   ConstCacheItr_t itr = fCache.find(aggNo);
00183   return ( itr == fCache.end() ) ? 0 : &itr->second;
00184 
00185 }
00186 
00187 //.....................................................................
00188 
00189 void DbiCache::Purge() {
00190 //
00191 //
00192 //  Purpose: Purge all sub-caches. 
00193 //
00194 //  Arguments:  None.
00195 //
00196 //  Return:   None. 
00197 //
00198 //  Contact:   N. West
00199 //
00200 //  Specification:-
00201 //  =============
00202 //
00203 //  o Purge all sub_caches.
00204 
00205 //  Program Notes:-
00206 //  =============
00207 
00208 //  The first sub-cached to be purged must be sub-cache -1 as
00209 //  its members may be aggregated and consequently will be
00210 //  connected to members in other caches.
00211 
00212 
00213 
00214   for ( CacheItr_t itr = fCache.begin(); itr != fCache.end(); ++itr
00215       ) Purge(itr->second);
00216 
00217 }
00218 //.....................................................................
00219 
00220 void DbiCache::Purge(ResultList_t& subCache, const DbiResult* res) {
00221 //
00222 //
00223 //  Purpose: Purge surplus sub-cache memebers. 
00224 //
00225 //  Arguments:
00226 //    subCache   in/out  The sub-cache to be purged
00227 //    res        in      Optional DbiResult (default =0)
00228 //
00229 //  Return:   None. 
00230 //
00231 //  Contact:   N. West
00232 //
00233 //  Specification:-
00234 //  =============
00235 //
00236 //  o Purge surplus sub-cache members i.e. those without clients.
00237 //
00238 //  o If a DbiResult is supplied, only purge entries that have
00239 //    expired relative to it or are stale.
00240 
00241 //  Program Notes:-
00242 //  =============
00243 
00244 //  Passing a DbiResult allows the sub-cache to hold entries
00245 //  for different detector types, simulation masks and tasks.
00246 
00247     for ( SubCacheItr_t itr = subCache.begin(); itr != subCache.end(); ) {
00248     DbiResult* pRes = *itr;
00249 
00250      if (      pRes->GetNumClients() == 0 
00251           && (    ! res 
00252                || pRes->CanDelete(res)  ) ) {
00253 
00254       MSG("Dbi",Msg::kDebug) << "Purging " << pRes->GetValidityRec()
00255                              << " from " << pRes->TableName() 
00256                              << " cache. Cache size now " 
00257                              << fCurSize-1 << endl;
00258       delete pRes;
00259 //    Erasing increments iterator.
00260       itr = subCache.erase(itr);
00261       --fCurSize;
00262 
00263     }
00264     else {
00265       ++itr;
00266     }
00267   }
00268 
00269 }
00270 //.....................................................................
00271 
00272 const DbiResult* DbiCache::Search(const DbiValidityRec& vrec,
00273                                   const string& sqlQualifiers) const {
00274 //
00275 //
00276 //  Purpose:  Search sub-cache for DbiResult set matching a DbiValidityRec. 
00277 //            with an optional sqlQualifiers string.
00278 //  Return:   Pointer to matching DbiResult, or = 0 if none. 
00279 
00280 
00281   Int_t aggNo = vrec.GetAggregateNo();
00282 
00283   MSG("Dbi",Msg::kSynopsis) << "Secondary cache search of table " << fTableName
00284                          << " for  " << vrec
00285                             << (sqlQualifiers != "" ? sqlQualifiers : "" ) << endl;
00286   const ResultList_t* subCache = this->GetSubCache(aggNo);
00287   if ( ! subCache ) {
00288     MSG("Dbi",Msg::kSynopsis) << "Secondary cache search failed." << endl;
00289     return 0;
00290   }
00291 
00292   ConstSubCacheItr_t itrEnd = subCache->end();
00293   for ( ConstSubCacheItr_t itr = subCache->begin();
00294         itr != itrEnd;
00295         ++itr) {
00296     DbiResult* res = *itr;
00297     if ( res->Satisfies(vrec,sqlQualifiers) ) {
00298       fNumReused += res->GetNumAggregates();
00299       MSG("Dbi",Msg::kSynopsis) << "Secondary cache search succeeded.  Result set no. of rows: " 
00300                                 << res->GetNumRows() << endl;
00301       return res;
00302     }
00303   }
00304 
00305   MSG("Dbi",Msg::kSynopsis) << "Secondary cache search failed." << endl;
00306   return 0;
00307 }
00308 
00309 //.....................................................................
00310 
00311 const DbiResult* DbiCache::Search(const VldContext& vc,
00312                                   const Dbi::Task& task ) const {
00313 //
00314 //
00315 //  Purpose:  Search primary cache for DbiResult set matching a new query. 
00316 //
00317 //  Arguments: 
00318 //    vc           in    Context of new query
00319 //    task         in    Task of new query
00320 //
00321 //  Return:   Pointer to matching DbiResult, or = 0 if none. 
00322 
00323   MSG("Dbi",Msg::kSynopsis) << "Primary cache search of table " << fTableName
00324                          << " for  " << vc
00325                          << " with task " << task << endl;
00326   const ResultList_t* subCache = this->GetSubCache(-1);
00327   if ( ! subCache ) {
00328     MSG("Dbi",Msg::kSynopsis) << "Primary cache search failed - sub-cache -1 is empty" << endl;
00329     return 0;
00330   }
00331 
00332   // Loop over all possible SimFlag associations.
00333 
00334   Detector::Detector_t     det(vc.GetDetector());
00335   SimFlag::SimFlag_t       sim(vc.GetSimFlag());
00336   VldTimeStamp              ts(vc.GetTimeStamp());
00337 
00338   DbiSimFlagAssociation::SimList_t simList 
00339                   = DbiSimFlagAssociation::Instance().Get(sim);
00340 
00341   DbiSimFlagAssociation::SimList_t::iterator listItr    = simList.begin();
00342   DbiSimFlagAssociation::SimList_t::iterator listItrEnd = simList.end();
00343   while ( listItr !=  listItrEnd ) {
00344 
00345     SimFlag::SimFlag_t simTry = *listItr;
00346     VldContext vcTry(det,simTry,ts);
00347 
00348     MSG("Dbi",Msg::kDebug) << "  Searching cache with SimFlag: "
00349                            << SimFlag::AsString(simTry) << endl;
00350     for ( ConstSubCacheItr_t itr = subCache->begin();
00351           itr != subCache->end();
00352           ++itr) {
00353       DbiResult* res = *itr;
00354       if ( res->Satisfies(vcTry,task) ) {
00355         fNumReused += res->GetNumAggregates();
00356         MSG("Dbi",Msg::kSynopsis) << "Primary cache search succeeded. Result set no. of rows: " 
00357                                   << res->GetNumRows() << endl; 
00358         return res;
00359       }
00360     }
00361 
00362   MSG("Dbi",Msg::kSynopsis) << "Primary cache search failed." << endl;
00363   ++listItr;
00364   }
00365 
00366   return 0;
00367 }
00368 //.....................................................................
00369 
00370 const DbiResult* DbiCache::Search(const string& sqlQualifiers) const {
00371 //
00372 //
00373 //  Purpose:  Search primary cache for DbiResult set matching a new query. 
00374 //
00375 //  Arguments: 
00376 //    sqlQualifiers  in  The SQL qualifiers (context-sql;data-sql;fill-options)
00377 //
00378 //  Return:   Pointer to matching DbiResult, or = 0 if none. 
00379 
00380   MSG("Dbi",Msg::kSynopsis) << "Primary cache search of table " << fTableName
00381                          << " for  SQL " << sqlQualifiers << endl;
00382   const ResultList_t* subCache = this->GetSubCache(-1);
00383   if ( ! subCache ) {
00384     MSG("Dbi",Msg::kSynopsis) << "Primary cache search failed" << endl;
00385     return 0;
00386   }
00387   for ( ConstSubCacheItr_t itr = subCache->begin();
00388         itr != subCache->end();
00389         ++itr) {
00390     DbiResult* res = *itr;
00391     if ( res->Satisfies(sqlQualifiers) ) {
00392       fNumReused += res->GetNumAggregates();
00393       MSG("Dbi",Msg::kSynopsis) << "Primary cache search succeeded Result set no. of rows: " 
00394                                 << res->GetNumRows() << endl;
00395       return res;
00396     }
00397   }
00398   MSG("Dbi",Msg::kSynopsis) << "Primary cache search failed" << endl;
00399   return 0;
00400 }
00401 
00402 //.....................................................................
00403 
00404 void DbiCache::SetStale() {
00405 //
00406 //
00407 //  Purpose: Set all entries in the cache as stale i.e. don't reuse. 
00408 //
00409 //  Arguments: None
00410 //
00411 //  Return:    n/a
00412 //
00413 //  Contact:   N. West
00414 //
00415 //  Specification:-
00416 //  =============
00417 //
00418 //  o Set all entries in the cache as stale i.e. don't reuse. 
00419 
00420 //  Program Notes:-
00421 //  =============
00422 
00423 //  This member function can be used to effectively clear the cache.
00424 //  As existing DbiResult objects currently in the cache may currently
00425 //  have clients, its not possible simply to delete them, so instead
00426 //  this function marks them as stale so they will not be reused and
00427 //  will eventually be dropped once all their clients have disconnected.
00428 
00429 
00430   for ( CacheItr_t cacheItr = fCache.begin(); 
00431         cacheItr != fCache.end(); 
00432         ++cacheItr
00433         ) {
00434     ResultList_t& subcache = cacheItr->second;
00435 
00436     for ( SubCacheItr_t subcacheItr = subcache.begin(); 
00437           subcacheItr != subcache.end();
00438           ++subcacheItr ) (*subcacheItr)->SetCanReuse(kFALSE);
00439   }
00440 
00441 }
00442 
00443 //.....................................................................
00444 
00445 MsgStream& DbiCache::ShowStatistics(MsgStream& msg) const {
00446 //
00447 //
00448 //  Purpose: Display statistics for cache on supplied MsgStream.  
00449 //
00450 //  Arguments: 
00451 //    msg          in    MsgStream to output on.
00452 //
00453 //  Return: Updated MsgStream. 
00454 //
00455 //  Contact:   N. West
00456 //
00457 //  Specification:-
00458 //  =============
00459 //
00460 //  o Output : Current Size, Max size, Adopted and Resused as
00461 //             4 10 character wide fields.
00462 
00463 //  Program Notes:-
00464 //  =============
00465 
00466 //  None.
00467 
00468   MsgFormat ifmt("%10i");
00469 
00470   msg << ifmt(fCurSize) << ifmt(fMaxSize) 
00471       << ifmt(fNumAdopted) << ifmt(fNumReused);
00472   return msg;
00473 
00474 }
00475 
00476 /*    Template for New Member Function
00477 
00478 //.....................................................................
00479 
00480 DbiCache:: {
00481 //
00482 //
00483 //  Purpose:  
00484 //
00485 //  Arguments: 
00486 //    xxxxxxxxx    in    yyyyyy
00487 //
00488 //  Return:    
00489 //
00490 //  Contact:   N. West
00491 //
00492 //  Specification:-
00493 //  =============
00494 //
00495 //  o 
00496 
00497 //  Program Notes:-
00498 //  =============
00499 
00500 //  None.
00501 
00502 
00503 }
00504 
00505 */
00506 

Generated on Mon Feb 15 11:06:34 2010 for loon by  doxygen 1.3.9.1