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

PerFileManager.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // PerFileManager
00004 //
00005 // Package: Per (Persistency).
00006 //
00007 // S. Kasahara 11/00
00008 //
00009 // Purpose: Utility singleton file manager used by persistency package to open
00010 //          and close files. 
00011 //
00012 // Based in part on the ideas of the BaBar Kanga(roo) RooFileManager class
00014 
00015 #include <string>
00016 #include "TEnv.h"
00017 
00018 #include "Persistency/PerFileManager.h"
00019 #include "Persistency/PerFile.h"
00020 #include "MessageService/MsgService.h"
00021 
00022 std::ostream& operator<<(std::ostream& ms, const PerFileManager& fm) 
00023 {
00024   return fm.Print(ms);
00025 }
00026 
00027 ClassImp(PerFileManager)
00028 
00029 //   Definition of static data members
00030 //   *********************************
00031 
00032 CVSID("$Id: PerFileManager.cxx,v 1.12 2005/09/25 19:25:52 schubert Exp $");
00033 
00034 PerFileManager* PerFileManager::fgInstance = 0;
00035 
00036 
00037 // Definition of methods (alphabetical order)
00038 // ******************************************
00039 
00040 
00041 const PerFile* PerFileManager::ChangeFile(std::string oldfilepathname, 
00042                                std::string newfilepathname,TFile* newfileptr) {
00043   //  Purpose:  This method is useful when TTree::Fill has closed the current
00044   //            file and opened a new one with extension _1 because it has
00045   //            detected that the file limit of 2 GByte is near.  Its purpose
00046   //            is to swap the new file name and file pointer for the old
00047   //            filename and pointer in its file map, without actually
00048   //            closing the old file or opening the new file, since this
00049   //            has already been done by root.
00050   //
00051   //  Arguments:oldfilepathname  full file path name of old file.
00052   //            newfilepathname  full file path name of new file.
00053   //            newfileptr       pointer to new file opened by root.
00054   //
00055   //  Return:  pointer to new PerFile.
00056   //
00057   //  Contact:   S. Kasahara
00058   //
00059   //  Notes: Caution: this method is only meant to be used under the
00060   //         special circumstances described above. 
00061   //
00062 
00063   FileMapItr itr = fFileMap.find(oldfilepathname);
00064 
00065   if ( itr == fFileMap.end() ) {
00066     // Nothing to be done if conversion already made
00067     FileMapItr newItr = fFileMap.find(newfilepathname);
00068     if ( newItr == fFileMap.end() ) {
00069       MSG("Per",Msg::kWarning) << "ChangeFile unable to find old file "
00070          << oldfilepathname << " or new file " << newfilepathname 
00071                                << " in file map." << endl; 
00072       return (PerFile*)0;
00073     }
00074     else return itr->second;
00075   }
00076 
00077   // Else convert PerFile attributes and replace entry in map
00078   PerFile* perFile = itr->second;
00079   perFile -> ChangeFile(newfilepathname,newfileptr);
00080 
00081   fFileMap.erase(itr);  // erase old entry
00082   fFileMap[newfilepathname] = perFile;  // replace it with new
00083 
00084   return perFile;
00085 
00086 }
00087 
00088 void PerFileManager::CloseAll() {
00089   //  Purpose:  Close all files managed by PerFileManager.
00090   //
00091   //  Argument: none.
00092   //
00093   //  Return:  none.
00094   //
00095   //  Contact:   S. Kasahara
00096   //
00097   //  Notes: Files are closed regardless of remaining number of clients.
00098   //
00099 
00100 
00101   for (FileMapItr itr = fFileMap.begin(); itr != fFileMap.end(); ++itr) {
00102     PerFile *file = itr -> second;
00103     file -> Close(true); // close file 
00104     delete file; // retrieve file memory
00105   }
00106   fFileMap.clear(); // clear all map entries
00107 
00108 }
00109 
00110 void PerFileManager::CloseFile(string fullfilepathname) {
00111   //  Purpose:  Close file with name fullfilepathname.  If file has more
00112   //            than one client, number of clients is just decremented by
00113   //            one and the file is left open.
00114   //
00115   //  Argument: fullfilepathname string containing name of file of interest.
00116   //
00117   //  Return:  none
00118   //
00119   //  Contact:   S. Kasahara
00120   //
00121 
00122   FileMapItr itr = fFileMap.find(fullfilepathname);
00123   if (itr != fFileMap.end()) {
00124     UInt_t clientsleft = (itr -> second) -> Close();
00125     if(clientsleft <= 0) {
00126       // Retrieve file memory and clear entry from map 
00127       delete (itr->second); 
00128       fFileMap.erase(itr);
00129     }
00130   }
00131   else {
00132     MSG("Per",Msg::kInfo) << "Unable to close file " << fullfilepathname <<
00133       ". File was not opened by PerFileManager. " << endl;
00134   }
00135   
00136 }
00137 
00138 
00139 const PerFile* PerFileManager::GetOpenedFile(string fullfilepathname) const {
00140   //  Purpose:  Retrieve file corresponding to fullfilepathname.
00141   //            File must have been previously opened with OpenFile method.
00142   //
00143   //  Argument: fullfilepathname string containing name of file of interest.
00144   //
00145   //  Return:  pointer to a constant PerFile. If file member with name
00146   //           fullfilepathname does not exist, returns (PerFile*)0.  
00147   //
00148   //  Contact:   S. Kasahara
00149   //
00150   //  Notes: User may not modify PerFile data directly.  All
00151   //         modifications should be handled through the PerFileManager. 
00152 
00153   FileMapConstItr citr = fFileMap.find(fullfilepathname);
00154   return (citr != fFileMap.end()) ? citr -> second : (PerFile*)0;
00155 
00156 }
00157 
00158 PerFileManager& PerFileManager::Instance() {
00159   //  Purpose:  Return unique instance of PerFileManager, creating it
00160   //            if necessary.
00161   //
00162   //  Arguments: none.
00163   //
00164   //  Return:  reference to PerFileManager.
00165   //
00166   //  Contact:   S. Kasahara
00167   //
00168 
00169   static Cleaner cleaner; // Cleaner destructor provides cleanup of singleton
00170   if (fgInstance == 0) {
00171     cleaner.UseMe(); // dummy call to quiet compiler warnings
00172     fgInstance = new PerFileManager();
00173   }
00174   return *fgInstance;
00175 
00176 }
00177 
00178 
00179 const PerFile* PerFileManager::OpenFile(string fullfilepathname, Per::EAccessMode accessmode) {
00180   //  Purpose:  Open file with name fullfilepathname in specified accessmode.
00181   //            If file is already open, adds a new client to this file if
00182   //            new accessmode is compatible with the accessmode in which the
00183   //            file was initially opened.
00184   //
00185   //  Arguments:fullfilepathname string containing full file path name of
00186   //                             file to be opened.  File may be local
00187   //                             or remote.  See PerFile::OpenFile
00188   //                             for information about the remote filename
00189   //                             format.
00190   //            accessmode       EAccessMode in which file is to be opened
00191   //                             (defined in Per.h).
00192   //                             kRead = open file in read only mode.
00193   //                             kNew = open new file in read/write. If file
00194   //                                    already exists, do not overwrite.
00195   //                             kRecreate = same as kNew, but if file already
00196   //                                         exists overwrite.
00197   //                             kUpdate = open existing file in read/write.
00198   //                                
00199   //
00200   //  Return:  pointer to a constant PerFile. If unable to open
00201   //           file, or if requested accessmode is incompatible with the
00202   //           accessmode in which the file was originally opened, 
00203   //           returns (PerFile*)0.
00204   //
00205   //  Contact:   S. Kasahara
00206   //
00207   //  Notes: User may not modify PerFile data directly.  All
00208   //         modifications should be handled through the PerFileManager.
00209   //         See PerFile::OpenFile for information about specifying
00210   //         the authentication information required for remote access.
00211   //         If file fails to open, PerFileManager::GetErrorCode can
00212   //         be used to determine source of failure.
00213 
00214   bool openok = false;
00215 
00216   fErrorCode = Per::kErrSuccess;
00217 
00218   PerFile* file = fFileMap[fullfilepathname];
00219   if (!file) {
00220     // File not found in map, need to create new one
00221     file = new PerFile(fullfilepathname,accessmode);
00222     fFileMap[fullfilepathname] = file;
00223     if(!file || !file -> IsOpen()) {
00224       fErrorCode = Per::kErrFileError;
00225       if (file) {
00226         fErrorCode = file -> GetErrorCode();
00227         delete file; file = 0; // retrieve memory
00228       }
00229 #ifndef IRIX6
00230       fFileMap.erase(fullfilepathname); // erase entry from map
00231 #else
00232       // erase entry from map -- SGI barfs at fFileMap.erase(fullfilepathname);
00233       FileMapItr itr = fFileMap.find(fullfilepathname);
00234       fFileMap.erase(itr);
00235 #endif
00236     }
00237     else {
00238       openok = true;
00239     }  
00240   }
00241   else {
00242     // File has already been opened, attempt to add new client if 
00243     // accessmodes are compatible
00244     openok = file -> AddNewClient(accessmode);
00245     if (!openok) fErrorCode = Per::kErrFileConflict;
00246   }
00247 
00248   return (openok) ? file : (PerFile*)0;
00249 
00250 }
00251 
00252 PerFileManager::PerFileManager() : fErrorCode(Per::kErrSuccess) {
00253   // Purpose: Default constructor.
00254   //
00255   // Arguments: none.
00256   //
00257   // Return: none.
00258   //
00259   // Contact:  S. Kasahara
00260   //
00261   // Notes: Not called directly, use PerFileManager::Instance() instead.
00262 
00263   // Initialize environment variable to force use of TNetFile in TFile::Open 
00264   // when path to file is prefaced by "root(s):", even when file path host
00265   // indicates a local file.
00266   gEnv -> SetValue("TFile.ForceRemote",1);
00267 
00268 }
00269 
00270 PerFileManager::~PerFileManager() {
00271   //  Purpose:  Destructor.
00272   //
00273   //  Arguments: none.
00274   //
00275   //  Return:  none.
00276   //
00277   //  Contact:   S. Kasahara
00278   //
00279   
00280   // Close all managed files and retrieve allocated memory
00281   CloseAll();
00282 
00283 }
00284 
00285 std::ostream& PerFileManager::Print(std::ostream& ms) const {
00286   //  Purpose:  Print current map of files maintained by file manager on
00287   //            ostream.
00288   //
00289   //  Arguments: ms ostream to display on.
00290   //
00291   //  Return:  ostream reference.
00292   //
00293   //  Contact:   S. Kasahara
00294   //
00295 
00296   ms << "Number of files currently open = " << GetNumFile() << "." << endl;
00297 
00298   int ifile=0;
00299   for (FileMapConstItr itr = fFileMap.begin(); itr != fFileMap.end(); ++itr) {
00300     ms << ++ifile << ")" << itr -> second;
00301   }
00302 
00303   return ms;
00304 }
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00316 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 

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