pq2actions.cxx

Go to the documentation of this file.
00001 // @(#)root/proof:$Id: pq2actions.cxx 36015 2010-10-01 13:54:46Z ganis $
00002 // Author: G. Ganis, Mar 2010
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 // *                        p q 2 a c t i o n s                            * //
00015 // *                                                                       * //
00016 // * This file implements the action functions used in PQ2                 * //
00017 // *                                                                       * //
00018 // ************************************************************************* //
00019 
00020 #include <errno.h>
00021 
00022 #include "pq2actions.h"
00023 #include "pq2wrappers.h"
00024 #include "redirguard.h"
00025 
00026 #include "TFile.h"
00027 #include "TFileCollection.h"
00028 #include "TFileInfo.h"
00029 #include "THashList.h"
00030 #include "TH1D.h"
00031 #include "TParameter.h"
00032 #include "TRegexp.h"
00033 #include "TString.h"
00034 #include "TSystem.h"
00035 
00036 // Global variables defined by other PQ2 components
00037 extern TString flog;
00038 extern TString ferr;
00039 extern TString fres;
00040 extern Int_t gverbose;
00041 
00042 // Local globals
00043 static const char *glabMet[] = { "#files", "size" };
00044 THashList gProtoPortMap;
00045 // Local functions
00046 int do_anadist_ds(TFileCollection *fc, const char *newsrvs = 0, const char *ignsrvs = 0,
00047                   const char *excsrvs = 0, int met = 0, const char *fnout = 0,
00048                   TList *distinfo = 0, const char *outfile = 0, const char *infile = 0);
00049 void do_anadist_getkey(const char *p, TString &key);
00050 void do_anadist_getkey(TUrl *u, TString &key);
00051 
00052 // Usefule macros
00053 #define SDELTWO(x,y)  { SafeDelete(x); SafeDelete(y); }
00054 #define SDELTRE(x,y,z)  { SafeDelete(x); SafeDelete(y); SafeDelete(z); }
00055 #define SDELETE(x,y,z,w,t)  { SafeDelete(x); SafeDelete(y); SafeDelete(z); SafeDelete(w); SafeDelete(t); }
00056 
00057 //_______________________________________________________________________________________
00058 void do_cache(bool clear, const char *ds)
00059 {
00060    // Execute 'cache'
00061 
00062    // Show / Clear the cache
00063    DataSetCache(clear, ds);
00064    // Remove the error file
00065    gSystem->Unlink(ferr.Data());
00066 }
00067 
00068 //_______________________________________________________________________________________
00069 void do_ls(const char *ds, const char *opt)
00070 {
00071    // Execute 'ls'
00072 
00073    // List the data sets
00074    ShowDataSets(ds, opt);
00075    // Remove the error file
00076    gSystem->Unlink(ferr.Data());
00077 }
00078 
00079 //_______________________________________________________________________________________
00080 void do_ls_files_server(const char *ds, const char *server)
00081 {
00082    // Execute 'ls-files'
00083 
00084    const char *action = (server && strlen(server) > 0) ? "pq2-ls-files-server" : "pq2-ls-files";
00085 
00086    // We need to scan all the datasets to find the matching ones ...
00087    TFileCollection *fc = 0;
00088    { redirguard rog(flog.Data(), "a", gverbose);
00089       if (server && strlen(server) > 0) {
00090          fc = GetDataSet(ds, server);
00091       } else {
00092          fc = GetDataSet(ds);
00093       }
00094    }
00095    if (!fc) {
00096       // Notify
00097       gSystem->Rename(flog.Data(), ferr.Data());
00098       Printf("%s: ERROR: problems retrieving info about dataset '%s'", action, ds);
00099       return;
00100    }
00101 
00102    // Overall info
00103    if (server && strlen(server) > 0) {
00104       Printf("%s: dataset '%s' has %d files on server: %s",
00105                                               action, ds, fc->GetList()->GetSize(), server);
00106    } else {
00107       Printf("%s: dataset '%s' has %d files", action, ds, fc->GetList()->GetSize());
00108    }
00109 
00110    // Header
00111    TString num("      #   ");
00112    TString nam("File"); nam.Resize(80);
00113    TString siz("        Size");
00114    TString met("#Objs Obj|Type|Entries, ...");
00115    TString header;
00116    header.Form("%s%s%s   %s", num.Data(), nam.Data(), siz.Data(), met.Data());
00117 
00118    // Iterate
00119    const char *unit[4] = {"kB", "MB", "GB", "TB"};
00120    TString uu, meta, name;
00121    TIter nxf(fc->GetList());
00122    TFileInfo *fi = 0;
00123    Int_t nf = 0;
00124    while ((fi = (TFileInfo *) nxf())) {
00125       nf++;
00126       if (nf == 1)
00127          Printf("%s:%s", action, header.Data());
00128       // URL
00129       uu = fi->GetCurrentUrl()->GetUrl();
00130       if (uu.Length() < 80) uu.Resize(80);
00131       // Size renormalize to kB, MB or GB
00132       Int_t k = 0;
00133       Long64_t refsz = 1024;
00134       Long64_t xsz = (Long64_t) (fi->GetSize() / refsz);
00135       while (xsz > 1024 && k < 3) {
00136          k++;
00137          refsz *= 1024;
00138          xsz = (Long64_t) (fi->GetSize() / refsz);
00139       }
00140       // Meta info
00141       meta = "";
00142       if (fi->GetMetaDataList()) {
00143          meta.Form("  %d  ", fi->GetMetaDataList()->GetSize());
00144          Bool_t firstObj = kTRUE;
00145          TIter nxm(fi->GetMetaDataList());
00146          TFileInfoMeta *fim = 0;
00147          while ((fim = (TFileInfoMeta *) nxm())) {
00148             if (!firstObj) meta += ",";
00149             name = fim->GetObject();
00150             if (strcmp(fim->GetDirectory(),"/")) name = fim->GetName();
00151             meta += Form("%s|%s|%lld", name.Data(), fim->GetClass(), fim->GetEntries());
00152             firstObj = kFALSE;
00153          }
00154       }
00155       // Printout
00156       if (xsz > 0) {
00157          Printf("%s:  %5d   %s %8lld %s    %s", action, nf, uu.Data(), xsz, unit[k], meta.Data());
00158       } else {
00159          Printf("%s:  %5d   %s         N/A    N/A", action, nf, uu.Data());
00160       }
00161    }
00162 }
00163 
00164 //______________________________________________________________________________
00165 void printDataSet(TFileCollection *fc, Int_t popt)
00166 {
00167    // Formatted printout of the content of TFileCollection 'fc'.
00168    // Options in the form
00169    //           popt = u * 10 + f
00170    //     f    0 => header only, 1 => header + files
00171    //   when printing files
00172    //     u    0 => print file name only, 1 => print full URL
00173 
00174    if (!fc) return;
00175 
00176    Int_t f = popt%10;
00177    Int_t u = popt - 10 * f;
00178 
00179    Printf("+++");
00180    if (fc->GetTitle() && (strlen(fc->GetTitle()) > 0)) {
00181       Printf("+++ Dumping: %s: ", fc->GetTitle());
00182    } else {
00183       Printf("+++ Dumping: %s: ", fc->GetName());
00184    }
00185    Printf("%s", fc->ExportInfo("+++ Summary:", 1)->GetName());
00186    if (f == 1) {
00187       Printf("+++ Files:");
00188       Int_t nf = 0;
00189       TIter nxfi(fc->GetList());
00190       TFileInfo *fi = 0;
00191       while ((fi = (TFileInfo *)nxfi())) {
00192          if (u == 1)
00193             Printf("+++ %5d. %s", ++nf, fi->GetCurrentUrl()->GetUrl());
00194          else
00195             Printf("+++ %5d. %s", ++nf, fi->GetCurrentUrl()->GetFile());
00196       }
00197    }
00198    Printf("+++");
00199 }
00200 
00201 //_______________________________________________________________________________________
00202 void do_info_server(const char *server)
00203 {
00204    // Execute 'info-server'
00205 
00206    const char *action = "pq2-info-server";
00207 
00208    // We need to scan all the datasets to find the matching ones ...
00209    TMap *dsmap = 0;
00210    {  redirguard rog(flog.Data(), "a", gverbose);
00211       dsmap = GetDataSets("/*/*", server);
00212    }
00213    if (!dsmap) {
00214       // Notify
00215       gSystem->Rename(flog.Data(), ferr.Data());
00216       Printf("%s: ERROR: problems retrieving info about datasets for server '%s'", action, server);
00217       return;
00218    }
00219 
00220    redirguard rog(fres.Data(), "w", gverbose);
00221    Int_t popt = 0;
00222    TIter nxk(dsmap);
00223    TObject *k = 0;
00224    TFileCollection *fc = 0;
00225    while ((k = nxk()) && (fc = (TFileCollection *) dsmap->GetValue(k))) {
00226       printDataSet(fc, popt);
00227    }
00228    delete dsmap;
00229 
00230    // Done
00231    return;
00232 }
00233 
00234 //_______________________________________________________________________________________
00235 Int_t pq2register(const char *dsname, const char *files, const char *opt) {
00236 
00237    // If the dataset exists already do not continue
00238    TString oo(opt);
00239    oo.ToUpper();
00240    redirguard rog(flog.Data(), "a", gverbose);
00241    if (ExistsDataSet(dsname) &&
00242        !oo.Contains("O") && !oo.Contains("U")) {
00243       return 2;
00244    }
00245    // Create the file collection
00246    TFileCollection *fc = new TFileCollection("dum", "dum", files);
00247 
00248    // The option may contain the default tree name and/or the staged status
00249    Int_t itb = kNPOS, ite = kNPOS;
00250    TString o(opt), deftree;
00251    if ((itb = o.Index("tree:")) != kNPOS) {
00252       deftree = o(itb + 5, o.Length());
00253       if ((ite = deftree.Index('|')) != kNPOS) deftree.Remove(ite);
00254       o.ReplaceAll(TString::Format("tree:%s|", deftree.Data()), "");
00255       if (!deftree.BeginsWith("/")) deftree.Insert(0, "/");
00256       if (!deftree.IsNull()) fc->SetDefaultTreeName(deftree);
00257    }
00258    if (o.Contains("staged|")) {
00259       fc->SetBitAll(TFileInfo::kStaged);
00260       o.ReplaceAll("staged|", "");
00261    }
00262    // Update the collection
00263    fc->Update();
00264 
00265    // Register the file collection
00266    Int_t rc =0;
00267    if (RegisterDataSet(dsname, fc, o) == 0) rc = 1;
00268    // Cleanup
00269    delete fc;
00270 
00271    // Done
00272    return rc;
00273 }
00274 
00275 //_______________________________________________________________________________________
00276 void do_put(const char *files, const char *opt)
00277 {
00278    // Execute 'put'
00279 
00280    const char *action = "pq2-put";
00281 
00282    // Check the file path makes sense
00283    if (!files || strlen(files) <= 0) {
00284       // Notify
00285       gSystem->Rename(flog.Data(), ferr.Data());
00286       Printf("%s: ERROR: path files not defined!", action);
00287       return ;
00288    }
00289 
00290    // Find out if it is a single file or a directory or contains a wildcard
00291    Bool_t isDir = kFALSE;
00292    Bool_t isWild = kFALSE;
00293    TString dir, base;
00294    FileStat_t st;
00295    if (gSystem->GetPathInfo(files, st) != 0) {
00296       // Path does not exists: check the basename for wild cards; in such a case
00297       // we have to do a selective search in the directory
00298       base = gSystem->BaseName(files);
00299       if (base.Contains("*")) {
00300          isWild = kTRUE;
00301          base.ReplaceAll("*", ".*");
00302          isDir = kTRUE;
00303          dir = gSystem->DirName(files);
00304       }
00305 
00306    } else {
00307       // Path exists: is it a dir or a file ?
00308       if (R_ISDIR(st.fMode)) {
00309          isDir = kTRUE;
00310          dir = files;
00311       }
00312    }
00313 
00314    Int_t ndp = 0, nd = 0;
00315    Int_t printerr = 1;
00316    Int_t rc = 0;
00317    // If simple file ...
00318    if (!isDir) {
00319       nd++;
00320       // ... just register and exit
00321       TString dsname = gSystem->BaseName(files);
00322       if ((rc = pq2register(dsname.Data(), files, opt)) != 0) {
00323          // Notify
00324          gSystem->Rename(flog.Data(), ferr.Data());
00325          if (rc == 2) {
00326             Printf("%s: WARNING: dataset '%s' already exists - ignoring request", action, dsname.Data());
00327             Printf("%s:          (use '-o O' to overwrite,  '-o U' to update)", action);
00328          } else {
00329             Printf("%s: ERROR: problems registering '%s' from '%s'", action, dsname.Data(), files);
00330          }
00331          return;
00332       }
00333       printerr = 0;
00334    } else {
00335       // ... else, scan the directory
00336       void *dirp = gSystem->OpenDirectory(dir.Data());
00337       if (!dirp) {
00338          // Notify
00339          gSystem->Rename(flog.Data(), ferr.Data());
00340          Printf("%s: ERROR: could not open directory '%s'", action, dir.Data());
00341          return;
00342       }
00343       printerr = 0;
00344       // Loop over the entries
00345       TString file;
00346       TRegexp reg(base);
00347       const char *ent = 0;
00348       while ((ent = gSystem->GetDirEntry(dirp))) {
00349          // Skip default entries
00350          if (!strcmp(ent, ".") || !strcmp(ent, "..")) continue;
00351          if (isWild) {
00352             file = ent;
00353             if (file.Index(reg) == kNPOS) continue;
00354          }
00355          nd++;
00356          file.Form("%s/%s", dir.Data(), ent);
00357          if ((rc = pq2register(ent, file.Data(), opt)) != 0) {
00358             nd--;
00359             ndp++;
00360             printerr = 1;
00361             // Notify
00362             if (rc == 1) {
00363                Printf("%s: ERROR: problems registering '%s' from '%s'", action, ent, file.Data());
00364             } else {
00365                Printf("%s: WARNING: dataset '%s' already exists - ignoring request", action, ent);
00366                Printf("%s:          (use '-o O' to overwrite,  '-o U' to update)", action);
00367             }
00368             continue;
00369          }
00370       }
00371       gSystem->FreeDirectory(dirp);
00372    }
00373 
00374    // If no match, notify
00375    if (printerr == 1) {
00376       if (ndp > 0)
00377          Printf("%s: WARNING: problems with %d dataset(s)", action, ndp);
00378       else
00379          Printf("%s: WARNING: some problems occured", action);
00380       gSystem->Rename(flog.Data(), ferr.Data());
00381    }
00382    Printf("%s: %d dataset(s) registered", action, nd);
00383 
00384    // Done
00385    return;
00386 }
00387 
00388 //_______________________________________________________________________________________
00389 void do_rm(const char *dsname)
00390 {
00391    // Execute 'rm'
00392 
00393    const char *action = "pq2-ds";
00394 
00395    Int_t nd = 0;
00396    Int_t printerr = 1;
00397    TString ds(dsname);
00398    if (!ds.Contains("*")) {
00399       nd++;
00400       // Remove the dataset
00401       redirguard rog(flog.Data(), "a", gverbose);
00402       if (RemoveDataSet(dsname) != 0) {
00403          // Notify
00404          gSystem->Rename(flog.Data(), ferr.Data());
00405          Printf("%s: ERROR: problems removing dataset '%s'", action, dsname);
00406          return;
00407       }
00408       printerr = 0;
00409    } else {
00410       // We need to scan all the datasets to find the matching ones ...
00411       TMap *dss = 0;
00412       {  redirguard rog(flog.Data(), "a", gverbose);
00413          dss = GetDataSets();
00414       }
00415       if (!dss) {
00416          // Notify
00417          gSystem->Rename(flog.Data(), ferr.Data());
00418          Printf("%s: ERROR: problems retrieving info about datasets", action);
00419          return;
00420       }
00421       printerr = 0;
00422       // Iterate
00423       TRegexp reg(dsname, kTRUE);
00424       TIter nxd(dss);
00425       TObjString *os = 0;
00426       while ((os = dynamic_cast<TObjString*>(nxd()))) {
00427          ds = os->GetName();
00428          if (ds.Index(reg) != kNPOS) {
00429             nd++;
00430             // Remove the dataset
00431             redirguard rog(flog.Data(), "a", gverbose);
00432             if (RemoveDataSet(ds.Data()) != 0) {
00433                printerr = 1;
00434                // Notify
00435                Printf("%s: ERROR: problems removing dataset '%s'", action, ds.Data());
00436                continue;
00437             }
00438          }
00439       }
00440 
00441    }
00442 
00443    // If no match, notify
00444    if (nd == 0) {
00445       Printf("%s: WARNING: no matching dataset found!", action);
00446    } else {
00447       Printf("%s: %d dataset(s) removed", action, nd);
00448    }
00449    if (printerr)
00450       gSystem->Rename(flog.Data(), ferr.Data());
00451 
00452    // Done
00453    return;
00454 }
00455 
00456 //_______________________________________________________________________________________
00457 int do_verify(const char *dsname, const char *opt, const char *redir)
00458 {
00459    // Execute 'verify'
00460 
00461    const char *action = "pq2-verify";
00462 
00463    Int_t nd = 0, rc = -1;
00464    Int_t printerr = 1;
00465    TString ds(dsname);
00466    if (!ds.Contains("*")) {
00467       nd++;
00468       // Verify the dataset
00469       if ((rc = VerifyDataSet(dsname, opt, redir)) < 0) {
00470          // Notify
00471          Printf("%s: ERROR: problems verifing dataset '%s'", action, dsname);
00472          return rc;
00473       } else if (rc > 0) {
00474          // Notify
00475          Printf("%s: WARNING: %s: some files not yet online (staged)", action, dsname);
00476       }
00477       printerr = 0;
00478    } else {
00479       // We need to scan all the datasets to find the matching ones ...
00480       TMap *dss = GetDataSets(dsname, "", "list");
00481       if (!dss) {
00482          // Notify
00483          Printf("%s: ERROR: problems retrieving info about datasets", action);
00484          return rc;
00485       }
00486       printerr = 0;
00487       // Iterate
00488       Int_t xrc = -1;
00489       TIter nxd(dss);
00490       TObjString *os = 0;
00491       while ((os = dynamic_cast<TObjString*>(nxd()))) {
00492          nd++;
00493          // Verify the dataset
00494          Printf("%s: start verification of dataset '%s' ...", action, os->GetName());
00495          if ((xrc = VerifyDataSet(os->GetName(), opt, redir)) < 0) {
00496             printerr = 1;
00497             // Notify
00498             Printf("%s: ERROR: problems verifying dataset '%s'", action, os->GetName());
00499             continue;
00500          } else if (xrc > 0) {
00501             // At least one is not fully available
00502             rc = 1;
00503             // Notify
00504             Printf("%s: WARNING: %s: some files not yet online (staged)", action, os->GetName());
00505          } else if (rc < 0) {
00506             // At least one is good
00507             rc = 0;
00508          }
00509       }
00510    }
00511 
00512    // If no match, notify
00513    if (nd == 0) {
00514       Printf("%s: WARNING: no matching dataset found!", action);
00515    } else {
00516       Printf("%s: %d dataset(s) verified", action, nd);
00517    }
00518    if (printerr)
00519       gSystem->Rename(flog.Data(), ferr.Data());
00520 
00521    // Done
00522    return rc;
00523 }
00524 
00525 //_______________________________________________________________________________________
00526 void do_anadist(const char *ds, const char *servers, const char *ignsrvs,
00527                 const char *excsrvs, const char *metrics, const char *fnout,
00528                 const char *plot, const char *outfile, const char *infile)
00529 {
00530    // Execute 'analyze-distribution' for the dataset(s) described by 'ds'.
00531    // The result is output to the screan and the details about file movement to file
00532    // 'fnout', if defined.
00533 
00534    const char *action = "pq2-ana-dist";
00535 
00536    // Running mode
00537    Bool_t plot_m = (plot && strlen(plot)) ? kTRUE : kFALSE;
00538    Bool_t plotonly_m = (plot_m && infile && strlen(infile)) ? kTRUE : kFALSE;
00539 
00540    // We need to scan all the datasets to find the matching ones ...
00541    TMap *fcmap = 0;
00542    TObject *k = 0;
00543    if (!plotonly_m) {
00544       redirguard rog(flog.Data(), "a", gverbose);
00545       TString dss(ds), d;
00546       Int_t from = 0;
00547       while (dss.Tokenize(d, from, ",")) {
00548          TMap *xm = GetDataSets(d);
00549          if (xm) {
00550             if (!fcmap) {
00551                fcmap = xm;
00552             } else {
00553                TIter nxds(xm);
00554                while ((k = nxds())) {
00555                   fcmap->Add(k, xm->GetValue(k));
00556                   xm->Remove(k);
00557                }
00558             }
00559             if (xm != fcmap) {
00560                xm->SetOwner(kFALSE);
00561                SafeDelete(xm);
00562             }
00563          }
00564       }
00565       if (!fcmap || fcmap->GetSize() <= 0) {
00566          SafeDelete(fcmap);
00567          // Notify
00568          gSystem->Rename(flog.Data(), ferr.Data());
00569          Printf("%s: ERROR: problems retrieving info about dataset '%s' (or empty dataset)", action, ds);
00570          return;
00571       }
00572       if (gverbose > 0) fcmap->Print();
00573    }
00574 
00575    // Which metrics
00576    Int_t optMet = 0;  // # of files
00577    if (metrics && !strcmp(metrics, "S")) optMet = 1;  // Size in bytes
00578    if (gverbose > 0) 
00579       Printf("%s: using metrics: '%s'", action, glabMet[optMet]);
00580 
00581    TList distinfo;
00582    if (plotonly_m) {
00583       // Get the dist info
00584       if (do_anadist_ds(0, 0, 0, 0, optMet, 0, &distinfo, 0, infile) != 0) {
00585          Printf("%s: problems getting dist info from '%s'", action, infile);
00586       }
00587    } else {
00588       // Name
00589       TString cname(ds);
00590       if (cname.BeginsWith("/")) cname.Remove(0,1);
00591       if (cname.EndsWith("/")) cname.Remove(cname.Last('/'));
00592       cname.ReplaceAll("/", "-");
00593       cname.ReplaceAll("*", "-star-");
00594       distinfo.SetName(cname);
00595       TFileCollection *fc = 0;
00596       TIter nxd(fcmap);
00597       TFileCollection *fctot = 0;
00598       while ((k = nxd()) && (fc = (TFileCollection *) fcmap->GetValue(k))) {
00599          if (!fctot) {
00600             // The first one
00601             fctot = fc;
00602             fcmap->Remove(k);
00603          } else {
00604             // Add
00605             fctot->Add(fc);
00606          }
00607       }
00608       // Analyse the global dataset
00609       if (do_anadist_ds(fctot, servers, ignsrvs, excsrvs,
00610                         optMet, fnout, &distinfo, outfile, infile) != 0) {
00611          Printf("%s: problems analysing dataset '%s'", action, fc ? fc->GetName() : "<undef>");
00612       }
00613       // Cleanup
00614       SafeDelete(fcmap);
00615       SafeDelete(fctot);
00616    }
00617 
00618    // Save histo, if any
00619    TString fileplot(plot), gext;
00620    if (!(fileplot.IsNull())) {
00621       if (fileplot.Contains(".")) {
00622          gext = fileplot(fileplot.Last('.') + 1, fileplot.Length());
00623       } else {
00624          gext = "png";
00625       }
00626       const char *fmts[9] = {"png", "eps", "ps", "pdf", "svg", "gif", "xpm", "jpg", "tiff" };
00627       Int_t iplot = 0;
00628       while (iplot < 9 && gext != fmts[iplot]) { iplot++; }
00629       if (iplot == 9) {
00630          Printf("%s: graphics format '%s' not supported: switching to 'png'", action, gext.Data());
00631          gext = "png";
00632       }
00633       if (!(fileplot.EndsWith(gext))) {
00634          if (!(fileplot.EndsWith("."))) fileplot += ".";
00635          fileplot += gext;
00636       }
00637       // Create the histogram
00638       TH1D *h1d = 0;
00639       if (distinfo.GetSize() > 0) {
00640          h1d = new TH1D("DistInfoHist", distinfo.GetName(), distinfo.GetSize(), 0.5, distinfo.GetSize() + .5);
00641          TIter nxs(&distinfo);
00642          TParameter<Double_t> *ent = 0;
00643          Double_t x = 0;
00644          while ((ent = (TParameter<Double_t> *) nxs())) {
00645             x += 1.;
00646             h1d->Fill(x, ent->GetVal());
00647             TString nn(TUrl(ent->GetName()).GetHost());
00648             if (nn.Contains(".")) nn.Remove(nn.First('.'));
00649             Int_t i = h1d->FindBin(x);
00650             h1d->GetXaxis()->SetBinLabel(i, nn.Data());
00651          }
00652       } else {
00653          Printf("%s: plot requested but no server found (info list is empty)!", action);
00654       }
00655       if (h1d) {
00656          TString filehist(fileplot);
00657          filehist.Remove(filehist.Last('.')+1);
00658          filehist += "root";
00659          TFile *f = TFile::Open(filehist, "RECREATE");
00660          if (f) {
00661             f->cd();
00662             h1d->Write(0,TObject::kOverwrite);
00663             SafeDelete(f);
00664             // Write the instruction for the plotting macro
00665             TString filetmp = TString::Format("%s/%s.tmp", gSystem->TempDirectory(), action);
00666             FILE *ftmp = fopen(filetmp.Data(), "w");
00667             if (ftmp) {
00668                fprintf(ftmp, "%s %s %s", filehist.Data(), fileplot.Data(), glabMet[optMet]);
00669                fclose(ftmp);
00670             } else {
00671                Printf("%s: problems opening temp file '%s' (errno: %d)", action, filetmp.Data(), errno);
00672                Printf("%s: relevant info: %s %s %s (input to pq2PlotDist.C)",
00673                                              action, filehist.Data(), fileplot.Data(), glabMet[optMet]);
00674             }
00675          } else {
00676             Printf("%s: problems opening file '%s'", action, filehist.Data());
00677          }
00678       } else {
00679          Printf("%s: histogram requested but not found", action);
00680       }
00681    }
00682 
00683    // Done
00684    return;
00685 }
00686 
00687 //_______________________________________________________________________________________
00688 int do_anadist_ds(TFileCollection *fc, const char *servers, const char *ignsrvs,
00689                   const char *excsrvs, int met, const char *fnout,
00690                   TList *distinfo, const char *outfile, const char *infile)
00691 {
00692    // Do analysis of dataset 'fc'
00693 
00694    const char *action = "pq2-ana-dist-ds";
00695 
00696    // Check the inputs
00697    Bool_t distonly_m = (!fc && distinfo && infile && strlen(infile) > 0) ? kTRUE : kFALSE;
00698    const char *dsname = 0;
00699    if (!distonly_m) {
00700       if (!fc) {
00701          Printf("%s: dataset undefined!", action);
00702          return -1;
00703       }
00704       dsname = fc->GetName();
00705       if (fc->GetList()->GetSize() <= 0) {
00706          Printf("%s: dataset '%s' is empty", action, dsname);
00707          return -1;
00708       }
00709    } else {
00710       dsname = distinfo->GetName();
00711    }
00712 
00713    THashList *ignore = 0, *targets = 0, *exclude = 0;
00714    Bool_t addmode = kFALSE;
00715    if (!distonly_m) {
00716       TString ss, k, key;
00717       Int_t from = 0;
00718       // List of servers to be ignored
00719       if (ignsrvs && strlen(ignsrvs)) {
00720          ss = ignsrvs;
00721          from = 0;
00722          while (ss.Tokenize(k, from, ",")) {
00723             do_anadist_getkey(k.Data(), key);
00724             if (!(key.IsNull())) {
00725                if (!ignore) ignore = new THashList();
00726                ignore->Add(new TObjString(key));
00727             }
00728          }
00729       }
00730       // List of servers to be excluded
00731       if (excsrvs && strlen(excsrvs)) {
00732          ss = excsrvs;
00733          from = 0;
00734          while (ss.Tokenize(k, from, ",")) {
00735             do_anadist_getkey(k.Data(), key);
00736             if (!(key.IsNull())) {
00737                if (!exclude) exclude = new THashList();
00738                exclude->Add(new TObjString(key));
00739             }
00740          }
00741       }
00742       // List of sub-TFileCollection for target servers: in add mode we complete it during
00743       // the first scan
00744       targets = new THashList();
00745       if (servers && strlen(servers)) {
00746          ss = servers;
00747          if (ss.BeginsWith("+")) {
00748             addmode = kTRUE;
00749             ss.Remove(0,1);
00750          }
00751          from = 0;
00752          while (ss.Tokenize(k, from, ",")) {
00753             do_anadist_getkey(k.Data(), key);
00754             if (!(key.IsNull())) targets->Add(new TFileCollection(key));
00755          }
00756       } else {
00757          addmode = kTRUE;
00758       }
00759    }
00760    // List of sub-TFileCollection for each server, so that we automatically count
00761    // the sizes and totals
00762    TNamed *fcsls_title = 0;
00763    THashList *fcsls = 0;
00764    Int_t targets_size = -1;
00765    if (infile && strlen(infile)) {
00766       TFile *flist = TFile::Open(infile);
00767       if (flist) {
00768          Printf("%s: reading info from file '%s' ", action, infile);
00769          if (!(fcsls = (THashList *) flist->Get("FileDistList"))) {
00770             Printf("%s: could not find starting file distribution 'FileDistList' in input file '%s' ",
00771                         action, infile);
00772             flist->Close();
00773             SafeDelete(flist);
00774             SDELTRE(ignore, targets, exclude);
00775             return -1;
00776          }
00777          // Get the title
00778          fcsls_title = (TNamed *) flist->Get("FileDistList_Title");
00779          // Get the targets size
00780          TParameter<Int_t> *psz = (TParameter<Int_t> *) flist->Get("Targets_Size");
00781          if (psz) targets_size = psz->GetVal();
00782          // Close
00783          flist->Close();
00784          SafeDelete(flist);
00785          // Add info about the current run in the title
00786          if (distinfo && fcsls_title && strlen(fcsls_title->GetTitle()) > 0) {
00787             TString runt(fcsls_title->GetTitle());
00788             if (strcmp(distinfo->GetName(), "TList")) {
00789                if (!(runt.IsNull())) runt += ",";
00790                runt += distinfo->GetName();
00791                fcsls_title->SetTitle(runt);
00792             }
00793             distinfo->SetName(fcsls_title->GetTitle());
00794          }
00795       } else {
00796          Printf("%s: problems opening input file '%s' ", action, infile);
00797          SDELTRE(ignore, targets, exclude);
00798          return -1;
00799       }
00800    }
00801    if (!fcsls) {
00802       fcsls = new THashList();
00803       fcsls->SetName("FileDistList");
00804       fcsls_title = new TNamed("FileDistList_Title", distinfo ? distinfo->GetName() : "");
00805    }
00806 
00807    // Set initial values for the counters, if needed
00808    Long64_t totsz = 0, totfiles = 0;
00809    TFileCollection *fcs = 0;
00810    TIter nxfc(fcsls);
00811    while ((fcs = (TFileCollection *) nxfc())) {
00812       fcs->Update();
00813       totfiles += fcs->GetNFiles();
00814       totsz += fcs->GetTotalSize();
00815    }
00816 
00817    // Analyze the file collection content now
00818    TFileInfo *fi = 0;
00819    if (fc) {
00820       TIter nxfi(fc->GetList());
00821       while ((fi = (TFileInfo *) nxfi())) {
00822          // Get the key
00823          TString key;
00824          do_anadist_getkey(fi->GetCurrentUrl(), key);
00825          // Ignore if requested
00826          if (ignore && ignore->FindObject(key)) continue;
00827          // Get the TFileCollection for this server
00828          if (!(fcs = (TFileCollection *) fcsls->FindObject(key))) {
00829             if (gverbose > 0)
00830                Printf("%s:%s: found server '%s' ... ", action, dsname, key.Data());
00831             fcs = new TFileCollection(key);
00832             fcsls->Add(fcs);
00833          }
00834          fcs->Add(fi);
00835          // In add mode, add  as target, if needed
00836          Bool_t excluded = (exclude && exclude->FindObject(key)) ? kTRUE : kFALSE;
00837          if (!excluded) {
00838             if (targets && !(fcs = (TFileCollection *) targets->FindObject(key))) {
00839                if (addmode) {
00840                   if (gverbose > 0)
00841                      Printf("%s:%s: add new target server '%s' ...", action, dsname, key.Data());
00842                   fcs = new TFileCollection(key);
00843                   targets->Add(fcs);
00844                }
00845             }
00846             if (fcs) fcs->Add(fi);
00847          }
00848          // Count
00849          totsz += fi->GetSize();
00850          totfiles++;
00851       }
00852 
00853       // Nothing to do if no targets
00854       if (targets->GetSize() <= 0) {
00855          Printf("%s:%s: target servers list is empty!", action, dsname);
00856          SDELETE(ignore, targets, exclude, fcsls, fcsls_title);
00857          return -1;
00858       } else {
00859          Printf("%s:%s: %d target servers found", action, dsname, targets->GetSize());
00860          if (gverbose > 0) targets->Print();
00861       }
00862    }
00863    SDELTWO(ignore, exclude);
00864 
00865    // Separate into 'excess' and 'defect' lists
00866    TList *excls = new TList;
00867    TList *defls = new TList;
00868    targets_size = (targets) ? targets->GetSize() : targets_size;
00869    Double_t avgfiles = 0, avgsize = 0;
00870    if (targets_size > 0) {
00871       avgfiles = (Double_t)totfiles / targets_size;
00872       avgsize = (Double_t)totsz / targets_size / 1024. / 1024. / 1024.;
00873       Printf("%s:%s: %d servers found, %lld files; in average: %.3f files / %.3f GBs per server",
00874                   action, dsname, fcsls->GetSize(), totfiles, avgfiles, avgsize);
00875    } else {
00876       // Cannot continue;
00877       Printf("%s:%s: target size is null or negative", action, dsname);
00878       SDELETE(ignore, targets, exclude, fcsls, fcsls_title);
00879       return -1;
00880    }
00881    // Before redistribution
00882    if (gverbose > 0) Printf("\n%s:%s: Before redistribution:", action, dsname);
00883    nxfc.Reset();
00884    while ((fcs = (TFileCollection *) nxfc())) {
00885       fcs->Update();
00886       Long64_t nfexcess = fcs->GetNFiles() - (Long64_t) avgfiles;
00887       Double_t xdf = nfexcess / avgfiles;
00888       Double_t fcsz = fcs->GetTotalSize() / 1024. / 1024. / 1024.;
00889       Double_t szexcess = fcsz - avgsize;
00890       Double_t xdsz = szexcess / avgsize;
00891       // Fill the output histogram, if needed
00892       if (distinfo) {
00893          TParameter<Double_t> *ent = (TParameter<Double_t> *) distinfo->FindObject(fcs->GetName());
00894          if (!ent) {
00895             ent = new TParameter<Double_t>(fcs->GetName(), 0.);
00896             distinfo->Add(ent);
00897          }
00898          if (met == 0) {
00899             ent->SetVal(ent->GetVal() + (Double_t) fcs->GetNFiles());
00900          } else if (met == 1) {
00901             ent->SetVal(ent->GetVal() + fcsz);
00902          }
00903       }
00904       if (gverbose > 0)
00905          Printf("%s:%s:  server %s:  %lld files (diff: %lld, %.3f) - %.3f GBs (diff: %.3f, %.3f)",
00906                 action, dsname, fcs->GetName(), fcs->GetNFiles(), nfexcess, xdf, fcsz, szexcess, xdsz);
00907       if (fc) {
00908          // Move to the appropriate list
00909          Bool_t isExcess = kFALSE;
00910          if (targets && targets->FindObject(fcs->GetName())) {
00911             if (met == 0) {
00912                if (nfexcess > 0.) isExcess = kTRUE;
00913             } else if (met == 1) {
00914                if (szexcess > 0.) isExcess = kTRUE;
00915             }
00916          } else {
00917             // This server needs to be freed
00918             isExcess = kTRUE;
00919          }
00920          if (isExcess) {
00921             excls->Add(fcs);
00922          } else {
00923             defls->Add(fcs);
00924          }
00925       }
00926    }
00927    if (outfile && strlen(outfile)) {
00928       TFile *flist = TFile::Open(outfile, "RECREATE");
00929       if (flist) {
00930          flist->cd();
00931          Printf("%s: saving info to file '%s' ", action, outfile);
00932          fcsls->Write("FileDistList", TObject::kOverwrite | TObject::kSingleKey);
00933          if (fcsls_title) fcsls_title->Write("FileDistList_Title", TObject::kOverwrite);
00934          if (targets) {
00935             TParameter<Int_t> *psz = new TParameter<Int_t>("Targets_Size", targets->GetSize());
00936             psz->Write("Targets_Size", TObject::kOverwrite);
00937          }
00938          flist->Close();
00939          SafeDelete(flist);
00940       } else {
00941          Printf("%s: problems opening output file '%s' ", action, outfile);
00942          return -1;
00943       }
00944    }
00945    // Cleanup
00946    fcsls->SetOwner(0);
00947    SDELTWO(fcsls, fcsls_title);
00948 
00949    // If we just need the dist info we are done
00950    if (!fc) {
00951       SDELETE(targets, fcsls, fcsls_title, excls, defls);
00952       return 0;
00953    }
00954 
00955    // Notify
00956    if (gverbose > 0) {
00957       Printf("%s:%s: %d servers found in excess", action, dsname, excls->GetSize());
00958       excls->Print();
00959       Printf("%s:%s: %d servers found in defect", action, dsname, defls->GetSize());
00960       defls->Print();
00961    } else {
00962       Printf("%s:%s: %d servers found in excess, %d in defect", action, dsname, excls->GetSize(), defls->GetSize());
00963    }
00964 
00965    // Open output file, if requested
00966    FILE *fout = 0;
00967    if (fnout && strlen(fnout) > 0) {
00968       if (!(fout = fopen(fnout, "a"))) {
00969          Printf("%s: problems opening output file '%s' (errno: %d)", action, fnout, errno);
00970          SDELETE(targets, fcsls, fcsls_title, excls, defls);
00971          return -1;
00972       }
00973    }
00974 
00975    // Get the list of files to be moved
00976    THashList szls;
00977    TIter nxefc(excls);
00978    TIter nxdfc(defls);
00979    Int_t mvfiles = 0;
00980    Bool_t printheader = kTRUE;
00981    TFileCollection *fcd = (TFileCollection *) nxdfc();
00982    while ((fcs = (TFileCollection *) nxefc())) {
00983       Bool_t isTarget = (targets->FindObject(fcs->GetName())) ? kTRUE : kFALSE;
00984       Long64_t fcfiles = 0;
00985       Double_t fcsz = 0.;
00986       TIter nxefi(fcs->GetList());
00987       while ((fi = (TFileInfo *) nxefi())) {
00988          if (!fcd) {
00989             Printf("%s:%s: WARNING: processing list in excess '%s': no more lists in deficit!",
00990                    action, dsname, fcs->GetName());
00991             break;
00992          }
00993          // Count
00994          fcfiles++;
00995          fcsz += (fi->GetSize() / 1024. / 1024. / 1024.) ;
00996          if (!isTarget ||
00997             (((met == 0) && (fcfiles > avgfiles)) || ((met == 1) && (fcsz > avgsize)))) {
00998             // Write record in output file, if requested
00999             TUrl u(fi->GetCurrentUrl()->GetUrl());
01000             u.SetAnchor("");
01001             u.SetOptions("");
01002             TString php(u.GetUrl());
01003             php.Remove(php.Index(u.GetFile()));
01004             if (php.EndsWith("/")) php.Remove(php.Last('/'));
01005             if (fout) {
01006                fprintf(fout,"%s %s %s\n", u.GetFile(), php.Data(), fcd->GetName());
01007             } else {
01008                if (printheader) Printf(" File  Source_Server  Destination_Server");
01009                Printf("%s %s %s", u.GetFile(), php.Data(), fcd->GetName());
01010                printheader = kFALSE;
01011             }
01012             fcs->GetList()->Remove(fi);
01013             fcd->Add(fi);
01014             Bool_t getnext = kFALSE;
01015             if (met == 0 && fcd->GetList()->GetSize() > avgfiles) getnext = kTRUE;
01016             if (met == 1) {
01017                Long64_t xfcsz = 0;
01018                TParameter<Long64_t> *ptot = (TParameter<Long64_t> *) szls.FindObject(fcd);
01019                if (!ptot) {
01020                   fcd->Update();
01021                   ptot = new TParameter<Long64_t>(fcd->GetName(), fcd->GetTotalSize());
01022                   xfcsz = ptot->GetVal();
01023                   szls.Add(ptot);
01024                } else {
01025                   xfcsz = ptot->GetVal();
01026                   xfcsz += fi->GetSize();
01027                }
01028                if ((xfcsz / 1024. / 1024. / 1024.) > avgsize) getnext = kTRUE;
01029             }
01030             if (getnext) fcd = (TFileCollection *) nxdfc();
01031             // Count files to be moved
01032             mvfiles++;
01033          }
01034       }
01035    }
01036    // Close the file
01037    if (fout) {
01038       if ((fclose(fout)) != 0)
01039          Printf("%s: problems closing output file '%s' (errno: %d)", action, fnout, errno);
01040    }
01041    Printf("%s:%s: %d files should be moved to make the distribution even (metrics: %s)",
01042           action, dsname, mvfiles, glabMet[met]);
01043 
01044    // After redistribution
01045    if (gverbose > 0) {
01046       Printf("\n%s:%s: After redistribution:", action, dsname);
01047       nxefc.Reset();
01048       while ((fcs = (TFileCollection *) nxefc())) {
01049          fcs->Update();
01050          Long64_t nfexcess = fcs->GetNFiles() - (Long64_t) avgfiles;
01051          Double_t xdf = nfexcess / avgfiles;
01052          Double_t fcsz = fcs->GetTotalSize() / 1024. / 1024. / 1024.;
01053          Double_t szexcess = fcsz - avgsize;
01054          Double_t xdsz = szexcess / avgsize;
01055          Printf("%s:%s:  Server %s:  %lld files (diff: %lld, %.3f) - %.3f GBs (diff: %.3f, %.3f)",
01056                 action, dsname, fcs->GetName(), fcs->GetNFiles(), nfexcess, xdf, fcsz, szexcess, xdsz);
01057       }
01058       nxdfc.Reset();
01059       while ((fcs = (TFileCollection *) nxdfc())) {
01060          fcs->Update();
01061          Long64_t nfexcess = fcs->GetNFiles() - (Long64_t) avgfiles;
01062          Double_t xdf = nfexcess / avgfiles;
01063          Double_t fcsz = fcs->GetTotalSize() / 1024. / 1024. / 1024.;
01064          Double_t szexcess = fcsz - avgsize;
01065          Double_t xdsz = szexcess / avgsize;
01066          Printf("%s:%s:  server %s:  %lld files (diff: %lld, %.3f) - %.3f GBs (diff: %.3f, %.3f)",
01067                 action, dsname, fcs->GetName(), fcs->GetNFiles(), nfexcess, xdf, fcsz, szexcess, xdsz);
01068       }
01069    }
01070    // Cleanup
01071    SDELETE(targets, fcsls, fcsls_title, excls, defls);
01072    // Done
01073    return 0;
01074 }
01075 
01076 //_______________________________________________________________________________________
01077 void do_anadist_getkey(const char *p, TString &key)
01078 {
01079    // Get the key corresponding to path 'p'.
01080 
01081    TUrl u(p);
01082    if (strncmp(p, u.GetProtocol(), strlen(u.GetProtocol()))) {
01083       u.SetProtocol("root");
01084       TString sport = TString::Format(":%d", u.GetPort());
01085       if (!strstr(p, sport.Data())) u.SetPort(1094);
01086    }
01087    if (gverbose > 0) Printf("do_anadist_getkey: url: %s", u.GetUrl());
01088    return do_anadist_getkey(&u, key);
01089 }
01090 
01091 //_______________________________________________________________________________________
01092 void do_anadist_getkey(TUrl *u, TString &key)
01093 {
01094    // Get the key corresponding to url 'u'.
01095 
01096    key = "";
01097    if (u) {
01098       TParameter<Int_t> *php = (TParameter<Int_t> *)gProtoPortMap.FindObject(u->GetProtocol());
01099       if (!php) {
01100          TUrl xu(TString::Format("%s://host//file", u->GetProtocol()));
01101          php = new TParameter<Int_t>(u->GetProtocol(), xu.GetPort());
01102          gProtoPortMap.Add(php);
01103       }
01104       if (u->GetPort() != php->GetVal()) {
01105          key.Form("%s://%s:%d", u->GetProtocol(), u->GetHost(), u->GetPort());
01106       } else {
01107          key.Form("%s://%s", u->GetProtocol(), u->GetHost());
01108       }
01109    }
01110    // Done
01111    return;
01112 }
01113 //_______________________________________________________________________________________
01114 int do_anadist_plot(TH1D *h1d, const char */*fnout*/)
01115 {
01116    // Create the plot for the histogram, and save to 'fnout'.
01117    // Format determined by th extension of fnout.
01118 
01119    Printf("do_anadist_plot: will be doing a plot here ... ");
01120 
01121    if (h1d) {
01122       Printf("do_anadist_plot: we save the histo for now (to testhist.root)");
01123       TFile *f = TFile::Open("testhist.root", "RECREATE");
01124       if (f) {
01125          f->cd();
01126          h1d->Write(0,TObject::kOverwrite);
01127          SafeDelete(f);
01128          return 0;
01129       }
01130    }
01131    return -1;
01132 }

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