00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012 #include "Plex/PlexLoanPool.h"
00013
00014 #include <vector>
00015
00016 #include "TSystem.h"
00017 #include "TROOT.h"
00018 #include "TClass.h"
00019 #include "TFile.h"
00020
00021 class PlexusReroot;
00022
00023 #include "Plex/Plexus.h"
00024 #include "Plex/PlexHandle.h"
00025 #include "Validity/VldContext.h"
00026 #include "Validity/VldRange.h"
00027 #include "Util/UtilString.h"
00028
00029 #include "MessageService/MsgService.h"
00030 CVSID("$Id: PlexLoanPool.cxx,v 1.30 2005/08/26 18:47:03 rhatcher Exp $");
00031
00032 #ifndef CSTDLIB
00033 #include <cstdlib>
00034 #define CSTDLIB
00035 #endif
00036
00037 #include <cassert>
00038
00039 ClassImp(PlexLoanPool)
00040
00041
00042
00043
00044 PlexLoanPool *PlexLoanPool::fgInstance = 0;
00045
00046 const Int_t dfltMaxUnused = 1;
00047
00048
00049 PlexLoanPool *PlexLoanPool::Instance()
00050 {
00051
00052 if (fgInstance == 0) {
00053 MSG("Plex",Msg::kSynopsis) << "PlexLoanPool instance creation" << endl;
00054 static PlexLoanPool::Cleaner c;
00055 c.ClassIsUsed();
00056
00057 fgInstance = new PlexLoanPool;
00058
00059
00060 Registry& r = fgInstance->GetConfig();
00061 r.SetName("PlexLoanPool Configuration");
00062 r.Merge(fgInstance->DefaultConfig());
00063 r.LockKeys();
00064 fgInstance->SetConfigFromEnvironment();
00065 fgInstance->Update();
00066
00067
00068
00069 if ( r.KeyExists("Cache") ) {
00070 const char* cache_location = "";
00071 if ( r.Get("Cache",cache_location) && strlen(cache_location) )
00072 PlexLoanPool::ReadFromFile(cache_location);
00073 }
00074 }
00075 return fgInstance;
00076 }
00077
00078
00079 void PlexLoanPool::Config()
00080 {
00081
00082
00083 MSG("Plex",Msg::kDebug) << "PlexLoanPool::Config " << endl;
00084
00085 Registry& r = GetConfig();
00086
00087
00088 int tmpi;
00089 if (r.Get("MaxUnref",tmpi)) fMaxSharedUnref = tmpi;
00090
00091 }
00092
00093
00094 const Registry& PlexLoanPool::DefaultConfig() const
00095 {
00096
00097
00098
00099 int itrue = 1;
00100
00101 static Registry r;
00102
00103 std::string name = this->GetName();
00104 name += ".config.default";
00105 r.SetName(name.c_str());
00106
00107 r.UnLockValues();
00108 r.Set("MaxUnref", dfltMaxUnused);
00109 r.Set("Cache", "");
00110 r.Set("CacheWrite", itrue);
00111 r.Set("PurgeDbiTableCache", itrue);
00112 r.Set("Paranoia", 0);
00113 r.LockValues();
00114
00115 return r;
00116
00117 }
00118
00119
00120 void PlexLoanPool::SetConfigFromEnvironment()
00121 {
00122
00123
00124
00125
00126 const char* strENV_PLEX = gSystem->Getenv("ENV_PLEX");
00127 if ( strENV_PLEX == 0 || strlen(strENV_PLEX) == 0 ) return;
00128
00129 MSG("Plex",Msg::kInfo)
00130 << "Configuring Plex from the environment variable ENV_PLEX:" << endl
00131 << " " << strENV_PLEX << endl;
00132
00133 std::vector<std::string> configRequests;
00134 UtilString::StringTok(configRequests, strENV_PLEX, ";");
00135
00136 for (unsigned entry = 0; entry < configRequests.size(); ++entry)
00137 this->Set(configRequests[entry].c_str());
00138 }
00139
00140
00141 void PlexLoanPool::ClearPool(Bool_t shared, Bool_t modifiable)
00142 {
00143 if (shared) fSharedPlexusList.Delete();
00144 if (modifiable) fPrivatePlexusList.Delete();
00145 }
00146
00147
00148 void PlexLoanPool::PurgeComponents(UInt_t purgeMask)
00149 {
00150
00151
00152
00153
00154 Plexus *plexus = 0;
00155
00156 TObjArrayIter iter_shared(&fSharedPlexusList);
00157 while (( plexus = dynamic_cast<Plexus*>(iter_shared.Next()) ))
00158 plexus->PurgeComponents(purgeMask);
00159
00160 TObjArrayIter iter_private(&fPrivatePlexusList);
00161 while (( plexus = dynamic_cast<Plexus*>(iter_private.Next()) ))
00162 plexus->PurgeComponents(purgeMask);
00163 }
00164
00165
00166 bool PlexLoanPool::DoesValidPlexExist(const VldContext& vldc, Bool_t shared)
00167 {
00168
00169
00170 Plexus *plex = GetExistingPlexus(vldc,shared);
00171 if (plex) return true;
00172 else return false;
00173 }
00174
00175
00176 bool PlexLoanPool::PurgeDbiTableCache() const
00177 {
00178
00179
00180
00181 Registry& r = fgInstance->GetConfig();
00182 int dopurge = true;
00183 r.Get("PurgeDbiTableCache",dopurge);
00184 return dopurge;
00185
00186 }
00187
00188
00189 PlexLoanPool::PlexLoanPool()
00190 : fMaxSharedUnref(dfltMaxUnused)
00191 {
00192
00193
00194 if (fgInstance && fgInstance != this) {
00195 MSG("Plex",Msg::kWarning)
00196 << "PlexLoanPool ctor() called but global already exists"
00197 << " -- memory leak (existing one will be lost)"
00198 << endl;
00199 }
00200 fgInstance = this;
00201
00202 MSG("Plex",Msg::kSynopsis) << "PlexLoanPool ctor" << endl;
00203
00204 fSharedPlexusList.SetOwner(true);
00205 fPrivatePlexusList.SetOwner(true);
00206 }
00207
00208
00209 PlexLoanPool::PlexLoanPool(const PlexLoanPool &plp)
00210 : TObject(plp), CfgConfigurable(plp)
00211 {
00212
00213 MSG("Plex",Msg::kFatal) <<
00214 "PlexLoanPool copy constructor called" << endl;
00215 assert(0);
00216 }
00217
00218
00219 PlexLoanPool::~PlexLoanPool()
00220 {
00221
00222
00223
00224 MSG("Plex",Msg::kSynopsis) << "PlexLoanPool shutdown" << endl;
00225
00226 Registry& r = GetConfig();
00227 if ( r.KeyExists("Cache") ) {
00228 const char* cache_location = "";
00229 if ( r.Get("Cache",cache_location) && strlen(cache_location) ) {
00230 int dowrite = true;
00231 if ( ! r.Get("CacheWrite",dowrite) ) {
00232 MSG("Plex",Msg::kInfo)
00233 << "PlexLoanPool not configured for 'CacheWrite', assume "
00234 << dowrite << "." << endl;
00235 }
00236 if (dowrite) {
00237 MSG("Plex",Msg::kInfo)
00238 << "PlexLoanPool writing file "
00239 << cache_location << " ..." << flush;
00240 PlexLoanPool::SaveToFile(cache_location);
00241 MSG("Plex",Msg::kInfo) << " done" << endl;
00242 }
00243 }
00244 }
00245
00246
00247 fSharedPlexusList.Delete();
00248 fPrivatePlexusList.Delete();
00249 }
00250
00251
00252 Plexus* PlexLoanPool::GetPlexus(const VldContext& vldc, Bool_t shared)
00253 {
00254
00255
00256 Plexus *plexus = GetExistingPlexus(vldc,shared);
00257 if (plexus) return plexus;
00258
00259
00260
00261 TObjArray* plexList = &fSharedPlexusList;
00262 if (!shared) plexList = &fPrivatePlexusList;
00263
00264
00265 Plexus *other_plex = 0;
00266 Int_t todelete = -fMaxSharedUnref;
00267 TObjArrayIter iter_cnt(plexList);
00268 while ( ( other_plex = (Plexus *)iter_cnt.Next() ) ) {
00269 if ( other_plex->CountRef() <= 0 ) todelete ++;
00270 }
00271
00272
00273 if (todelete > 0) {
00274 TObjArrayIter iter_rm(plexList);
00275 while ( ( other_plex = (Plexus *)iter_rm.Next() ) &&
00276 todelete > 0 ) {
00277 if (other_plex->CountRef() <= 0 ) {
00278 fSharedPlexusList.Remove(other_plex);
00279 delete other_plex;
00280 todelete--;
00281 }
00282 }
00283
00284 plexList->Compress();
00285 MSG("Plex",Msg::kVerbose)
00286 << "GetPlexus removed old unref'd plexii" << endl;
00287 }
00288
00289
00290 plexus = BuildPlexus(vldc);
00291 if ( !plexus ) {
00292 MSG("Plex",Msg::kFatal)
00293 << "PlexLoanPool failed to build for: " << endl;
00294 vldc.Print();
00295 assert(plexus);
00296 }
00297
00298
00299 MSG("Plex",Msg::kVerbose) <<
00300 "GetPlexus returned created new 'shared' Plexus " << endl;
00301 plexList->AddLast(plexus);
00302
00303 return plexus;
00304
00305 }
00306
00307
00308 Plexus* PlexLoanPool::GetExistingPlexus(const VldContext& vldc, Bool_t shared)
00309 {
00310
00311
00312 Plexus *plexus = 0;
00313
00314
00315 TObjArray* plexList = &fSharedPlexusList;
00316 if (!shared) plexList = &fPrivatePlexusList;
00317
00318
00319
00320 TObjArrayIter iter(plexList,kIterBackward);
00321
00322 while ( ( plexus = dynamic_cast<Plexus *>(iter.Next()) ) ) {
00323
00324 if ( plexus->IsCompatible(vldc) ) {
00325
00326 MSG("Plex",Msg::kVerbose) <<
00327 "GetPlexus returned found handle " << endl;
00328 return plexus;
00329 }
00330 }
00331 return 0;
00332 }
00333
00334
00335
00336 Plexus* PlexLoanPool::BuildPlexus(const VldContext& vldc)
00337 {
00338
00339
00340 Bool_t use_dbi = true;
00341
00342 switch (vldc.GetDetector()) {
00343 case Detector::kNear:
00344 break;
00345 case Detector::kFar:
00346 break;
00347 case Detector::kCalDet:
00348 break;
00349 default:
00350
00351 use_dbi = false;
00352 break;
00353 }
00354
00355 Plexus *plexus = 0;
00356
00357 if (use_dbi) {
00358 plexus = new Plexus(vldc);
00359 }
00360 else if (vldc.GetSimFlag() == SimFlag::kReroot) {
00361
00362
00363
00364
00365
00366
00367
00368 static bool first = true;
00369 if (first) {
00370 first = false;
00371 gROOT->LoadClass("PlexusReroot","libRerootExodus.so");
00372 }
00373 void *ptr = gROOT->GetClass("PlexusReroot",kTRUE)->New();
00374 if (!ptr) {
00375 MSG("Plex",Msg::kFatal)
00376 << "BuildPlexus failed to instantiate PlexusReroot "
00377 << vldc << endl;
00378 assert(0);
00379 }
00380
00381
00382
00383
00384
00385 plexus = (Plexus *)(ptr);
00386 }
00387 else {
00388
00389 TString detname = Detector::AsString(vldc.GetDetector());
00390 TString detNAME = detname;
00391 detNAME.ToUpper();
00392 MSG("Plex",Msg::kFatal)
00393 << "BuildPlexus " << endl << " vldc "<< vldc << endl
00394 << " no database info for the " << detname
00395 << " detector (or this VldContext) is available yet" << endl
00396 << " or NO_" << detNAME
00397 << "_PLEX_DATABASE needs to be switched off in GNUmakefile"
00398 << endl;
00399 exit(1);
00400 }
00401 return plexus;
00402 }
00403
00404
00405 void PlexLoanPool::Print(Option_t *option) const
00406 {
00407
00408
00409 Plexus *plexus;
00410
00411 MSG("Plex",Msg::kVerbose) << "Print" << endl;
00412
00413 GetConfig().Print();
00414
00415 cout << " --- Shared PlexLoanPool ---" << endl;
00416 TIter shared(&fSharedPlexusList);
00417 while ( ( plexus = (Plexus *)shared.Next() ) ) plexus->Print(option);
00418
00419 cout << " --- Private PlexLoanPool ---" << endl;
00420 TIter nonshared(&fPrivatePlexusList);
00421 while ( ( plexus = (Plexus *)nonshared.Next() ) ) plexus->Print(option);
00422
00423 cout << " --- End of PlexLoanPool ---" << endl;
00424 }
00425
00426
00427 void PlexLoanPool::SaveToFile(const char* filename, bool recreate)
00428 {
00429
00430
00431 PlexLoanPool* plp = PlexLoanPool::Instance();
00432
00433 const char* fmode = "RECREATE";
00434 if (!recreate) fmode = "UPDATE";
00435 TFile f(filename,fmode);
00436 plp->Write();
00437 f.Write();
00438 f.Close();
00439 }
00440
00441
00442 void PlexLoanPool::ReadFromFile(const char* filename)
00443 {
00444
00445
00446
00447
00448 if ( gSystem->AccessPathName(filename,kFileExists) ) {
00449
00450 MSG("Plex",Msg::kInfo)
00451 << "PlexLoanPool::ReadFromFile() no such file: " << filename << endl;
00452 return;
00453 }
00454
00455
00456 MSG("Plex",Msg::kInfo)
00457 << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl
00458 << "PlexLoanPool::ReadFromFile() used to build some plexii. " << endl
00459 << "This is really not a safe thing to do in that it bypasses the" << endl
00460 << "database and thus is not subject to rolling updates. Any plex" << endl
00461 << "will thus reflect the status at the time the file was written" << endl
00462 << "and may be outdated. Use at your own risk." << endl
00463 << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
00464
00465 PlexLoanPool* plpPrev = fgInstance;
00466 fgInstance = 0;
00467
00468 TFile f(filename);
00469 PlexLoanPool* plp = dynamic_cast<PlexLoanPool*>(f.Get("PlexLoanPool"));
00470
00471 if (!plp) {
00472
00473 MSG("Plex",Msg::kWarning)
00474 << "PlexLoanPool::ReadFromFile() found no pool in file:"
00475 << filename
00476 << endl;
00477
00478 fgInstance = plpPrev;
00479 }
00480 else if (plpPrev) {
00481
00482
00483 MSG("Plex",Msg::kInfo)
00484 << "PlexLoanPool::ReadFromFile() will now merge newly read data "
00485 << "into prior loan pool" << endl;
00486
00487 fgInstance = plpPrev;
00488
00489 TObjArray *from, *to;
00490 for (int pubpriv = 0; pubpriv <= 1; ++pubpriv) {
00491 if (pubpriv) {
00492 from = &plp->fSharedPlexusList;
00493 to = &fgInstance->fSharedPlexusList;
00494 }
00495 else {
00496 from = &plp->fPrivatePlexusList;
00497 to = &fgInstance->fPrivatePlexusList;
00498 }
00499 for (int indx = 0; indx <= from->GetLast(); ++indx) {
00500 TObject* plexus = from->RemoveAt(indx);
00501 if (plexus) to->Add(plexus);
00502 }
00503 }
00504
00505
00506 plp->GetConfig().RemoveKey("Cache");
00507 delete plp;
00508 }
00509
00510 }
00511
00512