00001
00002
00003 #include "Conventions/Detector.h"
00004 #include "Conventions/SimFlag.h"
00005 #include "DatabaseInterface/DbiBinaryFile.h"
00006 #include "DatabaseInterface/DbiCache.h"
00007 #include "DatabaseInterface/DbiConnectionMaintainer.h"
00008 #include "DatabaseInterface/DbiResultAgg.h"
00009 #include "DatabaseInterface/DbiResultNonAgg.h"
00010 #include "DatabaseInterface/DbiResultSet.h"
00011 #include "DatabaseInterface/DbiTableProxy.h"
00012 #include "DatabaseInterface/DbiTableRow.h"
00013 #include "DatabaseInterface/DbiTimerManager.h"
00014 #include "DatabaseInterface/DbiValidityRec.h"
00015 #include "DatabaseInterface/DbiValidityRecBuilder.h"
00016 #include "LeakChecker/Lea.h"
00017 #include "MessageService/MsgService.h"
00018
00019 ClassImp(DbiTableProxy)
00020
00021
00022
00023
00024 CVSID("$Id: DbiTableProxy.cxx,v 1.28 2006/08/08 10:51:32 west Exp $");
00025
00026
00027
00028
00029
00030
00031
00032
00033 DbiTableProxy::DbiTableProxy(DbiCascader* cascader,
00034 const string& tableName,
00035 const string& vldSuffix,
00036 const DbiTableRow* tableRow) :
00037 fCascader(cascader),
00038 fMetaData(tableName),
00039 fMetaValid(tableName+vldSuffix),
00040 fCanL2Cache(kFALSE),
00041 fCache(0),
00042 fDBProxy(*cascader,tableName,&fMetaData,&fMetaValid,this),
00043 fExists(0),
00044 fTableName(tableName),
00045 fTableRow(tableRow->CreateTableRow())
00046 {
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 LEA_CTOR
00073
00074 fCache = new DbiCache(*this,fTableName);
00075 this->RefreshMetaData();
00076 fExists = fDBProxy.TableExists();
00077 fCanL2Cache = tableRow->CanL2Cache();
00078 if ( fCanL2Cache )
00079 MSG("Dbi", Msg::kInfo) << "DbiTableProxy: Can L2 cache " << this->GetRowName() << endl;
00080 MSG("Dbi", Msg::kVerbose) << "Creating DbiTableProxy "
00081 << fTableName.c_str() << " at " << this
00082 << ( fExists ? " (table exists)"
00083 : " (table missing)" )
00084 << endl;
00085 }
00086
00087
00088
00089 DbiTableProxy::~DbiTableProxy() {
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 LEA_DTOR
00113
00114 MSG("Dbi", Msg::kVerbose) << "Destroying DbiTableProxy "
00115 << fTableName << " at " << this
00116 << endl;
00117 delete fCache;
00118 delete fTableRow;
00119
00120 }
00121
00122
00123 Bool_t DbiTableProxy::CanReadL2Cache() const {
00124
00125
00126 return fCanL2Cache && DbiBinaryFile::CanReadL2Cache();
00127
00128 }
00129 Bool_t DbiTableProxy::CanWriteL2Cache() const {
00130
00131
00132 return fCanL2Cache && DbiBinaryFile::CanWriteL2Cache();
00133
00134 }
00135
00136
00137
00138 const DbiResult* DbiTableProxy::Query(const VldContext& vc,
00139 const Dbi::Task& task,
00140 Bool_t findFullTimeWindow) {
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 if ( const DbiResult* result = fCache->Search(vc,task)
00169 ) return result;
00170
00171 DbiConnectionMaintainer cm(fCascader);
00172
00173
00174 UInt_t startGEL = DbiExceptionLog::GetGELog().Size()+1;
00175
00176
00177 DbiValidityRecBuilder builder(fDBProxy,vc,task,-1,findFullTimeWindow);
00178
00179
00180
00181 if ( builder.NonAggregated() ) {
00182
00183 DbiValidityRec effVRec = builder.GetValidityRec(0);
00184
00185 DbiResult* result = const_cast<DbiResult*>(Query(effVRec));
00186
00187 result->CaptureExceptionLog(startGEL);
00188 return result;
00189 }
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 if ( this->CanReadL2Cache() ) {
00201 UInt_t numPresent = 0;
00202 UInt_t numRequired = 0;
00203 Int_t maxRow = builder.GetNumValidityRec() - 1;
00204 for ( Int_t rowNo = 1; rowNo <= maxRow; ++rowNo ) {
00205 const DbiValidityRec& vrec = builder.GetValidityRec(rowNo);
00206 if ( fCache->Search(vrec) ) ++numPresent;
00207 else if ( ! vrec.IsGap() ) ++numRequired;
00208 }
00209 if ( numRequired < numPresent ) MSG("Dbi",Msg::kInfo)
00210 << "Skipping search of L2 cache; already have "
00211 << numPresent << " aggregates, and only require a further "
00212 << numRequired << endl;
00213 else this->RestoreFromL2Cache(builder);
00214 }
00215
00216 DbiResult* result = new DbiResultAgg(fTableName,
00217 fTableRow,
00218 fCache,
00219 &builder,
00220 &fDBProxy);
00221
00222 result->CaptureExceptionLog(startGEL);
00223
00224 fCache->Adopt(result);
00225 this->SaveToL2Cache(builder.GetL2CacheName(),*result);
00226 return result;
00227
00228 }
00229
00230
00231 const DbiResult* DbiTableProxy::Query(const string& context,
00232 const Dbi::Task& task,
00233 const string& data,
00234 const string&fillOpts) {
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 std::ostringstream os;
00264 os << context;
00265 if ( task != Dbi::kAnyTask
00266 ) os << " and Task = " << task;
00267 os << ';' << data << ';' << fillOpts;
00268 string sqlQualifiers = os.str();
00269
00270 MSG("Dbi", Msg::kVerbose)
00271 << "Extended query: sqlQualifiers: " << sqlQualifiers << endl;
00272
00273
00274
00275 if ( const DbiResult* result = fCache->Search(sqlQualifiers)
00276 ) return result;
00277
00278 DbiConnectionMaintainer cm(fCascader);
00279
00280
00281 UInt_t startGEL = DbiExceptionLog::GetGELog().Size()+1;
00282
00283
00284 DbiValidityRecBuilder builder(fDBProxy,context,task);
00285
00286
00287
00288
00289 DbiResult* result = new DbiResultAgg(fTableName,
00290 fTableRow,
00291 fCache,
00292 &builder,
00293 &fDBProxy,
00294 sqlQualifiers);
00295
00296 result->CaptureExceptionLog(startGEL);
00297
00298 fCache->Adopt(result);
00299 return result;
00300
00301 }
00302
00303
00304 const DbiResult* DbiTableProxy::Query(UInt_t seqNo,UInt_t dbNo) {
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 DbiConnectionMaintainer cm(fCascader);
00316
00317
00318 UInt_t startGEL = DbiExceptionLog::GetGELog().Size()+1;
00319
00320
00321 DbiResultSet* rs = fDBProxy.QueryValidity(seqNo,dbNo);
00322 DbiValidityRec tr;
00323 DbiResultNonAgg result(rs,&tr,0,kFALSE);
00324 delete rs;
00325
00326
00327 if ( result.GetNumRows() == 0 ) {
00328 DbiResultNonAgg* empty = new DbiResultNonAgg();
00329
00330 empty->CaptureExceptionLog(startGEL);
00331 fCache->Adopt(empty);
00332 return empty;
00333 }
00334
00335
00336
00337
00338
00339 const DbiValidityRec* vrec
00340 = dynamic_cast<const DbiValidityRec*>(result.GetTableRow(0));
00341
00342 DbiResult* res = const_cast<DbiResult*>(Query(*vrec,kFALSE));
00343
00344 res->CaptureExceptionLog(startGEL);
00345 return res;
00346
00347 }
00348
00349
00350 const DbiResult* DbiTableProxy::Query(const DbiValidityRec& vrec,
00351 Bool_t canReuse ) {
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 DbiConnectionMaintainer cm(fCascader);
00374
00375
00376 UInt_t startGEL = DbiExceptionLog::GetGELog().Size()+1;
00377
00378 if ( canReuse ) {
00379 DbiValidityRecBuilder builder(vrec,this->GetTableName());
00380 if ( this->RestoreFromL2Cache(builder) ) {
00381 const DbiResult* res = fCache->Search(vrec);
00382 if ( res ) return res;
00383 }
00384 }
00385
00386 unsigned int seqNo = vrec.GetSeqNo();
00387 DbiResult* result = 0;
00388
00389
00390 if ( ! seqNo ) {
00391 result = new DbiResultNonAgg(0,0,&vrec);
00392 }
00393
00394
00395
00396
00397 else if (vrec.GetTableProxy()->GetTableName() != GetTableName() ) {
00398 MAXMSG("Dbi",Msg::kError,20)
00399 << "Unable to satisfy DbiValidityRec keyed query:" << endl
00400 << vrec
00401 << " was filled by " << vrec.GetTableProxy()->GetTableName()
00402 << " not by this DbiTableProxy ("
00403 << GetTableName() << ")" << endl;
00404 result = new DbiResultNonAgg(0,0,&vrec);
00405 }
00406
00407 else {
00408
00409
00410
00411
00412 DbiResultSet* rs = fDBProxy.QuerySeqNo(seqNo,vrec.GetDbNo());
00413 result = new DbiResultNonAgg(rs,fTableRow,&vrec);
00414 delete rs;
00415 }
00416
00417
00418 result->CaptureExceptionLog(startGEL);
00419
00420
00421
00422 fCache->Adopt(result);
00423 if ( canReuse ) this->SaveToL2Cache(vrec.GetL2CacheName(),*result);
00424 else result->SetCanReuse(kFALSE);
00425
00426 return result;
00427
00428 }
00429
00430
00431
00432 void DbiTableProxy::RefreshMetaData() {
00433
00434
00435
00436
00437
00438 fDBProxy.StoreMetaData(fMetaData);
00439 fDBProxy.StoreMetaData(fMetaValid);
00440
00441 }
00442
00443
00444 VldTimeStamp DbiTableProxy::QueryOverlayCreationDate(const DbiValidityRec& vrec,
00445 UInt_t dbNo)
00446 {
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 const VldRange& vr(vrec.GetVldRange());
00497 VldContext vc((Detector::Detector_t) vr.GetDetectorMask(),
00498 (SimFlag::SimFlag_t) vr.GetSimMask(),
00499 vr.GetTimeStart());
00500
00501 DbiConnectionMaintainer cm(fCascader);
00502
00503
00504
00505 DbiValidityRecBuilder builder(fDBProxy,vc,vrec.GetTask(),dbNo);
00506
00507
00508 const DbiValidityRec& vrecOvlay(builder.GetValidityRecFromAggNo(vrec.GetAggregateNo()));
00509
00510
00511
00512 VldTimeStamp ovlayTS(vr.GetTimeStart());
00513 if ( ! vrecOvlay.IsGap() ) {
00514 time_t overlaySecs = vrecOvlay.GetCreationDate().GetSec();
00515 ovlayTS = VldTimeStamp(overlaySecs + 60,0);
00516 }
00517
00518 MSG("Dbi",Msg::kDebug) << "Looking for overlay creation date for: "
00519 << vrec << "found it would overlap: "
00520 << vrecOvlay << " so overlay creation date set to "
00521 << ovlayTS.AsString("s") << endl;
00522 return ovlayTS;
00523
00524 }
00525
00526
00527 Bool_t DbiTableProxy::RestoreFromL2Cache(const DbiValidityRecBuilder& builder) {
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 const string name(builder.GetL2CacheName());
00539 MSG("Dbi",Msg::kDebug) << "Request to restore query result " << name
00540 << endl;
00541 if ( ! this->CanReadL2Cache() ) return kFALSE;
00542 string cacheFileName;
00543 if ( name != ""
00544 ) cacheFileName = this->GetTableName() + "_"
00545 + this->GetRowName() + "_"
00546 + name + ".dbi_cache";
00547 DbiBinaryFile bf(cacheFileName.c_str());
00548 if ( ! bf.IsOK() ) {
00549 MSG("Dbi",Msg::kDebug) << "Caching disabled or cannot open "
00550 << bf.GetFileName() << endl;
00551 return kFALSE;
00552 }
00553
00554 static bool warnOnce = true;
00555 if ( warnOnce ) {
00556 MSG("Dbi",Msg::kWarning) << "\n\n\n"
00557 << " WARNING: Reading from the Level 2 cache has been activated.\n"
00558 << " ******* This should only be used for development and never for production !!!\n\n\n";
00559 warnOnce = false;
00560 }
00561
00562 MSG("Dbi",Msg::kInfo) << "Restoring query result from " << bf.GetFileName() << endl;
00563 DbiTimerManager::gTimerManager.RecMainQuery();
00564
00565 DbiResult* result = 0;
00566 unsigned numRowsRest = 0;
00567 unsigned numRowsIgn = 0;
00568 UInt_t numNonAgg = 0;
00569 bf >> numNonAgg;
00570
00571 while ( numNonAgg-- ) {
00572 if ( ! bf.IsOK() ) break;
00573 if ( ! result ) result = new DbiResultNonAgg;
00574 bf >> *result;
00575
00576
00577
00578
00579 const DbiValidityRec& vrec = result->GetValidityRec();
00580 UInt_t seqNo = vrec.GetSeqNo();
00581 MSG("Dbi",Msg::kDebug) << "Fix up L2 cache DbiValidityRec, by replacing: " << vrec
00582 << " with: " << builder.GetValidityRecFromSeqNo(seqNo) << endl;
00583
00584 (const_cast<DbiValidityRec&>(vrec)) = builder.GetValidityRecFromSeqNo(seqNo);
00585
00586
00587 if ( ! fCache->Search(vrec) ) {
00588 numRowsRest += result->GetNumRows();
00589 fCache->Adopt(result);
00590 result = 0;
00591 }
00592 else numRowsIgn += result->GetNumRows();
00593 }
00594 MSG("Dbi",Msg::kInfo) << " a total of " << numRowsRest << " were restored ("
00595 << numRowsIgn << " ignored - already in memory)" << endl;
00596
00597 delete result;
00598 result = 0;
00599
00600 return numRowsRest > 0;
00601
00602 }
00603
00604
00605 Bool_t DbiTableProxy::SaveToL2Cache(const string& name, DbiResult& res) {
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 MSG("Dbi",Msg::kDebug) << "Request to save query result as " << name
00616 << " data from DB? " << res.ResultsFromDb()
00617 << " can be saved? " << res.CanSave() << endl;
00618 if ( ! this->CanWriteL2Cache() || ! res.ResultsFromDb() || ! res.CanSave() ) return kFALSE;
00619
00620 string cacheFileName;
00621 if ( name != ""
00622 ) cacheFileName = this->GetTableName() + "_"
00623 + this->GetRowName() + "_"
00624 + name + ".dbi_cache";
00625 DbiBinaryFile bf(cacheFileName.c_str(),kFALSE);
00626 if ( bf.IsOK() ) {
00627 MSG("Dbi",Msg::kInfo) << "Saving query result (" << res.GetNumRows()
00628 << " rows) to " << bf.GetFileName() << endl;
00629 DbiTimerManager::gTimerManager.RecMainQuery();
00630
00631
00632
00633 if ( dynamic_cast<DbiResultNonAgg*>(&res) ) {
00634 UInt_t numNonAgg = 1;
00635 bf << numNonAgg;
00636 }
00637 bf << res;
00638 return kTRUE;
00639 }
00640 MSG("Dbi",Msg::kDebug) << "Caching disabled or cannot open "
00641 << bf.GetFileName() << endl;
00642 return kFALSE;
00643
00644 }
00645
00646
00647 void DbiTableProxy::SetSqlCondition(const string& sql) {
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 fDBProxy.SetSqlCondition(sql);
00670
00671 }