00001 #include <algorithm>
00002 #include <cstdlib>
00003
00004 #include "TSystem.h"
00005
00006 #include "FileFinder.h"
00007
00008 using namespace RootUtil;
00009 using namespace std;
00010
00011
00012 FileFinder::FileFinder()
00013 :fFirstRun(0),
00014 fLastRun(0),
00015 fRunNumberPos(0),
00016 fRunNumberLen(0),
00017 fRecursiveDepth(1),
00018 fUseIndex(false),
00019 fKeys(),
00020 fNames(),
00021 fFiles()
00022 {
00023 }
00024
00025
00026 FileFinder::~FileFinder()
00027 {
00028 }
00029
00030
00031 void FileFinder::SetKey(const string &value)
00032 {
00033 if(value.size() < 1)
00034 {
00035 cerr << "Key search substring must be non empty" << endl;
00036 return;
00037 }
00038
00039 if(find(fKeys.begin(), fKeys.end(), value) != fKeys.end())
00040 {
00041 cout << "Ignoring already existing key: " << value << endl;
00042 }
00043 fKeys.push_back(value);
00044 }
00045
00046
00047 void FileFinder::SetRunRange(const int first_run, const int last_run)
00048 {
00049 if(first_run < 1 || first_run < 1 || last_run < first_run)
00050 {
00051 cerr << "Bad run numbers range: " << first_run << " - " << last_run << endl;
00052 return;
00053 }
00054
00055 fFirstRun = first_run;
00056 fLastRun = last_run;
00057 }
00058
00059
00060 void FileFinder::SetRunPosition(const int beg_pos, const int length)
00061 {
00062 if(beg_pos < 0 || length < 0)
00063 {
00064 cerr << "Invalid position = " << beg_pos << " or length = " << length << " setting" << endl;
00065 return;
00066 }
00067
00068 fRunNumberPos = beg_pos;
00069 fRunNumberLen = length;
00070 }
00071
00072
00073 void FileFinder::SetRecursiveDepth(const short depth)
00074 {
00075 if(depth < 1 || depth > 100)
00076 {
00077 cerr << "Invalid recursive depth setting: " << depth << endl;
00078 return;
00079 }
00080 fRecursiveDepth = depth;
00081 }
00082
00083
00084 int FileFinder::Search(string path, const short depth)
00085 {
00086 int nfiles = 0;
00087
00088 void *dir_ptr = gSystem -> OpenDirectory(path.c_str());
00089 if(!dir_ptr)
00090 {
00091 return 0;
00092 }
00093
00094 cout << "Looking into directory: " << path << endl;
00095
00096 if(path.find_last_of("/") != path.size() - 1)
00097 {
00098 path += "/";
00099 }
00100
00101 const char *entry = gSystem -> GetDirEntry(dir_ptr);
00102 while(entry)
00103 {
00104 const string file_name = entry;
00105 entry = gSystem -> GetDirEntry(dir_ptr);
00106
00107 ++nfiles;
00108
00109
00110
00111 if(file_name.size() < 3) continue;
00112
00113
00114 if(depth < fRecursiveDepth)
00115 {
00116 nfiles += Search(path + file_name, depth + 1);
00117 }
00118
00119 if(!FindMatch(file_name)) continue;
00120
00121 const int run_number = GetRunNumber(file_name);
00122
00123 if(run_number > 0 && fFirstRun > 0 && fLastRun > fFirstRun)
00124 {
00125 if(run_number < fFirstRun || run_number > fLastRun)
00126 {
00127 continue;
00128 }
00129 }
00130
00131 const string full_path = path + file_name;
00132
00133 FileStat_t stat;
00134 stat.fSize = 0;
00135 if(gSystem -> GetPathInfo(full_path.c_str(), stat) != 0 || stat.fSize < 1)
00136 {
00137 continue;
00138 }
00139
00140 if(!CheckFileName(file_name, full_path))
00141 {
00142 continue;
00143 }
00144
00145 fFiles.push_back(full_path);
00146 }
00147
00148 gSystem -> FreeDirectory(dir_ptr);
00149
00150 return nfiles;
00151 }
00152
00153
00154 void FileFinder::SetIndexFile(const std::string &index_file)
00155 {
00156 ifstream infile(index_file.c_str());
00157
00158 if(!infile)
00159 {
00160 cerr << "Failed to open file " << index_file << endl;
00161 return;
00162 }
00163
00164 fUseIndex = true;
00165
00166 do
00167 {
00168 string tmp;
00169 infile >> tmp;
00170
00171 if(infile.eof()) break;
00172
00173 fIndex.push_back(tmp);
00174 } while(!infile.eof());
00175 }
00176
00177
00178 int FileFinder::GetRunNumber(const string &filename) const
00179 {
00180 if(fRunNumberLen < 1 || fRunNumberPos + fRunNumberLen > int(filename.size()) - 1)
00181 {
00182 return 0;
00183 }
00184
00185 return atoi(filename.substr(fRunNumberPos,fRunNumberLen).c_str());
00186 }
00187
00188
00189 bool FileFinder::CheckFileName(const std::string &name, const std::string &path)
00190 {
00191 if(find(fNames.begin(), fNames.end(), name) != fNames.end())
00192 {
00193 cerr << "Error: found duplicate files: " << endl;
00194 cerr << path << endl;
00195
00196 for(vector<string>::const_iterator it = fFiles.begin(); it != fFiles.end(); ++it)
00197 {
00198 if(it -> find(name) != string::npos)
00199 {
00200 cerr << *it << endl;
00201 }
00202 }
00203 return false;
00204 }
00205
00206 fNames.push_back(name);
00207 return true;
00208 }
00209
00210
00211 bool FileFinder::FindMatch(const string &filename)
00212 {
00213 if(!fUseIndex)
00214 {
00215 for(vector<string>::const_iterator it = fKeys.begin(); it != fKeys.end(); ++it)
00216 {
00217 if(filename.find(*it, 0) == string::npos) return false;
00218 }
00219 return true;
00220 }
00221
00222 if(fUseIndex)
00223 {
00224 for(vector<string>::const_iterator it = fIndex.begin(); it != fIndex.end(); ++it)
00225 {
00226 if(filename == *it) return true;
00227 }
00228 return false;
00229 }
00230
00231 return true;
00232 }
00233
00234
00235 string FileFinder::GetFile(const int index) const
00236 {
00237 if(index < 0 || index >= int(fFiles.size()))
00238 {
00239 cerr << "Index is out of range, returning empty string" << endl;
00240 return string();
00241 }
00242
00243 return fFiles[index];
00244 }
00245
00246
00247 double FileFinder::FileSize(int index) const
00248 {
00249 if(index >= 0)
00250 {
00251 const string filepath = GetFile(index);
00252 FileStat_t stat;
00253 stat.fSize = 0;
00254 if(gSystem -> GetPathInfo(filepath.c_str(), stat) == 0 && stat.fSize > 1)
00255 {
00256 return double(stat.fSize)/1048576.0;
00257 }
00258
00259 return 0.0;
00260 }
00261
00262 double size = 0.0;
00263 for(vector<string>::const_iterator it = fFiles.begin(); it != fFiles.end(); ++it)
00264 {
00265 FileStat_t stat;
00266 stat.fSize = 0;
00267
00268 const string &file = *it;
00269
00270 if(gSystem -> GetPathInfo(file.c_str(), stat) == 0 && stat.fSize > 1)
00271 {
00272 size += double(stat.fSize);
00273 }
00274 }
00275 return size/1048576.0;
00276 }
00277
00278
00279 void FileFinder::Print() const
00280 {
00281 cout << "FileFinder: printing config parameters "<< endl;
00282
00283 cout << "Recurisive depth of directory search = " << fRecursiveDepth << endl;
00284
00285 if(!fUseIndex)
00286 {
00287 cout << "Searching for files containing the following substrings " << endl;
00288 for(vector<string>::const_iterator it = fKeys.begin(); it != fKeys.end(); ++it)
00289 {
00290 cout << "Key: " << *it << endl;
00291 }
00292 }
00293 if(fUseIndex)
00294 {
00295 cout << "Searching for the following files: " << endl;
00296 for(vector<string>::const_iterator it = fIndex.begin(); it != fIndex.end(); ++it)
00297 {
00298 cout << *it;
00299 }
00300 }
00301
00302 if(fFirstRun > 0 && fLastRun > fFirstRun)
00303 {
00304 cout << "File's run number must be in the range " << fFirstRun << " - " << fLastRun << endl;
00305 cout << "In file name string run number starts at " << fRunNumberPos << " position and extends for "
00306 << fRunNumberLen << " characters" << endl;
00307 }
00308 }