TFileCollection.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TFileCollection.cxx 38128 2011-02-17 23:01:29Z ganis $
00002 // Author: Gerhard Erich Bruckner, Jan Fiete Grosse-Oetringhaus  04/06/07
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TFileCollection                                                      //
00015 //                                                                      //
00016 // Class that contains a list of TFileInfo's and accumulated meta       //
00017 // data information about its entries. This class is used to describe   //
00018 // file sets as stored by Grid file catalogs, by PROOF or any other     //
00019 // collection of TFile names.                                           //
00020 //                                                                      //
00021 //////////////////////////////////////////////////////////////////////////
00022 
00023 #include "TFileCollection.h"
00024 #include "THashList.h"
00025 #include "TFileInfo.h"
00026 #include "TIterator.h"
00027 #include "TMap.h"
00028 #include "TObjString.h"
00029 #include "TUri.h"
00030 #include "TUrl.h"
00031 #include "TSystem.h"
00032 #include "Riostream.h"
00033 #include "TRegexp.h"
00034 #include "TError.h"
00035 
00036 
00037 ClassImp(TFileCollection)
00038 
00039 //______________________________________________________________________________
00040 TFileCollection::TFileCollection(const char *name, const char *title,
00041                                  const char *textfile, Int_t nfiles, Int_t firstfile)
00042    : TNamed(name, title), fList(0), fMetaDataList(0), fDefaultTree(),
00043      fTotalSize(0), fNFiles(0), fNStagedFiles(0), fNCorruptFiles(0)
00044 {
00045    // TFileCollection constructor. Specify a name and title describing
00046    // the list. If textfile is specified the file is opened and a
00047    // TFileCollection is created containing the files in the textfile.
00048 
00049    fList = new THashList();
00050    fList->SetOwner();
00051 
00052    fMetaDataList = new TList;
00053    fMetaDataList->SetOwner();
00054 
00055    AddFromFile(textfile, nfiles, firstfile);
00056 }
00057 
00058 //______________________________________________________________________________
00059 TFileCollection::~TFileCollection()
00060 {
00061    // Cleanup.
00062 
00063    delete fList;
00064    delete fMetaDataList;
00065 }
00066 
00067 //______________________________________________________________________________
00068 Int_t TFileCollection::Add(TFileInfo *info)
00069 {
00070    // Add TFileInfo to the collection.
00071 
00072    if (fList && info) {
00073       if (!fList->FindObject(info->GetName())) {
00074          fList->Add(info);
00075          return 1;
00076       } else {
00077          Warning("Add", "file: '%s' already in the list - ignoring",
00078                         info->GetCurrentUrl()->GetUrl());
00079       }
00080    }
00081    return 0;
00082 }
00083 
00084 //______________________________________________________________________________
00085 Int_t TFileCollection::Add(TFileCollection *coll)
00086 {
00087    // Add content of the TFileCollection to this collection.
00088 
00089    if (fList && coll && coll->GetList()) {
00090       TIter nxfi(coll->GetList());
00091       TFileInfo *fi = 0;
00092       while ((fi = (TFileInfo *) nxfi())) {
00093          fList->Add(new TFileInfo(*fi));
00094       }
00095       return 1;
00096    } else {
00097       return 0;
00098    }
00099 }
00100 
00101 //______________________________________________________________________________
00102 Int_t TFileCollection::AddFromFile(const char *textfile, Int_t nfiles, Int_t firstfile)
00103 {
00104    // Add file names contained in the specified text file.
00105    // The file should contain one url per line; empty lines or lines starting with '#'
00106    // (commented lines) are ignored.
00107    // If nfiles > 0 only nfiles files are added, starting from file 'firstfile' (>= 1).
00108    // The method returns the number of added files.
00109 
00110    if (!fList)
00111      return 0;
00112 
00113    Int_t nf = 0;
00114    TString fn(textfile);
00115    if (!fn.IsNull() && !gSystem->ExpandPathName(fn)) {
00116       ifstream f;
00117       f.open(fn);
00118       if (f.is_open()) {
00119          Bool_t all = (nfiles <= 0) ? kTRUE : kFALSE;
00120          Int_t ff = (!all && (firstfile < 1)) ? 1 : firstfile;
00121          Int_t nn = 0;
00122          while (f.good() && (all || nf < nfiles)) {
00123             TString line;
00124             line.ReadToDelim(f);
00125             // Skip commented or empty lines
00126             if (!line.IsWhitespace() && !line.BeginsWith("#")) {
00127                nn++;
00128                if (all || nn >= ff) {
00129                   fList->Add(new TFileInfo(line));
00130                   nf++;
00131                }
00132             }
00133          }
00134          f.close();
00135          Update();
00136       } else
00137          Error("AddFromFile", "unable to open file %s (%s)", textfile, fn.Data());
00138    }
00139    return nf;
00140 }
00141 
00142 //______________________________________________________________________________
00143 Int_t TFileCollection::Add(const char *dir)
00144 {
00145    // Add all files matching the specified pattern to the collection.
00146    // 'dir' can include wildcards after the last slash, which causes all
00147    // matching files in that directory to be added.
00148    // If dir is the full path of a file, only one element is added.
00149    // Return value is the number of added files.
00150 
00151    Int_t nf = 0;
00152 
00153    if (!fList)
00154       return nf;
00155 
00156    if (!dir || !*dir) {
00157       Error("Add", "input dir undefined");
00158       return nf;
00159    }
00160 
00161    FileStat_t st;
00162    FileStat_t tmp;
00163    TString baseDir = gSystem->DirName(dir);
00164    // if the 'dir' or its base dir exist
00165    if (gSystem->GetPathInfo(dir, st) == 0 ||
00166        gSystem->GetPathInfo(baseDir, tmp) == 0) {
00167       // If 'dir' points to a single file, add to the list and exit
00168       if (R_ISREG(st.fMode)) {
00169          // regular, single file
00170          TFileInfo *info = new TFileInfo(dir);
00171          info->SetBit(TFileInfo::kStaged);
00172          Add(info);
00173          nf++;
00174          Update();
00175          return nf;
00176       } else {
00177          void *dataSetDir = gSystem->OpenDirectory(gSystem->DirName(dir));
00178          if (!dataSetDir) {
00179             // directory cannot be opened
00180             Error("Add", "directory %s cannot be opened",
00181                   gSystem->DirName(dir));
00182          } else {
00183             const char *ent;
00184             TString filesExp(TString("^") + gSystem->BaseName(dir) + "$");
00185             filesExp.ReplaceAll("*",".*");
00186             TRegexp rg(filesExp);
00187             while ((ent = gSystem->GetDirEntry(dataSetDir))) {
00188                TString entryString(ent);
00189                if (entryString.Index(rg) != kNPOS) {
00190                   // matching dir entry
00191                   TString fn = gSystem->DirName(dir);
00192                   fn += "/";
00193                   fn += ent;
00194                   gSystem->GetPathInfo(fn, st);
00195                   if (R_ISREG(st.fMode)) {
00196                      // regular file
00197                      TFileInfo *info = new TFileInfo(fn);
00198                      info->SetBit(TFileInfo::kStaged);
00199                      Add(info);
00200                      nf++;
00201                   }
00202                }
00203             }
00204             // close the directory
00205             gSystem->FreeDirectory(dataSetDir);
00206             Update();
00207          }
00208       }
00209    }
00210    return nf;
00211 }
00212 
00213 //______________________________________________________________________________
00214 Int_t TFileCollection::RemoveDuplicates()
00215 {
00216    // Remove duplicates based on the UUID, typically after a verification.
00217    // Return the number of entries removed.
00218 
00219    THashList *hl = new THashList;
00220    hl->SetOwner();
00221 
00222    Int_t n0 = fList->GetSize();
00223    TIter nxfi(fList);
00224    TFileInfo *fi = 0;
00225    while ((fi = (TFileInfo *)nxfi())) {
00226       if (!(hl->FindObject(fi->GetUUID()->AsString()))) {
00227          // We hash on the UUID
00228          fList->Remove(fi);
00229          fi->SetName(fi->GetUUID()->AsString());
00230          hl->Add(fi);
00231       }
00232    }
00233    delete fList;
00234    fList = hl;
00235    // How many removed?
00236    Int_t nr = n0 - fList->GetSize();
00237    if (nr > 0)
00238       Info("RemoveDuplicates", "%d duplicates found and removed", nr);
00239    // Done
00240    return nr;
00241 }
00242 
00243 //______________________________________________________________________________
00244 TFileCollection *TFileCollection::GetStagedSubset()
00245 {
00246    // Creates a subset of the files that have the kStaged & !kCorrupted bit set.
00247 
00248    if (!fList)
00249      return 0;
00250 
00251    TFileCollection *subset = new TFileCollection(GetName(), GetTitle());
00252 
00253    TIter iter(fList);
00254    TFileInfo *fileInfo = 0;
00255    while ((fileInfo = dynamic_cast<TFileInfo*>(iter.Next()))) {
00256       if (fileInfo->TestBit(TFileInfo::kStaged) && !fileInfo->TestBit(TFileInfo::kCorrupted))
00257          subset->Add(fileInfo);
00258    }
00259 
00260    subset->Update();
00261 
00262    return subset;
00263 }
00264 
00265 //______________________________________________________________________________
00266 Long64_t TFileCollection::Merge(TCollection *li) 
00267 {
00268    //merge all TFileCollection objects in li into this TFileCollection object
00269         
00270    if (!li) return 0;
00271    if (li->IsEmpty()) return 0;
00272 
00273    // We don't want to add the clone to gDirectory,
00274    // so remove our kMustCleanup bit temporarily
00275    Bool_t mustCleanup = TestBit(kMustCleanup);
00276    if (mustCleanup) ResetBit(kMustCleanup);
00277    TList inlist;
00278    TFileCollection* hclone = (TFileCollection*)Clone("FirstClone");
00279    if (mustCleanup) SetBit(kMustCleanup);
00280    R__ASSERT(hclone);
00281 //    BufferEmpty(1);         // To remove buffer.
00282 //    Reset();                // BufferEmpty sets limits so we can't use it later.
00283    inlist.Add(hclone);
00284    inlist.AddAll(li);
00285 
00286    Long64_t nentries=0;
00287    TIter next(&inlist);
00288    while (TObject *o = next()) {
00289       TFileCollection* coll = dynamic_cast<TFileCollection*> (o);
00290       if (!coll) {
00291          Error("Add","Attempt to add object of class: %s to a %s",
00292             o->ClassName(),this->ClassName());
00293          return -1;
00294       }
00295       Add(coll);
00296       nentries++;
00297    }
00298          
00299    //copy merged stats
00300    inlist.Remove(hclone);
00301    delete hclone;
00302    return nentries;
00303         
00304 }
00305 
00306 //______________________________________________________________________________
00307 Int_t TFileCollection::Update(Long64_t avgsize)
00308 {
00309    // Update accumulated information about the elements of the collection
00310    // (e.g. fTotalSize). If 'avgsize' > 0, use an average file size of 'avgsize'
00311    // bytes when the size info is not available.
00312    // Also updates the meta data information by summarizing
00313    // the meta data of the contained objects.
00314    // Return -1 in case of any failure, 0 if the total size is exact, 1 if
00315    // incomplete, 2 if complete but (at least partially) estimated.
00316 
00317    if (!fList)
00318      return -1;
00319 
00320    Int_t rc = 0;
00321 
00322    fTotalSize = 0;
00323    fNStagedFiles = 0;
00324    fNCorruptFiles = 0;
00325 
00326    // Clear internal meta information which is going to be rebuilt in this
00327    // function
00328    TIter nxm(fMetaDataList);
00329    TFileInfoMeta *m = 0;
00330    while ((m = (TFileInfoMeta *)nxm())) {
00331       if (!(m->TestBit(TFileInfoMeta::kExternal))) {
00332          fMetaDataList->Remove(m);
00333          delete m;
00334       }
00335    }
00336 
00337    fNFiles = fList->GetEntries();
00338 
00339    TIter iter(fList);
00340    TFileInfo *fileInfo = 0;
00341    while ((fileInfo = dynamic_cast<TFileInfo*> (iter.Next()))) {
00342 
00343       if (fileInfo->GetSize() > 0) {
00344          fTotalSize += fileInfo->GetSize();
00345       } else {
00346          rc = 1;
00347          if (avgsize > 0) {
00348             rc = 2;
00349             fTotalSize += avgsize;
00350          }
00351       }
00352 
00353       if (fileInfo->TestBit(TFileInfo::kStaged) && !fileInfo->TestBit(TFileInfo::kCorrupted)) {
00354          fNStagedFiles++;
00355 
00356          if (fileInfo->GetMetaDataList()) {
00357             TIter metaDataIter(fileInfo->GetMetaDataList());
00358             // other than TFileInfoMeta is also allowed in list
00359             TObject *obj = 0;
00360             while ((obj = metaDataIter.Next())) {
00361                TFileInfoMeta *metaData = dynamic_cast<TFileInfoMeta*>(obj);
00362                if (!metaData)
00363                   continue;
00364                if (!metaData->IsTree())
00365                   continue;
00366 
00367                // find corresponding entry in TFileCollection's meta data
00368                TFileInfoMeta *metaDataSum = dynamic_cast<TFileInfoMeta*>(fMetaDataList->FindObject(metaData->GetName()));
00369                Bool_t newObj = kFALSE;
00370                if (!metaDataSum) {
00371                   // create explicitly, there are some values that do not make sense for the sum
00372                   metaDataSum = new TFileInfoMeta(metaData->GetName(), metaData->GetTitle());
00373                   fMetaDataList->Add(metaDataSum);
00374                   newObj = kTRUE;
00375                }
00376 
00377                // sum the values
00378                if (newObj)
00379                   metaDataSum->SetEntries(metaData->GetEntries());
00380                else
00381                   metaDataSum->SetEntries(metaDataSum->GetEntries() + metaData->GetEntries());
00382             }
00383          }
00384       }
00385       if (fileInfo->TestBit(TFileInfo::kCorrupted))
00386          fNCorruptFiles++;
00387    }
00388 
00389    // Done
00390    return rc;
00391 }
00392 
00393 //______________________________________________________________________________
00394 void TFileCollection::Print(Option_t *option) const
00395 {
00396    // Prints the contents of the TFileCollection.
00397    // If option contains:
00398    //      'M'             print global meta information
00399    //      'F'             print all the files in the collection in compact form
00400    //                      (current url, default tree name|class|entries, md5)
00401    //      'L'             together with 'F', print all the files in the collection
00402    //                      in long form (uuid, md5, all URLs, all meta objects; on
00403    //                      many lines)
00404 
00405    Printf("TFileCollection %s - %s contains: %lld files with a size of"
00406           " %lld bytes, %.1f %% staged - default tree name: '%s'",
00407           GetName(), GetTitle(), fNFiles, fTotalSize, GetStagedPercentage(),
00408           GetDefaultTreeName());
00409 
00410    TString opt(option);
00411    if (opt.Contains("M", TString::kIgnoreCase)) {
00412       Printf("The files contain the following trees:");
00413 
00414       TIter metaDataIter(fMetaDataList);
00415       TFileInfoMeta* metaData = 0;
00416       while ((metaData = dynamic_cast<TFileInfoMeta*>(metaDataIter.Next()))) {
00417          if (!metaData->IsTree())
00418             continue;
00419 
00420          Printf("Tree %s: %lld events", metaData->GetName(), metaData->GetEntries());
00421       }
00422    }
00423 
00424    if (fList && opt.Contains("F", TString::kIgnoreCase)) {
00425       Printf("The collection contains the following files:");
00426       if (!opt.Contains("L") && !fDefaultTree.IsNull())
00427          opt += TString::Format(" T:%s", fDefaultTree.Data());
00428       fList->Print(opt);
00429    }
00430 }
00431 
00432 //______________________________________________________________________________
00433 void TFileCollection::SetAnchor(const char *anchor)
00434 {
00435    // Calls TUrl::SetAnchor() for all URLs contained in all TFileInfos.
00436 
00437    if (!fList)
00438      return;
00439 
00440    TIter iter(fList);
00441    TFileInfo *fileInfo = 0;
00442    while ((fileInfo = dynamic_cast<TFileInfo*>(iter.Next()))) {
00443       fileInfo->ResetUrl();
00444       TUrl *url = 0;
00445       while ((url = fileInfo->NextUrl()))
00446          url->SetAnchor(anchor);
00447       fileInfo->ResetUrl();
00448    }
00449 }
00450 
00451 //______________________________________________________________________________
00452 void TFileCollection::SetBitAll(UInt_t f)
00453 {
00454    // Set the bit for all TFileInfos
00455 
00456    if (!fList)
00457      return;
00458 
00459    TIter iter(fList);
00460    TFileInfo *fileInfo = 0;
00461    while ((fileInfo = dynamic_cast<TFileInfo*>(iter.Next())))
00462       fileInfo->SetBit(f);
00463 }
00464 
00465 //______________________________________________________________________________
00466 void TFileCollection::ResetBitAll(UInt_t f)
00467 {
00468    // Reset the bit for all TFileInfos
00469 
00470    if (!fList)
00471      return;
00472 
00473    TIter iter(fList);
00474    TFileInfo *fileInfo = 0;
00475    while ((fileInfo = dynamic_cast<TFileInfo*>(iter.Next())))
00476       fileInfo->ResetBit(f);
00477 }
00478 
00479 //______________________________________________________________________________
00480 const char *TFileCollection::GetDefaultTreeName() const
00481 {
00482    // Returns the tree set with SetDefaultTreeName if set
00483    // Returns the name of the first tree in the meta data list.
00484    // Returns 0 in case no trees are found in the meta data list.
00485 
00486    if (fDefaultTree.Length() > 0)
00487      return fDefaultTree;
00488 
00489    TIter metaDataIter(fMetaDataList);
00490    TFileInfoMeta *metaData = 0;
00491    while ((metaData = dynamic_cast<TFileInfoMeta*>(metaDataIter.Next()))) {
00492       if (!metaData->IsTree())
00493          continue;
00494       return metaData->GetName();
00495    }
00496    return 0;
00497 }
00498 
00499 //______________________________________________________________________________
00500 Long64_t TFileCollection::GetTotalEntries(const char *tree) const
00501 {
00502    // Returns the number of entries for the specified tree (retrieved from meta data).
00503    // If tree is not specified, use the default tree name.
00504    // Returns -1 in case the specified tree is not found.
00505 
00506    if (!tree || !*tree) {
00507       tree = GetDefaultTreeName();
00508       if (!tree)
00509          return -1;
00510    }
00511 
00512    TFileInfoMeta *metaData = dynamic_cast<TFileInfoMeta*>(fMetaDataList->FindObject(tree));
00513    if (!metaData)
00514       return -1;
00515 
00516    return metaData->GetEntries();
00517 }
00518 
00519 //______________________________________________________________________________
00520 TFileInfoMeta *TFileCollection::GetMetaData(const char *meta) const
00521 {
00522    // Returns the meta data object with the soecified meta name.
00523    // Returns 0 in case specified meta data is not found.
00524 
00525    if (!meta || !*meta)
00526       return 0;
00527 
00528    return dynamic_cast<TFileInfoMeta*>(fMetaDataList->FindObject(meta));
00529 }
00530 
00531 //______________________________________________________________________________
00532 void TFileCollection::SetDefaultMetaData(const char *meta)
00533 {
00534    // Moves the indicated meta data in the first position, so that
00535    // it becomes efectively the default.
00536 
00537    TFileInfoMeta *fim = GetMetaData(meta);
00538    if (fim) {
00539       fMetaDataList->Remove(fim);
00540       fMetaDataList->AddFirst(fim);
00541    }
00542 }
00543 
00544 //______________________________________________________________________________
00545 void TFileCollection::RemoveMetaData(const char *meta)
00546 {
00547    // Removes the indicated meta data object in all TFileInfos and this object
00548    // If no name is given all metadata is removed
00549 
00550    if (fList) {
00551       TIter iter(fList);
00552       TFileInfo *fileInfo = 0;
00553       while ((fileInfo = dynamic_cast<TFileInfo*>(iter.Next())))
00554          fileInfo->RemoveMetaData(meta);
00555    }
00556 
00557    if (meta) {
00558       TObject* obj = fMetaDataList->FindObject("meta");
00559       if (obj) {
00560          fMetaDataList->Remove(obj);
00561          delete obj;
00562       }
00563    } else
00564       fMetaDataList->Clear();
00565 }
00566 
00567 //______________________________________________________________________________
00568 void TFileCollection::Sort()
00569 {
00570    // Sort the collection.
00571 
00572    if (!fList)
00573      return;
00574 
00575    fList->Sort();
00576 }
00577 
00578 //______________________________________________________________________________
00579 TObjString *TFileCollection::ExportInfo(const char *name, Int_t popt)
00580 {
00581    // Export the relevant info as a string; use 'name' as collection name,
00582    // if defined, else use GetName().
00583    // The output object must be destroyed by the caller
00584 
00585    TString treeInfo;
00586    if (GetDefaultTreeName()) {
00587       TFileInfoMeta* meta = GetMetaData(GetDefaultTreeName());
00588       if (popt == 1) {
00589          treeInfo = GetDefaultTreeName();
00590          if (meta)
00591             treeInfo += TString::Format(", %lld entries", meta->GetEntries());
00592          TFileInfoMeta *frac = GetMetaData("/FractionOfTotal");
00593          if (frac)
00594             treeInfo += TString::Format(", %3.1f %% of total", frac->GetEntries() / 10.);
00595       } else {
00596          treeInfo.Form(" %s ", GetDefaultTreeName());
00597          if (treeInfo.Length() > 14) treeInfo.Replace(13, 1, '>');
00598          treeInfo.Resize(14);
00599          if (meta) {
00600             if (meta->GetEntries() > 99999999) {
00601                treeInfo += TString::Format("| %8lld ", meta->GetEntries());
00602             } else {
00603                treeInfo += TString::Format("| %8.4g ", (Double_t) meta->GetEntries());
00604             }
00605          }
00606       }
00607    } else {
00608       treeInfo = "        N/A";
00609    }
00610    if (popt == 0) treeInfo.Resize(25);
00611 
00612    // Renormalize the size to kB, MB or GB
00613    const char *unit[4] = {"kB", "MB", "GB", "TB"};
00614    Int_t k = 0;
00615    Long64_t refsz = 1024;
00616    Long64_t xsz = (Long64_t) (GetTotalSize() / refsz);
00617    while (xsz > 1024 && k < 3) {
00618       k++;
00619       refsz *= 1024;
00620       xsz = (Long64_t) (GetTotalSize() / refsz);
00621    }
00622 
00623    // The name
00624    TString dsname(name);
00625    if (dsname.IsNull()) dsname = GetName();
00626 
00627    // Create the output string
00628    TObjString *outs = 0;
00629    if (popt == 1) {
00630       outs = new TObjString(Form("%s %lld files, %lld %s, staged %d %%, tree: %s", dsname.Data(),
00631                                  GetNFiles(), xsz, unit[k],
00632                                  (Int_t)GetStagedPercentage(), treeInfo.Data()));
00633    } else {
00634       outs = new TObjString(Form("%s| %7lld |%s| %5lld %s |  %3d %%", dsname.Data(),
00635                                  GetNFiles(), treeInfo.Data(), xsz, unit[k],
00636                                  (Int_t)GetStagedPercentage()));
00637    }
00638    // Done
00639    return outs;
00640 }
00641 
00642 //______________________________________________________________________________
00643 TFileCollection *TFileCollection::GetFilesOnServer(const char *server)
00644 {
00645    // Return the subset of files served by 'server'. The sysntax for 'server' is
00646    // the standard URI one, i.e. [<scheme>://]<host>[:port]
00647 
00648    TFileCollection *fc = (TFileCollection *)0;
00649 
00650    // Server specification is mandatory
00651    if (!server || strlen(server) <= 0) {
00652       Info("GetFilesOnServer", "server undefined - do nothing");
00653       return fc;
00654    }
00655 
00656    // Nothing to do for empty lists
00657    if (!fList || fList->GetSize() <= 0) {
00658       Info("GetFilesOnServer", "the list is empty - do nothing");
00659       return fc;
00660    }
00661 
00662    // Define the server reference string
00663    TUri uri(server);
00664    TString srv, scheme("root"), port;
00665    if (uri.GetScheme() != "") scheme = uri.GetScheme();
00666    if (uri.GetPort() != "") port.Form(":%s", uri.GetPort().Data());
00667    srv.Form("%s://%s%s", scheme.Data(), TUrl(server).GetHostFQDN(), port.Data());
00668    if (gDebug > 0)
00669       Info("GetFilesOnServer", "searching for files on server: '%s' (input: '%s')", srv.Data(), server);
00670 
00671    // Prepare the output
00672    fc = new TFileCollection(GetName());
00673    TString title;
00674    if (GetTitle() && strlen(GetTitle()) > 0) {
00675       title.Form("%s (subset on server %s)", GetTitle(), srv.Data());
00676    } else {
00677       title.Form("subset of '%s' on server %s", GetName(), srv.Data());
00678    }
00679    fc->SetTitle(title.Data());
00680    // The default tree name
00681    fc->SetDefaultTreeName(GetDefaultTreeName());
00682 
00683    // We look for URL starting with srv
00684    srv.Insert(0, "^");
00685 
00686    // Go through the list
00687    TIter nxf(fList);
00688    TFileInfo *fi = 0;
00689    while ((fi = (TFileInfo *)nxf())) {
00690       TUrl *xu = 0;
00691       if ((xu = fi->FindByUrl(srv.Data()))) {
00692          // Create a new TFileInfo object
00693          TFileInfo *nfi = new TFileInfo(xu->GetUrl(), fi->GetSize(),
00694                                         fi->GetUUID() ? fi->GetUUID()->AsString() : 0,
00695                                         fi->GetMD5() ? fi->GetMD5()->AsString() : 0);
00696          if (fi->GetMetaDataList()) {
00697             TIter nxm(fi->GetMetaDataList());
00698             TFileInfoMeta *md = 0;
00699             while ((md = (TFileInfoMeta *) nxm())) {
00700                nfi->AddMetaData(new TFileInfoMeta(*md));
00701             }
00702          }
00703          if (fi->TestBit(TFileInfo::kStaged)) nfi->SetBit(TFileInfo::kStaged);
00704          if (fi->TestBit(TFileInfo::kCorrupted)) nfi->SetBit(TFileInfo::kCorrupted);
00705          if (gDebug > 1)
00706             Info("GetFilesOnServer", "adding: %s", xu->GetUrl());
00707          fc->Add(nfi);
00708       }
00709    }
00710 
00711    // If nothing found, delete the object
00712    if (fc->GetList()->GetSize() <= 0) {
00713       delete fc;
00714       fc = 0;
00715       Info("GetFilesOnServer", "dataset '%s' has no files on server: '%s' (searched for: '%s')",
00716                                GetName(), server, srv.Data());
00717    }
00718 
00719    // Fill up sums on the sub file collection
00720    if (fc) {
00721       fc->Update();
00722       // Fraction of total in permille
00723       Long64_t xf = (fc->GetTotalSize() * 1000) / GetTotalSize();
00724       TFileInfoMeta *m = new TFileInfoMeta("FractionOfTotal", "External Info", xf);
00725       m->SetBit(TFileInfoMeta::kExternal);
00726       fc->AddMetaData(m);
00727    }
00728 
00729    // Done
00730    return fc;
00731 }
00732 
00733 //______________________________________________________________________________
00734 TMap *TFileCollection::GetFilesPerServer(const char *exclude)
00735 {
00736    // Return a map of TFileCollections with the files on each data server,
00737    // excluding servers in the comma-separated list 'exclude'
00738 
00739    TMap *dsmap = 0;
00740 
00741    // Nothing to do for empty lists
00742    if (!fList || fList->GetSize() <= 0) {
00743       Info("GetFilesPerServer", "the list is empty - do nothing");
00744       return dsmap;
00745    }
00746 
00747    // List of servers to be ignored
00748    THashList *excl = 0;
00749    if (exclude && strlen(exclude) > 0) {
00750       excl = new THashList;
00751       excl->SetOwner();
00752       TUri uri;
00753       TString srvs(exclude), s, srv, scheme, port;
00754       Int_t from = 0;
00755       while (srvs.Tokenize(s, from, ",")) {
00756          uri.SetUri(s.Data());
00757          scheme = "root";
00758          port = "";
00759          if (uri.GetScheme() != "") scheme = uri.GetScheme();
00760          if (uri.GetPort() != "") port.Form(":%s", uri.GetPort().Data());
00761          srv.Form("%s://%s%s", scheme.Data(), TUrl(s.Data()).GetHostFQDN(), port.Data());
00762          // Add
00763          excl->Add(new TObjString(srv.Data()));
00764       }
00765    }
00766 
00767    // Prepare the output
00768    dsmap = new TMap();
00769 
00770    // Go through the list
00771    TIter nxf(fList);
00772    TFileInfo *fi = 0;
00773    TUri uri;
00774    TString key;
00775    TFileCollection *fc = 0;
00776    while ((fi = (TFileInfo *)nxf())) {
00777       // Save current URL
00778       TUrl *curl = fi->GetCurrentUrl();
00779       // Loop over URLs
00780       fi->ResetUrl();
00781       TUrl *xurl = 0;
00782       while ((xurl = fi->NextUrl())) {
00783          // Find the key for this server
00784          key.Form("%s://%s", xurl->GetProtocol(), xurl->GetHostFQDN());
00785          // Check if this has to be ignored
00786          if (excl && excl->FindObject(key.Data())) continue;
00787          // Complete the key, if needed, and recheck
00788          if (xurl->GetPort() > 0) {
00789             key += TString::Format(":%d", xurl->GetPort());
00790             if (excl && excl->FindObject(key.Data())) continue;
00791          }
00792          // Get the map entry for this key
00793          TPair *ent = 0;
00794          if (!(ent = (TPair *) dsmap->FindObject(key.Data()))) {
00795             // Create the TFileCollection
00796             fc = new TFileCollection(GetName());
00797             TString title;
00798             if (GetTitle() && strlen(GetTitle()) > 0) {
00799                title.Form("%s (subset on server %s)", GetTitle(), key.Data());
00800             } else {
00801                title.Form("subset of '%s' on server %s", GetName(), key.Data());
00802             }
00803             fc->SetTitle(title.Data());
00804             // The default tree name
00805             fc->SetDefaultTreeName(GetDefaultTreeName());
00806             // Add it to the map
00807             dsmap->Add(new TObjString(key.Data()), fc);
00808             // Notify
00809             if (gDebug > 0)
00810                Info("GetFilesPerServer", "found server: '%s' (fc: %p)", key.Data(), fc);
00811          } else {
00812             // Attach to the TFileCollection
00813             fc = (TFileCollection *) ent->Value();
00814          }
00815          // Create a new TFileInfo object
00816          TFileInfo *nfi = new TFileInfo(xurl->GetUrl(kTRUE), fi->GetSize(),
00817                                         fi->GetUUID() ? fi->GetUUID()->AsString() : 0,
00818                                         fi->GetMD5() ? fi->GetMD5()->AsString() : 0);
00819          if (fi->GetMetaDataList()) {
00820             TIter nxm(fi->GetMetaDataList());
00821             TFileInfoMeta *md = 0;
00822             while ((md = (TFileInfoMeta *) nxm())) {
00823                nfi->AddMetaData(new TFileInfoMeta(*md));
00824             }
00825          }
00826          if (fi->TestBit(TFileInfo::kStaged)) nfi->SetBit(TFileInfo::kStaged);
00827          if (fi->TestBit(TFileInfo::kCorrupted)) nfi->SetBit(TFileInfo::kCorrupted);
00828          fc->Add(nfi);
00829       }
00830       // Restore current URL
00831       fi->SetCurrentUrl(curl);
00832    }
00833 
00834    // Fill up sums on the sub file collections
00835    TIter nxk(dsmap);
00836    TObject *k = 0;
00837    while ((k = nxk()) && (fc = (TFileCollection *) dsmap->GetValue(k))) {
00838       fc->Update();
00839       // Fraction of total in permille
00840       Long64_t xf = (fc->GetTotalSize() * 1000) / GetTotalSize();
00841       TFileInfoMeta *m = new TFileInfoMeta("FractionOfTotal", "External Info", xf);
00842       m->SetBit(TFileInfoMeta::kExternal);
00843       fc->AddMetaData(m);
00844    }
00845 
00846    // Cleanup
00847    if (excl) delete excl;
00848 
00849    // Done
00850    return dsmap;
00851 }
00852 
00853 //______________________________________________________________________________
00854 Bool_t TFileCollection::AddMetaData(TObject *meta)
00855 {
00856    // Add's a meta data object to the file collection object. The object will be
00857    // adopted by the TFileCollection and should not be deleted by the user.
00858    // Typically objects of class TFileInfoMeta or derivatives should be added,
00859    // but any class is accepted.
00860    // NB : a call to TFileCollection::Update will remove these objects unless the
00861    //      bit TFileInfoMeta::kExternal is set.
00862    // Returns kTRUE if successful, kFALSE otherwise.
00863 
00864    if (meta) {
00865       if (!fMetaDataList) {
00866          fMetaDataList = new TList;
00867          fMetaDataList->SetOwner();
00868       }
00869       fMetaDataList->Add(meta);
00870       return kTRUE;
00871    }
00872    return kFALSE;
00873 }

Generated on Tue Jul 5 14:11:20 2011 for ROOT_528-00b_version by  doxygen 1.5.1