TDbiCache.cxx

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

Generated on 11 Aug 2013 for SKDatabase by  doxygen 1.6.1