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

IoFileListItem.cxx

Go to the documentation of this file.
00001 
00002 //
00003 // IoFileListItem
00004 //
00005 // Package: Io (IoModules).
00006 //
00007 // S. Kasahara 02/2003
00008 //
00009 // Purpose: Helper class to associate a file path, including possibly
00010 //          wildcards, with an associated file list and stream list.
00011 //
00013 
00014 #include <algorithm>
00015 #include <iostream>
00016 #include <vector>
00017 
00018 #include "TFile.h"
00019 #include "TROOT.h"
00020 #include "TKey.h"
00021 #include "TClass.h"
00022 #include "TRegexp.h"
00023 #include "TSystem.h"
00024 
00025 #include "IoModules/IoFileListItem.h"
00026 #include "Persistency/PerFileManager.h"
00027 #include "Persistency/PerFile.h"
00028 #include "Util/UtilString.h"
00029 
00030 std::ostream& operator << ( std::ostream& os, const IoFileListItem& ifl ) 
00031                                               { return ifl.Print(os); }
00032 
00033 // Definition of methods (alphabetical order)
00034 // ******************************************
00035 
00036 std::string IoFileListItem::BuildDefStreamList(std::string filename) {
00037 //
00038 // Purpose:  Open the specified file and determine the default list of
00039 //           streams for that file.
00040 //
00041 // Contact:  S. Kasahara
00042 //
00043 
00044   std::string defstreamlist;
00045   
00046   const PerFile* perFile
00047     = PerFileManager::Instance().OpenFile(filename,Per::kRead);
00048   if ( !perFile ) return defstreamlist; // file open failed
00049 
00050   TFile* tfile = perFile -> GetTFile();
00051   // use file keys to determine names of existing trees in input file
00052   tfile -> ReadKeys();
00053   TKey* key;
00054   TIter nextkey(tfile->GetListOfKeys());
00055   while ((key = (TKey*)nextkey())) {
00056     TClass* tclass = gROOT -> GetClass(key->GetClassName());
00057     if ( tclass -> InheritsFrom("TTree") ) {
00058       // Can be TTree or any of its derived classes
00059       std::string newstream = key -> GetName();
00060       if ( defstreamlist.empty() ) defstreamlist = newstream;
00061       else defstreamlist += "," + newstream;
00062     }
00063   }
00064   PerFileManager::Instance().CloseFile(filename);
00065   
00066   return defstreamlist;
00067 
00068 }
00069 
00070 std::list<std::string> IoFileListItem::BuildFileIndex (std::string filepath) {
00071 //
00072 //  Purpose:  Build file index from input filepath. The filename portion of 
00073 //            the path may include wildcard(s), e.g.
00074 //            /mypath/myfile*.root, or
00075 //            ~kasahara/mypath/*p*.root
00076 //            The directory path may include standard shell characters, 
00077 //            e.g. $,.,~  The input filepath will be used to build a list of 
00078 //            fullfilepathnames to be returned to user.
00079 //
00080 //  Contact: S. Kasahara
00081 //
00082 //  Notes: This code is adapted from ROOT's TChain::Add method, but
00083 //         augmented to allow wildcards in the directory path.
00084 //
00085 
00086   std::list<std::string> fileList;
00087 
00088   if ( strchr(filepath.c_str(),'*') == 0 ) {
00089     // No wildcard, just push filepath as is
00090     fileList.push_back(filepath);  
00091     return fileList;
00092   }
00093 
00094   // wildcard present
00095   // Break full directory path up into a set of short strings delimited by "/"
00096   std::vector<std::string> itemizedpath;
00097   UtilString::StringTok(itemizedpath,filepath,"/");
00098   
00099   // if wildcard present in directory path, there may be multiple directories
00100   // to search. dirlist is list of directories to search.
00101   std::vector<std::string> dirlist;
00102   std::string filename;
00103   
00104   if ( itemizedpath.size() <= 1 ) {
00105     // If no '/' specified in input filepath, use working directory.
00106     if ( filepath.find("/") == 0 ) dirlist.push_back("/");
00107     else dirlist.push_back(gSystem->WorkingDirectory());
00108     filename = filepath;
00109   }
00110   else {
00111     // filename is last of segments
00112     filename=itemizedpath[itemizedpath.size()-1]; 
00113 
00114     // Seed directory list
00115     if ( filepath.find("/") == 0 ) 
00116       BuildDirIndex("/",itemizedpath[0],dirlist);
00117     else if ( strchr(itemizedpath[0].c_str(),'*') != 0 ) {
00118       // wildcard, but no initial "/". Assume working directory
00119       BuildDirIndex("./",itemizedpath[0],dirlist);
00120     }
00121     else {
00122       dirlist.push_back(gSystem->ExpandPathName(itemizedpath[0].c_str()));
00123     }
00124     
00125 
00126     for ( unsigned int is = 1; is < itemizedpath.size()-1; is++ ) {
00127       std::vector<std::string> subdirlist;
00128       for (unsigned int idir = 0; idir != dirlist.size(); idir++) {
00129         std::string dirpath = dirlist[idir];
00130         BuildDirIndex(dirpath,itemizedpath[is],subdirlist);
00131       }
00132       dirlist.clear();
00133       for ( unsigned int isub = 0; isub != subdirlist.size(); isub++) {
00134         dirlist.push_back(subdirlist[isub]);
00135       }
00136     }
00137   }
00138   
00139   // List of directory paths is now final, loop to test filename
00140   for ( unsigned int idir = 0; idir < dirlist.size(); idir++ ) {
00141     if ( strchr(filename.c_str(),'*') == 0 ) {
00142       // No wildcard in filename, test existence in this directory
00143       std::string fullfilepath = dirlist[idir]+"/"+filename;
00144       // accesspathname returns false if it was able to access file, bizarre
00145       Bool_t isFail = gSystem->AccessPathName(fullfilepath.c_str());
00146       if ( !isFail ) fileList.push_back(fullfilepath);
00147     }
00148     else {
00149       void *dir = gSystem->OpenDirectory(dirlist[idir].c_str());
00150       if ( dir ) {
00151         TRegexp re(filename.c_str(),kTRUE); // kTRUE indicates wildcard present
00152         const char* dirfile;
00153         while ((dirfile = gSystem->GetDirEntry(dir))) {
00154           if ( !strcmp(dirfile,".") || !strcmp(dirfile,"..") ) continue;
00155           if (   !strcmp(filename.c_str(),dirfile) 
00156               || TString(dirfile).Index(re)!=kNPOS) {
00157             // filename or regular expression matches dirfile 
00158             std::string fullfilepathname = dirlist[idir] + "/"
00159                                          + std::string(dirfile);
00160             fileList.push_back(fullfilepathname);
00161           }
00162         }
00163         gSystem->FreeDirectory(dir);
00164       }
00165     }
00166   }
00167 
00168   return fileList;
00169 
00170 }
00171 
00172 void IoFileListItem::BuildDirIndex(std::string dirpath,std::string subdir,
00173                                  std::vector<std::string>& subdirlist) const {
00174   // Search for directories matching character string subdir in directory
00175   // dirpath.  subdir may include wildcards.  Matching subdirs are
00176   // pushed to subdirlist.
00177   
00178   std::string separator = "/";
00179   if ( dirpath.find("/") == dirpath.size()-1 ) separator = "";
00180 
00181   if ( strchr(subdir.c_str(),'*') == 0 ) {
00182     // No wildcard in subdirectory.
00183     subdirlist.push_back(dirpath+separator+subdir);
00184     return;
00185   }
00186 
00187   void *dir = gSystem->OpenDirectory(dirpath.c_str());
00188   if ( !dir ) return;
00189   
00190   // kTRUE indicates wildcard present
00191   TRegexp re(subdir.c_str(),kTRUE); 
00192   const char* dirfile;
00193   while ((dirfile = gSystem->GetDirEntry(dir))) {
00194     if ( !strcmp(dirfile,".") || !strcmp(dirfile,"..") ) continue;
00195     if (!strcmp(subdir.c_str(),dirfile) 
00196         || TString(dirfile).Index(re)!=kNPOS) {
00197       // filename matches subdir
00198       std::string fulltestpath = dirpath + separator + std::string(dirfile);
00199       
00200       // check to see that it's a directory
00201       FileStat_t filestatbuf;
00202       int isFailed 
00203            = gSystem->GetPathInfo(fulltestpath.c_str(),filestatbuf);
00204       if ( !isFailed ) {
00205         if ( R_ISDIR(filestatbuf.fMode) ) 
00206           subdirlist.push_back(fulltestpath.c_str());
00207       }  
00208     }
00209   }
00210 
00211   gSystem->FreeDirectory(dir);
00212 
00213   return;
00214 
00215 }
00216 
00217 
00218 IoFileListItem::IoFileListItem(const char* filepath, int at,
00219                            const char* streams): fFilePath(filepath),fAt(at) {
00220   //
00221   //  Purpose:  Constructor 
00222   //
00223   //  Arguments: filepath      May include wildcards
00224   //             at            Index position to which this file list should
00225   //                           be added for each stream
00226   //             streams       Delimiter separated list of streams (if "*", =>
00227   //                           will open file and use default list of trees)
00228   //
00229   //  Contact:   S. Kasahara
00230   //
00231 
00232   std::list<std::string> filelist = this->BuildFileIndex(filepath);
00233   std::list<std::string>::iterator fileitr;
00234 
00235   std::string streamlist;
00236   std::string s(streams);
00237 
00238   for ( fileitr = filelist.begin(); fileitr != filelist.end(); fileitr++ ) {
00239     std::string filename = *fileitr;
00240     if ( s == "*" ) streamlist = BuildDefStreamList(filename);
00241     else streamlist = s;
00242 
00243     fFileStreamMap[filename] = streamlist;
00244   }
00245 
00246 }
00247 
00248 IoFileListItem::~IoFileListItem() {
00249   //
00250   //  Purpose:  Destructor
00251   //
00252   //  Contact:   S. Kasahara
00253   //
00254 
00255 }
00256 
00257 
00258 std::ostream& IoFileListItem::Print(std::ostream& os) const {
00259   //
00260   //  Purpose:  Print status of file/stream associations on ostream.
00261   //
00262   //  Contact:   S. Kasahara
00263   //
00264 
00265   FileStreamMapConstItr itr = fFileStreamMap.begin();
00266   for ( ; itr != fFileStreamMap.end(); itr++ ) {
00267     os << itr->first << "\t" << itr->second << endl;
00268   }
00269 
00270   return os;
00271 
00272 }
00273 
00274 
00275 void IoFileListItem::RemoveFile(const char* filename, const char* streams) {
00276   //
00277   //  Purpose:  Remove specified stream(s) from specified file.
00278   //            If streams = "*", remove file from list.
00279   //            If filename = "*", apply to all files.
00280   //
00281   //  Contact:   S. Kasahara
00282   //
00283 
00284   std::string f(filename);
00285   std::string s(streams);
00286 
00287   FileStreamMapItr fileItr = fFileStreamMap.end();
00288   while ( !fFileStreamMap.empty() && fileItr != fFileStreamMap.begin() ) {
00289     fileItr--;
00290     if ( f == "*" || f == (fileItr->first) ) { 
00291       if ( s == "*" ) {
00292         fFileStreamMap.erase(fileItr);  // remove file from map
00293       }
00294       else {
00295         std::vector<std::string> vrm;
00296         std::vector<std::string>::iterator vrmitr;
00297         UtilString::StringTok(vrm,streams,":,;/ ");
00298 
00299         std::string oldstreams = fileItr->second;
00300         std::vector<std::string> vold;
00301         UtilString::StringTok(vold,oldstreams,":,;/ ");
00302         std::vector<std::string>::iterator volditr = vold.end();
00303         
00304         while ( volditr !=  vold.begin() ) {
00305           volditr--;
00306           vrmitr = std::find(vrm.begin(),vrm.end(),*volditr);
00307           if ( vrmitr != vrm.end() ) vold.erase(volditr);      
00308         }
00309         if ( vold.empty() ) fFileStreamMap.erase(fileItr);
00310         else {
00311           std::string revisedstreams;
00312           for ( volditr = vold.begin(); volditr != vold.end(); volditr++ ) {
00313             if ( revisedstreams.empty() ) revisedstreams = *volditr;
00314             else revisedstreams += "," + *volditr;
00315           }
00316           fileItr->second = revisedstreams;
00317         }
00318       }
00319     }
00320   }
00321   return;
00322 
00323 }
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 

Generated on Mon Feb 15 11:06:48 2010 for loon by  doxygen 1.3.9.1