00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00014 #include "TROOT.h"
00015 #include "TFile.h"
00016 #include "TTree.h"
00017 #include "TClass.h"
00018 #include <iostream>
00019 using std::endl;
00020
00021 #include "Persistency/PerOutputStream.h"
00022 #include "Persistency/PerFile.h"
00023 #include "Persistency/PerFileManager.h"
00024 #include "MessageService/MsgService.h"
00025 #include "Record/RecMinos.h"
00026 #include "Record/RecRecord.h"
00027 #include "Validity/VldContext.h"
00028
00029 std::ostream& operator<<(std::ostream& os, const PerOutputStream& pos) {
00030 return pos.Print(os);
00031 }
00032
00033 ClassImp(PerOutputStream)
00034
00035
00036
00037
00038 CVSID("$Id: PerOutputStream.cxx,v 1.41 2007/01/15 20:57:28 rhatcher Exp $");
00039
00040
00041
00042
00043
00044 void PerOutputStream::AutoSaveByTime(UInt_t currentVldTime) {
00045
00046
00047
00048
00049
00050
00051 if ( !IsOpen() || fEntry == -1 ) return;
00052
00053 TDirectory* savedir = gDirectory;
00054
00055 if ( IsFileChange() ) ChangeFile();
00056
00057 bool isAutoSave = false;
00058
00059 if (!fLastTimeSaved) fLastTimeSaved = currentVldTime;
00060
00061 bool isAutoSaveTime
00062 = (fAutoSaveTime > 0 && (currentVldTime - fLastTimeSaved) >= fAutoSaveTime);
00063 if ( isAutoSaveTime && fLastEntrySaved != fEntry ) isAutoSave = true;
00064
00065 if ( isAutoSave && fBasketSaveLinked ) {
00066
00067
00068 fTBranch -> SetBasketSize(1000);
00069 } else {
00070 fTBranch -> SetBasketSize(fBasketSize);
00071 }
00072
00073 if ( isAutoSave ) {
00074 Int_t savecompress = 9;
00075 if ( fCompress >= 0 ) {
00076 savecompress = fTFile -> GetCompressionLevel();
00077 fTFile -> SetCompressionLevel(fCompress);
00078 }
00079
00080
00081 MSG("Per",Msg::kDebug) << "AutoSaving tree " << fTreeName << " with "
00082 << fTTree->GetEntries() << " entries to file "
00083 << fFullFilePathName << " ByTime(sec) "
00084 << currentVldTime << "." << endl;
00085 fTFile -> cd();
00086 fTTree -> AutoSave();
00087 fTFile -> SaveSelf();
00088 fLastTimeSaved = currentVldTime;
00089 fLastEntrySaved = fEntry;
00090 fLastBytesSaved = fTotalBytes;
00091 if ( fCompress >= 0 )fTFile -> SetCompressionLevel(savecompress);
00092 }
00093
00094 savedir -> cd();
00095
00096 return;
00097
00098 }
00099
00100 void PerOutputStream::ChangeFile() {
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 TFile* newFile = fTTree->GetCurrentFile();
00116 if ( !newFile ) {
00117 MSG("Per",Msg::kWarning)
00118 << "ChangeFile requested for tree " << fTreeName <<
00119 " from old file " << fFullFilePathName << " but TTree has null file ptr."
00120 << endl;
00121 return;
00122 }
00123 std::string newFileName = newFile -> GetName();
00124 MSG("Per",Msg::kInfo) << "PerOutputStream::ChangeFile requested for tree "
00125 << fTreeName << "\nfrom old file " << fFullFilePathName
00126 << " total entries " << fEntry+1
00127 << ", to new file " << newFileName << "." << endl;
00128 PerFileManager& perfilemanager = PerFileManager::Instance();
00129 perfilemanager.ChangeFile(fFullFilePathName,newFileName,newFile);
00130
00131 fFullFilePathName = newFileName;
00132 fTFile = newFile;
00133
00134
00135 fEntry = static_cast<Int_t>(fTTree->GetEntries()-1);
00136
00137 fLastEntrySaved = fEntry;
00138 fLastTimeSaved = 0;
00139 fLastBytesSaved = 0; fTotalBytes = 0;
00140
00141 return;
00142
00143 }
00144
00145 PerOutputStream::PerOutputStream(string treename, string classname,
00146 string username, string inputstreamname, Int_t splitlevel, Int_t basketsize,
00147 Int_t compress) :
00148 PerStream(treename),fUserName(username),fInputStreamName(inputstreamname),
00149 fSplitLevel(splitlevel),fBasketSize(basketsize),fCompress(compress),
00150 fAutoSaveInt(0),fAutoSaveTime(0),fAutoSaveBytes(0),fLastEntrySaved(-1),
00151 fLastTimeSaved(0),fLastBytesSaved(0),fTotalBytes(0),fBasketSaveLinked(false){
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 fClassName = classname;
00184
00185 }
00186
00187 PerOutputStream::~PerOutputStream() {
00188
00189
00190
00191
00192
00193
00194 }
00195
00196 std::ostream& PerOutputStream::Print(std::ostream& ms) const {
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 ms << " PerOutput";
00208 PerStream::Print(ms);
00209
00210 if (!fUserName.empty()) ms << " This stream serves objects of username "
00211 << fUserName << "." << endl;
00212
00213 ms << " TTree SplitLevel = " << fSplitLevel << endl;
00214
00215 if ( fAutoSaveInt && fAutoSaveTime ) {
00216 ms << " AutoSaves were requested in intervals of " << fAutoSaveInt
00217 << " entries or " << fAutoSaveTime
00218 << " seconds,\n whichever comes first." << endl;
00219 }
00220 else if (fAutoSaveInt) {
00221 ms << " AutoSaves were requested in intervals of " << fAutoSaveInt
00222 << " entries." << endl;
00223 }
00224 else if (fAutoSaveTime) {
00225 ms << " AutoSaves were requested in time intervals of " << fAutoSaveTime
00226 << " seconds." << endl;
00227 }
00228 else if (fAutoSaveBytes) {
00229 ms << " AutoSaves were requested in byte intervals of " << fAutoSaveBytes
00230 << " bytes." << endl;
00231 }
00232 else {
00233 ms << " AutoSaves were not requested." << endl;
00234 }
00235
00236 if (fBasketSaveLinked) {
00237 ms << " Branch basket dumps are requested to occur at the same\n"
00238 << " interval as the tree AutoSaves or when the branch basket size\n "
00239 << fBasketSize << " is reached, whichever comes first." << endl;
00240 }
00241 else {
00242 ms << " Branch basket dumps were not requested at regular intervals.\n"
00243 << " Basket dumps will occur when the basket size "
00244 << fBasketSize << " is reached." << endl;
00245 }
00246 if (fCompress >= 0) {
00247 ms << " Compression level " << fCompress
00248 << " was requested for this stream." << endl;
00249 }
00250
00251 return ms;
00252
00253 }
00254
00255 void PerOutputStream::SetAutoSave(UInt_t autoSaveInt, UInt_t autoSaveTime,
00256 UInt_t autoSaveBytes, bool basketSaveLinked) {
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 fAutoSaveInt = autoSaveInt;
00283 fAutoSaveTime = autoSaveTime;
00284 fAutoSaveBytes = autoSaveBytes;
00285 fBasketSaveLinked = basketSaveLinked;
00286
00287 return;
00288
00289 }
00290
00291 void PerOutputStream::Close() {
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 CloseFile();
00303
00304 }
00305
00306 void PerOutputStream::CloseFile() {
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 if ( IsFileChange() ) ChangeFile();
00318 fLastEntrySaved = -1;
00319 fLastTimeSaved = 0;
00320 fLastBytesSaved = 0;
00321 fTotalBytes = 0;
00322 PerStream::CloseFile();
00323
00324 }
00325
00326 bool PerOutputStream::SetFile(string fullfilepathname,
00327 Per::EAccessMode accessmode) {
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 if (!IsEnabled()) return false;
00349
00350
00351 TDirectory* savedir = gDirectory;
00352
00353
00354 if ( fTFile ) {
00355 CloseFile();
00356 }
00357
00358 fErrorCode = Per::kErrSuccess;
00359
00360 if (accessmode != Per::kNew && accessmode != Per::kRecreate &&
00361 accessmode != Per::kUpdate) {
00362 MSG("Per",Msg::kWarning)
00363 << "PerOutputStream::SetFile called w/ invalid accessmode "
00364 << Per::AsString(accessmode) << endl;
00365 fErrorCode = Per::kErrInvalidAccessMode;
00366 savedir -> cd();
00367 return false;
00368 }
00369
00370
00371 PerFileManager& perfilemanager = PerFileManager::Instance();
00372 const PerFile* file = perfilemanager.OpenFile(fullfilepathname,accessmode);
00373 if (!file) {
00374
00375 fErrorCode = perfilemanager.GetErrorCode();
00376 savedir -> cd();
00377 return false;
00378 }
00379 fFullFilePathName = fullfilepathname;
00380 fTFile = file -> GetTFile();
00381
00382 TTree* tree = dynamic_cast<TTree*> (fTFile -> Get(fTreeName.c_str()));
00383 if (tree) {
00384
00385 MSG("Per",Msg::kWarning)
00386 << "PerOutputStream::SetFile failed because requested tree "
00387 << fTreeName << " already exists in file " << fullfilepathname << endl;
00388 fErrorCode = Per::kErrTreeExists;
00389 delete tree;
00390 CloseFile();
00391 savedir -> cd();
00392 return false;
00393 }
00394
00395 fTFile -> cd();
00396
00397
00398
00399 Int_t savecompress = 9;
00400 if (fCompress >= 0) {
00401 savecompress = fTFile -> GetCompressionLevel();
00402 fTFile -> SetCompressionLevel(fCompress);
00403 }
00404
00405
00406
00407 fTTree = new TTree(fTreeName.c_str(),"Persistency stream tree");
00408
00409 fTObject = 0;
00410 TClass* tclass = gROOT -> GetClass(fClassName.c_str());
00411 if ( tclass ) fTObject = (TObject*)tclass->New();
00412
00413 if ( ! tclass ) {
00414 MSG("Per",Msg::kError)
00415 << "TClass not found for requested output stream of type "
00416 << fClassName.c_str() << "\nor class does not derive from TObject."
00417 << endl;
00418 CloseFile();
00419 savedir -> cd();
00420 return false;
00421 }
00422
00423 fTBranch = fTTree -> Branch(fClassName.c_str(),fClassName.c_str(),
00424 &fTObject,fBasketSize,fSplitLevel);
00425 if ( fTObject ) delete fTObject; fTObject = 0;
00426
00427 if (fCompress >= 0) fTFile -> SetCompressionLevel(savecompress);
00428
00429
00430
00431
00432 fTTree -> AutoSave();
00433 fTFile -> SaveSelf();
00434
00435
00436
00437 Int_t rootautosize = 2000000000;
00438 fTTree->SetAutoSave(rootautosize);
00439
00440
00441 savedir -> cd();
00442
00443 return true;
00444
00445 }
00446
00447 bool PerOutputStream::SetObject(TObject* object) {
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 if ( !IsEnabled() ) return false;
00463
00464 if( IsModified() ) {
00465
00466 Reset();
00467 }
00468
00469 if ( !IsOpen() ) {
00470 MSG("Per",Msg::kWarning)
00471 << "Attempting to SetObject in an unopened output stream." << endl;
00472 return false;
00473 }
00474
00475 if ( !object ) {
00476 MSG("Per",Msg::kWarning)
00477 << "PerOutputStream called with null object pointer." << endl;
00478 return false;
00479 }
00480
00481 if (strcmp(fClassName.c_str(),object->IsA()->GetName())) {
00482
00483 return false;
00484 }
00485
00486 if (!fUserName.empty() && strcmp(fUserName.c_str(),object->GetName())) {
00487
00488 return false;
00489 }
00490
00491 Registry* temptags = 0;
00492 bool isPersisted = false;
00493 bool isInputStream = true;
00494 if ( !fInputStreamName.empty() ) isInputStream = false;
00495 if ( RecMinos* record = dynamic_cast<RecMinos*>(object) ) {
00496 temptags = &(record->GetTempTags());
00497 if ( !isInputStream && temptags ) {
00498 const char* objectInputStream = 0;
00499 if ( temptags->Get("stream",objectInputStream) ) {
00500 if ( !strcmp(fInputStreamName.c_str(),objectInputStream) )
00501 isInputStream = true;
00502 }
00503 }
00504
00505 if ( !isInputStream ) return false;
00506
00507 isPersisted = record->IsPersistedToOutputStream(
00508 this->GetStreamName().c_str(),this->GetFullFilePathName().c_str(),
00509 this->GetTreeName().c_str());
00510 }
00511 else if ( RecRecord* record = dynamic_cast<RecRecord*>(object) ) {
00512 temptags = &(record->GetTempTags());
00513 if ( !isInputStream && temptags ) {
00514 const char* objectInputStream = 0;
00515 if ( temptags->Get("stream",objectInputStream) ) {
00516 if ( !strcmp(fInputStreamName.c_str(),objectInputStream) )
00517 isInputStream=true;
00518 }
00519 }
00520
00521 if ( !isInputStream ) return false;
00522
00523 isPersisted = record->IsPersistedToOutputStream(
00524 this->GetStreamName().c_str(),this->GetFullFilePathName().c_str(),
00525 this->GetTreeName().c_str());
00526 }
00527
00528 if ( !isInputStream || isPersisted ) return false;
00529
00530 fTObject = object;
00531 return true;
00532
00533 }
00534
00535 Int_t PerOutputStream::Store() {
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551 Int_t nBytes = 0;
00552
00553 TDirectory* savedir = gDirectory;
00554
00555 if ( !IsEnabled() || !IsModified() ) {
00556
00557
00558 return nBytes;
00559 }
00560
00561 if ( !IsOpen() ) {
00562 MSG("Per",Msg::kWarning)
00563 << "Attempting to store data on unopened output stream." << endl;
00564 return nBytes;
00565 }
00566
00567 if ( IsFileChange() ) ChangeFile();
00568
00569 fEntry++;
00570
00571
00572 UInt_t recordTime = 0;
00573 if ( RecMinos* record = dynamic_cast<RecMinos*>(fTObject) ) {
00574 recordTime = (record -> GetVldContext() -> GetTimeStamp()).GetSec();
00575 record->PersistedToOutputStream(this->GetStreamName().c_str(),
00576 this->GetFullFilePathName().c_str(),this->GetTreeName().c_str(),fEntry);
00577 }
00578 else if ( RecRecord* record = dynamic_cast<RecRecord*>(fTObject) ) {
00579 recordTime = (record->GetHeader()).GetVldContext().GetTimeStamp().GetSec();
00580 record->PersistedToOutputStream(this->GetStreamName().c_str(),
00581 this->GetFullFilePathName().c_str(),this->GetTreeName().c_str(),fEntry);
00582 }
00583
00584 if ( !recordTime && fAutoSaveTime ) {
00585
00586
00587 MSG("Per",Msg::kWarning) << "Using AutoSaveTime requires records\n"
00588 << "to derive from RecMinos or RecRecord class. Option will be ignored."
00589 << endl;
00590 fAutoSaveTime = 0;
00591 }
00592
00593 bool isAutoSave = false;
00594 if (!fLastTimeSaved) fLastTimeSaved = recordTime;
00595
00596 bool isAutoSaveInt
00597 = (fAutoSaveInt > 0 && (fEntry - fLastEntrySaved) >= (int)fAutoSaveInt);
00598 bool isAutoSaveTime
00599 = (fAutoSaveTime > 0 && (recordTime - fLastTimeSaved) >= fAutoSaveTime);
00600 bool isAutoSaveBytes
00601 = (fAutoSaveBytes > 0 && (fTotalBytes - fLastBytesSaved)>=fAutoSaveBytes);
00602
00603 if ( isAutoSaveInt || isAutoSaveTime || isAutoSaveBytes ) {
00604 isAutoSave = true;
00605 }
00606
00607 if ( isAutoSave && fBasketSaveLinked ) {
00608
00609
00610 fTBranch -> SetBasketSize(1000);
00611 } else {
00612 fTBranch -> SetBasketSize(fBasketSize);
00613 }
00614
00615
00616
00617 Int_t savecompress = 9;
00618 if ( fCompress >= 0 ) {
00619 savecompress = fTFile -> GetCompressionLevel();
00620 fTFile -> SetCompressionLevel(fCompress);
00621 }
00622
00623
00624 nBytes = fTTree -> Fill();
00625
00626 fTotalBytes += nBytes;
00627
00628 if ( IsFileChange() ) {
00629 if ( savedir->GetFile() == fTFile ) {
00630
00631 MSG("Per",Msg::kWarning) << "gDirectory points to old file and\n"
00632 << "ChangeFile requested, will switch to:" << gDirectory->GetPath()
00633 << endl;
00634 savedir = gDirectory;
00635 }
00636 ChangeFile();
00637 }
00638 else if ( isAutoSave ) {
00639
00640 MSG("Per",Msg::kDebug) << "AutoSaving tree " << fTreeName << " with "
00641 << fTTree->GetEntries() << " entries to file "
00642 << fFullFilePathName << " IsAutoSaveInt/Time/Bytes "
00643 << isAutoSaveInt << "/" << isAutoSaveTime << "/" << isAutoSaveBytes
00644 << endl;
00645 fTFile -> cd();
00646 fTTree -> AutoSave();
00647 fTFile -> SaveSelf();
00648 fLastTimeSaved = recordTime;
00649 fLastEntrySaved = fEntry;
00650 fLastBytesSaved = fTotalBytes;
00651 }
00652
00653 if ( fCompress >= 0 )fTFile -> SetCompressionLevel(savecompress);
00654
00655 savedir -> cd();
00656
00657 return nBytes;
00658
00659 }
00660
00661 Int_t PerOutputStream::Write() {
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 Int_t nBytes = 0;
00674
00675 if ( !IsOpen() || !IsEnabled() ) return nBytes;
00676
00677 TDirectory* savedir = gDirectory;
00678
00679
00680 if ( IsFileChange() ) ChangeFile();
00681
00682 fTFile -> cd();
00683
00684 Int_t savecompress = 9;
00685 if (fCompress >= 0) {
00686 savecompress = fTFile -> GetCompressionLevel();
00687 fTFile -> SetCompressionLevel(fCompress);
00688 }
00689
00690 nBytes = fTTree -> Write(NULL,TObject::kOverwrite);
00691 MSG("Per",Msg::kDebug) << "Wrote tree " << fTreeName
00692 << " with " << fTTree->GetEntries() << " entries "
00693 << " to file " << fFullFilePathName << "." << endl;
00694
00695 if (fCompress >= 0) fTFile -> SetCompressionLevel(savecompress);
00696
00697 savedir -> cd();
00698
00699 return nBytes;
00700
00701 }
00702
00703
00704
00705
00706