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

PerOutputStream.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // PerOutputStream
00004 //
00005 // Package: Per (Persistency).
00006 //
00007 // S. Kasahara 04/2001
00008 //
00009 // Purpose: Class for managing an individual output data stream.
00010 //          The user should use the PerOutputStreamManager to open and
00011 //          close PerOutputStreams.
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 //   Definition of static data members
00036 //   *********************************
00037 
00038 CVSID("$Id: PerOutputStream.cxx,v 1.41 2007/01/15 20:57:28 rhatcher Exp $");
00039 
00040 
00041 // Definition of methods (alphabetical order)
00042 // ***************************************************
00043 
00044 void PerOutputStream::AutoSaveByTime(UInt_t currentVldTime) {
00045   //
00046   // Purpose: AutoSave stream if new entries on this tree and currentvldtime
00047   //          passed from manager satisfies autosavetime requirement. 
00048   //
00049 
00050 
00051   if ( !IsOpen() || fEntry == -1 ) return;
00052 
00053   TDirectory* savedir = gDirectory; // save current working directory
00054 
00055   if ( IsFileChange() ) ChangeFile();
00056 
00057   bool isAutoSave = false;
00058   
00059   if (!fLastTimeSaved) fLastTimeSaved = currentVldTime;
00060   // Save tree to file if requested on this entry and/or time interval
00061   bool isAutoSaveTime
00062      = (fAutoSaveTime > 0 && (currentVldTime - fLastTimeSaved) >= fAutoSaveTime);
00063   if ( isAutoSaveTime && fLastEntrySaved != fEntry ) isAutoSave = true;
00064   
00065   if ( isAutoSave && fBasketSaveLinked ) {
00066     // Reset basket size so baskets will be dumped on next TTree::Fill
00067     // if more than 1 kbyte of data in that buffer
00068     fTBranch -> SetBasketSize(1000);
00069   } else {
00070     fTBranch -> SetBasketSize(fBasketSize); // reset to default basketsize
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     // Save tree to file if requested on this entry interval
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();  // save tree to file
00087     fTFile -> SaveSelf();  // save file directory containing this tree
00088     fLastTimeSaved = currentVldTime;
00089     fLastEntrySaved = fEntry;
00090     fLastBytesSaved = fTotalBytes;
00091     if ( fCompress >= 0 )fTFile -> SetCompressionLevel(savecompress);
00092   }
00093     
00094   savedir -> cd(); // return to original working directory
00095 
00096   return;
00097 
00098 }
00099   
00100 void PerOutputStream::ChangeFile() {
00101   //
00102   //  Purpose:  This private method is called internally when it is detected
00103   //            that TTree::Fill has closed the current file and opened
00104   //            a new one with extension _n because it has detected that
00105   //            the file limit of 2 GByte is near.
00106   //
00107   //  Arguments: none.
00108   //
00109   //  Return: none.
00110   //
00111   //  Contact:   S. Kasahara
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   // All tree parameters get reset upon start of new file
00135   fEntry = static_cast<Int_t>(fTTree->GetEntries()-1);
00136   // All counts start fresh in new file
00137   fLastEntrySaved = fEntry;
00138   fLastTimeSaved = 0; // will be set to 1st record time
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   //  Purpose:  Default constructor.
00154   //
00155   //  Arguments: 
00156   //      treename   string name of tree served by this output stream.
00157   //     classname   string classname of object to be stored in this stream -
00158   //                        used to retrieve objects from MomNavigator.
00159   //      username   string username of object to be stored in this stream -
00160   //                        secondary identifier used to retrieve object from 
00161   //                        MomNavigator.
00162   // inputstreamname string input streamname of origin of object to be stored in this
00163   //                        stream - tertiary identifier used to retrieve object from
00164   //                        MomNavigator.
00165   //    splitlevel   Int_t  splitlevel of created ROOT TTree branch (default = 0)
00166   //    basketsize   Int_t  basketsize with which main branch is opened
00167   //                        (default = 64000).
00168   //      compress   Int_t  compression level of tree. If -1 (default),
00169   //                        tree compression level is set to that of
00170   //                        file (default file compression = 1).  ROOT defines 
00171   //                        compression levels 0-9, with level 0 == no 
00172   //                        compression.
00173   //
00174   //  Return:    n/a.
00175   //
00176   //  Contact:   S. Kasahara
00177   // 
00178   //  Notes: This constructor doesn't do anything except fill in data members.
00179   //         PerOutputStream does not become active until PerOutputStream::
00180   //         SetFile is invoked.
00181   // 
00182 
00183   fClassName = classname;
00184 
00185 }
00186 
00187 PerOutputStream::~PerOutputStream() {
00188   //
00189   //  Purpose:  PerOutputStream destructor.  
00190   //
00191   //  Contact:   S. Kasahara
00192   // 
00193 
00194 }
00195 
00196 std::ostream& PerOutputStream::Print(std::ostream& ms) const {
00197   //
00198   //  Purpose:  Print status of stream on std::ostream.
00199   //
00200   //  Arguments: ms std::ostream to display on.
00201   //
00202   //  Return:  std::ostream reference.
00203   //
00204   //  Contact:   S. Kasahara
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   //  Purpose:  Set AutoSave interval for this stream.  The TTree will
00259   //            be saved to file every fAutoSaveInt entries OR 
00260   //            OR every fAutoSaveTime (sec) OR every fAutoSaveBytes
00261   //            bytes filled to the tree, whichever comes first.
00262   //            Any or all of the autosave intervals may be set. An autosave
00263   //            parameter set to zero will be ignored.
00264   //
00265   //  Arguments: 
00266   //           autoSaveInt   UInt_t  TTree save entry interval     (default=0 
00267   //                              => no AutoSave requested at entry intervals) 
00268   //           autoSaveTime  UInt_t  TTree save time interval(sec) (default=0 
00269   //                              => no AutoSave requested at time intervals) 
00270   //           autoSaveBytes UInt_t  TTree save byte interval      (default=0 
00271   //                              => no AutoSave requested at byte intervals) 
00272   //        basketSaveLinked bool    tie basket dumps to TTree saves so that
00273   //                                 all branch baskets are dumped just before
00274   //                                 the tree header is saved to disk. 
00275   //                                 (default = true)
00276   //
00277   //  Return:  none
00278   //
00279   //  Contact:   S. Kasahara
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   //  Purpose:  Close the output stream.
00294   //
00295   //  Arguments: none.
00296   //
00297   //  Return:  none.
00298   //
00299   //  Contact:   S. Kasahara
00300   // 
00301 
00302   CloseFile();
00303 
00304 }
00305 
00306 void PerOutputStream::CloseFile() {
00307   //
00308   //  Purpose:  Close the file attached to the output stream.
00309   //
00310   //  Arguments: none.
00311   //
00312   //  Return:  none.
00313   //
00314   //  Contact:   S. Kasahara
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   //  Purpose:  Set new output file for this stream.
00330   //
00331   //  Arguments: fullfilepathname string      new filename containing stream.
00332   //             accessmode Per::EAccessMode  accessmode in which to open file.
00333   //                                          (must be Per::kNew or
00334   //                                           Per::kRecreate (default)).
00335   //
00336   //  Return:  true if file was opened successfully and stream tree of
00337   //           name fTreeName was set to that file, else false.  See Note.
00338   //
00339   //  Contact:   S. Kasahara
00340   //
00341   //  Notes:  This method enforces the uniqueness of trees of a given 
00342   //          treename in the output file.  This is done to avoid overwriting
00343   //          trees in the same file.  If treename is not unique, the new file
00344   //          is not set for this stream, and false is returned.
00345   //          If SetFile fails, the method PerStream::GetErrorCode can be
00346   //          used to determine reason for failure.
00347 
00348   if (!IsEnabled()) return false;
00349 
00350   // Save current working directory
00351   TDirectory* savedir = gDirectory;
00352 
00353   // Check to see if file is already set, if so close it before proceeding
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   // Use file manager singleton to open file in requested mode.
00371   PerFileManager& perfilemanager = PerFileManager::Instance();
00372   const PerFile* file = perfilemanager.OpenFile(fullfilepathname,accessmode);
00373   if (!file) {
00374     // file open failed
00375     fErrorCode = perfilemanager.GetErrorCode();
00376     savedir -> cd();
00377     return false;
00378   }
00379   fFullFilePathName = fullfilepathname;
00380   fTFile = file -> GetTFile();
00381   // Check to see if a previous existing tree of fTreeName exists in this file
00382   TTree* tree = dynamic_cast<TTree*> (fTFile -> Get(fTreeName.c_str()));
00383   if (tree) {
00384     // tree of duplicate treename already exists in file
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(); // make current file the working directory
00396 
00397   // This funniness is required because otherwise must manually
00398   // set compression level of all subbranches when tree is split
00399   Int_t savecompress = 9;
00400   if (fCompress >= 0) {
00401     savecompress = fTFile -> GetCompressionLevel();
00402     fTFile -> SetCompressionLevel(fCompress);
00403   }
00404 
00405   // Create new tree with requested treename, may want to specify job
00406   // related title for this tree
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   // Autosave immediately to avoid the situation in which the open file
00430   // has basket dumps but no keys which would produce an error during the
00431   // read of the open file.
00432   fTTree -> AutoSave();  // save tree to file
00433   fTFile -> SaveSelf();  // save file directory containing this tree
00434   
00435   // Effectively turn ROOT autosave off.  AutoSave is controlled instead
00436   // through PerOutputStream AutoSavexxx parameters
00437   Int_t rootautosize = 2000000000;
00438   fTTree->SetAutoSave(rootautosize);
00439 
00440   // Switch back to original working directory
00441   savedir -> cd();
00442 
00443   return true;
00444 
00445 }
00446 
00447 bool PerOutputStream::SetObject(TObject* object) {
00448   //
00449   //  Purpose:  Set object to be persisted to ROOT TTree main branch.
00450   //            The object is not actually filled into the branch until the
00451   //            PerOutputStream::Store() method is invoked.
00452   //
00453   //  Arguments: object:  pointer to object to be stored.  Must be of same
00454   //                      type as "ClassName" with which PerOutputStream
00455   //                      was created.  
00456   //
00457   //  Return:  true if stream is successfully updated.
00458   //
00459   //  Contact:   S. Kasahara
00460   // 
00461 
00462   if ( !IsEnabled() ) return false;
00463 
00464   if( IsModified() ) {
00465     // Reset object cache managed by this stream
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     // object is of wrong classname for this stream
00483     return false;
00484   }
00485 
00486   if (!fUserName.empty() && strcmp(fUserName.c_str(),object->GetName())) {
00487     // object is of wrong username for this stream
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     // test if object is of wrong input stream name for this stream
00505     if ( !isInputStream ) return false;
00506     // test to see if object has already been persisted to this stream
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     // test if object is of wrong input stream name for this stream
00521     if ( !isInputStream ) return false;
00522     // test if object has already been persisted to this stream
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   //  Purpose:  Fill data in stream tree.
00538   //
00539   //  Arguments: none.
00540   //
00541   //  Return:  number of bytes filled.
00542   //
00543   //  Contact:   S. Kasahara
00544   // 
00545   //  Notes:  This method fills the data into the stream tree. If fAutoSaveInt
00546   //          or fAutoSaveTime interval has been set, it will also
00547   //          invoke the proper methods to save the baskets and tree to file
00548   //          at correct entry and/or time interval.
00549   //
00550 
00551   Int_t nBytes = 0;
00552 
00553   TDirectory* savedir = gDirectory; // save current working directory
00554 
00555   if ( !IsEnabled() || !IsModified() ) {
00556     // disabled streams or streams in which an object has not been loaded
00557     // are not persisted
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++;  // increment current entry number for this stream
00570 
00571   // Determine record validity time in secs
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     // Records are required to derive from RecMinos class to use autosave
00586     // by time interval.
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   // Save tree to file if requested on this entry and/or time interval
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     // Reset basket size so baskets will be dumped on next TTree::Fill
00609     // if more than 1 kbyte of data in that buffer
00610     fTBranch -> SetBasketSize(1000);
00611   } else {
00612     fTBranch -> SetBasketSize(fBasketSize); // reset to default basketsize
00613   }
00614 
00615   // Must do this so that if AutoSave is invoked it knows the compression
00616   // level of the tree
00617   Int_t savecompress = 9;
00618   if ( fCompress >= 0 ) {
00619     savecompress = fTFile -> GetCompressionLevel();
00620     fTFile -> SetCompressionLevel(fCompress);
00621   }
00622 
00623   // Fill tree
00624   nBytes = fTTree -> Fill();
00625 
00626   fTotalBytes += nBytes;
00627   // Test for new file pointer in case ChangeFile was invoked
00628   if ( IsFileChange() ) {
00629     if ( savedir->GetFile() == fTFile ) {
00630       // This shouldn't happen
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     // Save tree to file if requested on this entry interval
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();  // save tree to file
00647     fTFile -> SaveSelf();  // save file directory containing this tree
00648     fLastTimeSaved = recordTime;
00649     fLastEntrySaved = fEntry;
00650     fLastBytesSaved = fTotalBytes;
00651   }
00652 
00653   if ( fCompress >= 0 )fTFile -> SetCompressionLevel(savecompress);
00654     
00655   savedir -> cd(); // return to original working directory
00656 
00657   return nBytes;
00658 
00659 }
00660 
00661 Int_t PerOutputStream::Write() {
00662   //
00663   //  Purpose:  Write the tree to file.  By default this overwrites any
00664   //            previous version of the tree in the file.
00665   //
00666   //  Arguments: none.
00667   //
00668   //  Return:  number of bytes written to file.
00669   //
00670   //  Contact:   S. Kasahara
00671   // 
00672 
00673   Int_t nBytes = 0;
00674 
00675   if ( !IsOpen() || !IsEnabled() ) return nBytes;
00676 
00677   TDirectory* savedir = gDirectory; // save current working directory
00678 
00679   // Check to see if root has changed the file from underneath us
00680   if ( IsFileChange() ) ChangeFile();
00681 
00682   fTFile -> cd(); // move to directory of current file
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); // save tree to this file
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();  // return to original directory
00698 
00699   return nBytes;
00700 
00701 }
00702 
00703 
00704 
00705 
00706 

Generated on Mon Feb 15 11:07:19 2010 for loon by  doxygen 1.3.9.1