#include "TSystemDirectory.h" #include "TList.h" #include #include "TString.h" #include "TObjString.h" #include "TOrdCollection.h" #include "TSystem.h" #include "TBrowser.h" #include "TFile.h" #include "TTree.h" //****************************************************************************** //****************************************************************************** // This small utility class allows to perform some operations on the file servers // with an open xrootd port. All operations go through xrootd. // // Currently present functionality allows to: // - Browse the files of a given directory with the ROOT TBrowser // - Export contents of the directory to a text file // - Print the hostnames of the machines, that contain this directory // - Validate the files in the directory // class TDirXroot: public TSystemDirectory { public: TDirXroot():TSystemDirectory(){}; TDirXroot(const char *dirname, const char *hosts, Option_t *opt="file"); TDirXroot(const char *dirname, TList *hosts); virtual ~TDirXroot(){}; Bool_t IsItDirectory(const char *name, const char *hostname) const; virtual void Browse(TBrowser *b); virtual void ExportToFile(const char *filename, const char *redir = "gsiaf.gsi.de", Option_t *opt = ""); // *MENU* virtual void PrintHosts(); // *MENU* virtual void Validate(const char *good_output, const char *bad_output, Int_t detail=0); // *MENU* private: TList *fHosts; virtual void ExportOne(const char *filename, const char *redir); ClassDef(TDirXroot, 1); }; ClassImp(TDirXroot) //______________________________________________________________________________ TDirXroot::TDirXroot(const char *dirname, const char *hosts, Option_t *opt): TSystemDirectory(dirname, dirname) { //Create an object to browse //Option "file" reads host name from file fHosts = new TList(); TString option = opt; option.ToLower(); TObjString *hostname; //TString s(100); char buf[100]; if (option.Contains("file")){ ifstream in(hosts); while (in.getline(buf, 100)){ hostname= new TObjString(); hostname->SetString(buf); //bring the hostname to the form "root://hostname// if (!(hostname->String()).BeginsWith("root://")) (hostname->String()).Prepend("root://"); if (!(hostname->String()).EndsWith("/")) (hostname->String()).Append("//"); else if (!(hostname->String()).EndsWith("//")) (hostname->String()).Append("/"); //printf("hostname=%s\n", hostname->String().Data()); fHosts->Add(hostname); } } else { //maybe some checks here later hostname = new TObjString(); hostname->SetString(hosts); fHosts->Add(hostname); } } //______________________________________________________________________________ TDirXroot::TDirXroot(const char *dirname, TList *hosts):TSystemDirectory(dirname, dirname) { //Create an object, using hostnames from the TList fHosts = new TList(); TIter next(hosts); TObjString *hostname; while ((hostname = (TObjString*)next())){ fHosts->Add(hostname); } } //______________________________________________________________________________ void TDirXroot::Browse(TBrowser *b) { // Browse OS system directories. // Collections to keep track of all browser objects that have been // generated. It's main goal is to prevent the contineous // allocations of new objects with the same names during browsing. if (!fDirsInBrowser) fDirsInBrowser = new TOrdCollection; if (!fFilesInBrowser) fFilesInBrowser = new TOrdCollection(10); const char *name = GetTitle(); //const char *name = new char[1000]; TSystemFile *sfile; TSystemDirectory *sdir; const char *file; void *dir; //gSystem->ChangeDirectory(name); if (GetName()[0] == '.' && GetName()[1] == '.') SetName(gSystem->BaseName(name)); TIter next(fHosts); TObjString *hostname; while((hostname=(TObjString*)next())){ TString s = hostname->GetString(); if (name[0]=='/') name++; if (name[0]=='/') name++; s.Append(Form("%s/",name)); dir = gSystem->OpenDirectory(s.Data()); if (!dir){ fHosts->Remove(hostname); continue; } while ((file = gSystem->GetDirEntry(dir))) { if (b->TestBit(TBrowser::kNoHidden) && file[0] == '.' && file[1] != '.' ) continue; if (IsItDirectory(file, s.Data())) { TString sdirpath; if (!strcmp(file, ".")) sdirpath = name; else if (!strcmp(file, "..")) sdirpath = gSystem->DirName(name); else { sdirpath = name; if (!sdirpath.EndsWith("/")) sdirpath += "/"; sdirpath += file; } if (!(sdir = FindDirObj(sdirpath.Data()))) { sdir = new TDirXroot(sdirpath.Data(), fHosts); fDirsInBrowser->Add(sdir); } b->Add(sdir, file); } else { if (!(sfile = FindFileObj(file, gSystem->WorkingDirectory()))) { sfile = new TSystemFile(file, s.Data()); fFilesInBrowser->Add(sfile); } char buf[200]; sprintf(buf, "%s%s", s.Data(), file); //printf("buf=%s\n", buf); b->Add(sfile, buf); } } } gSystem->FreeDirectory(dir); } //______________________________________________________________________________ Bool_t TDirXroot::IsItDirectory(const char *name, const char *hostname) const { // Check if name is a directory. Long64_t size; Long_t id, flags, modtime; Int_t len = strlen(name)+strlen(hostname)+1; char *buf = new char[len]; sprintf(buf, "%s%s", hostname, name); gSystem->GetPathInfo(buf, &id, &size, &flags, &modtime); Int_t isdir = (Int_t)flags & 2; delete [] buf; return isdir ? kTRUE : kFALSE; } //______________________________________________________________________________ void TDirXroot::ExportOne(const char *filename, const char *redir) { //Internal function - exports to a file the contents of the directory on one host ofstream of; of.open(filename, std::ios_base::app); void *dir; const char *file; const char *name = GetTitle(); TObjString *hostname = (TObjString*)fHosts->First(); if (!hostname) return; TString s = hostname->GetString(); if (name[0]=='/') name++; if (name[0]=='/') name++; s.Append(Form("%s/", name)); TString exstr; if (!strstr(redir, "root://")) exstr = "root://"; exstr.Append(Form("%s//",redir)); TDirXroot *sdir; //printf("directory full path: %s\n", s.Data()); dir = gSystem->OpenDirectory(s.Data()); if (!dir) return; // fHosts->Remove(hostname); //continue; //} while ((file = gSystem->GetDirEntry(dir))) { if (IsItDirectory(file, s.Data())) { //continue; TString sdirpath; if (!strcmp(file, ".") || !strcmp(file, "..")) continue; sdirpath = name; if (!sdirpath.EndsWith("/")) sdirpath += "/"; sdirpath += file; sdir = new TDirXroot(sdirpath.Data(), fHosts); sdir->ExportOne(filename, redir); delete sdir; } else { TString s=Form("%s%s/%s", exstr.Data(), name, file); //printf("file: %s\n", s.Data()); of<FreeDirectory(dir); of.close(); } //______________________________________________________________________________ void TDirXroot::ExportToFile(const char *filename, const char *redir, Option_t *opt) { //Print the names of all the files in this directory (and all subdirectories) into a text file //The second parameter stands for the name of the redirector, that should be added to have //the files in accesible form, i.e. to have root://redir.gsi.de//dir1/dir2/filename.root const char *name = GetTitle(); TString option = opt; option.ToLower(); ofstream of; if (option.Contains("app")) of.open(filename, std::ios_base::app); else of.open(filename); TIter next(fHosts); TObjString *hostname; TString exstr; if (!strstr(redir, "root://")) exstr = "root://"; exstr.Append(Form("%s//",redir)); TDirXroot *sdir; while((hostname=(TObjString*)next())){ //Try to open the directory on all the hosts sdir = new TDirXroot(name, hostname->GetString(), ""); sdir->ExportOne(filename, redir); delete sdir; } of.close(); } //______________________________________________________________________________ void TDirXroot::Validate(const char *good_output, const char *bad_output, Int_t detail) { //Validate the files in the directory //Names of the good files are exported to the good_output file //Names of the bad files are exported to the bad_output file //detail = 0 only performs TFile::Open() //detail > 0 - not implemented yet const char *name = GetTitle(); TIter next(fHosts); TObjString *hostname; const char *file; void *dir; TDirXroot *sdir; ofstream ofgood; ofstream ofbad; ofgood.open(good_output, std::ios_base::app); ofbad.open(bad_output, std::ios_base::app); TFile *f = 0; // TTree *tree = 0; Bool_t ok=kFALSE; while ((hostname = (TObjString*)next())){ TString s = hostname->GetString(); if (name[0]=='/') name++; if (name[0]=='/') name++; s.Append(Form("%s/", name)); //printf("directory full path: %s\n", s.Data()); dir = gSystem->OpenDirectory(s.Data()); if (!dir){ //fHosts->Remove(hostname); continue; } while ((file = gSystem->GetDirEntry(dir))) { if (IsItDirectory(file, s.Data())) { //continue; TString sdirpath; if (!strcmp(file, ".") || !strcmp(file, "..")) continue; sdirpath = name; if (!sdirpath.EndsWith("/")) sdirpath += "/"; sdirpath += file; sdir = new TDirXroot(sdirpath.Data(), fHosts); sdir->Validate(good_output, bad_output); delete sdir; sdir = 0; // b->Add(sdir, file); } else { TString sfile=Form("%s%s", s.Data(), file); //printf("validating: %s\n", sfile.Data()); f = TFile::Open(sfile.Data()); if (f) ok = kTRUE; if (detail>0){ //open the file, read the tree, blabla } if (ok){ ofgood<Close(); f=0; } else { ofbad<GetString().Data()); } }