00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00037 extern TString flog;
00038 extern TString ferr;
00039 extern TString fres;
00040 extern Int_t gverbose;
00041
00042
00043 static const char *glabMet[] = { "#files", "size" };
00044 THashList gProtoPortMap;
00045
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
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
00061
00062
00063 DataSetCache(clear, ds);
00064
00065 gSystem->Unlink(ferr.Data());
00066 }
00067
00068
00069 void do_ls(const char *ds, const char *opt)
00070 {
00071
00072
00073
00074 ShowDataSets(ds, opt);
00075
00076 gSystem->Unlink(ferr.Data());
00077 }
00078
00079
00080 void do_ls_files_server(const char *ds, const char *server)
00081 {
00082
00083
00084 const char *action = (server && strlen(server) > 0) ? "pq2-ls-files-server" : "pq2-ls-files";
00085
00086
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
00097 gSystem->Rename(flog.Data(), ferr.Data());
00098 Printf("%s: ERROR: problems retrieving info about dataset '%s'", action, ds);
00099 return;
00100 }
00101
00102
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
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
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
00129 uu = fi->GetCurrentUrl()->GetUrl();
00130 if (uu.Length() < 80) uu.Resize(80);
00131
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
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
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
00168
00169
00170
00171
00172
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
00205
00206 const char *action = "pq2-info-server";
00207
00208
00209 TMap *dsmap = 0;
00210 { redirguard rog(flog.Data(), "a", gverbose);
00211 dsmap = GetDataSets("/*/*", server);
00212 }
00213 if (!dsmap) {
00214
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
00231 return;
00232 }
00233
00234
00235 Int_t pq2register(const char *dsname, const char *files, const char *opt) {
00236
00237
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
00246 TFileCollection *fc = new TFileCollection("dum", "dum", files);
00247
00248
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
00263 fc->Update();
00264
00265
00266 Int_t rc =0;
00267 if (RegisterDataSet(dsname, fc, o) == 0) rc = 1;
00268
00269 delete fc;
00270
00271
00272 return rc;
00273 }
00274
00275
00276 void do_put(const char *files, const char *opt)
00277 {
00278
00279
00280 const char *action = "pq2-put";
00281
00282
00283 if (!files || strlen(files) <= 0) {
00284
00285 gSystem->Rename(flog.Data(), ferr.Data());
00286 Printf("%s: ERROR: path files not defined!", action);
00287 return ;
00288 }
00289
00290
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
00297
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
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
00318 if (!isDir) {
00319 nd++;
00320
00321 TString dsname = gSystem->BaseName(files);
00322 if ((rc = pq2register(dsname.Data(), files, opt)) != 0) {
00323
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
00336 void *dirp = gSystem->OpenDirectory(dir.Data());
00337 if (!dirp) {
00338
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
00345 TString file;
00346 TRegexp reg(base);
00347 const char *ent = 0;
00348 while ((ent = gSystem->GetDirEntry(dirp))) {
00349
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
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
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
00385 return;
00386 }
00387
00388
00389 void do_rm(const char *dsname)
00390 {
00391
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
00401 redirguard rog(flog.Data(), "a", gverbose);
00402 if (RemoveDataSet(dsname) != 0) {
00403
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
00411 TMap *dss = 0;
00412 { redirguard rog(flog.Data(), "a", gverbose);
00413 dss = GetDataSets();
00414 }
00415 if (!dss) {
00416
00417 gSystem->Rename(flog.Data(), ferr.Data());
00418 Printf("%s: ERROR: problems retrieving info about datasets", action);
00419 return;
00420 }
00421 printerr = 0;
00422
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
00431 redirguard rog(flog.Data(), "a", gverbose);
00432 if (RemoveDataSet(ds.Data()) != 0) {
00433 printerr = 1;
00434
00435 Printf("%s: ERROR: problems removing dataset '%s'", action, ds.Data());
00436 continue;
00437 }
00438 }
00439 }
00440
00441 }
00442
00443
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
00453 return;
00454 }
00455
00456
00457 int do_verify(const char *dsname, const char *opt, const char *redir)
00458 {
00459
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
00469 if ((rc = VerifyDataSet(dsname, opt, redir)) < 0) {
00470
00471 Printf("%s: ERROR: problems verifing dataset '%s'", action, dsname);
00472 return rc;
00473 } else if (rc > 0) {
00474
00475 Printf("%s: WARNING: %s: some files not yet online (staged)", action, dsname);
00476 }
00477 printerr = 0;
00478 } else {
00479
00480 TMap *dss = GetDataSets(dsname, "", "list");
00481 if (!dss) {
00482
00483 Printf("%s: ERROR: problems retrieving info about datasets", action);
00484 return rc;
00485 }
00486 printerr = 0;
00487
00488 Int_t xrc = -1;
00489 TIter nxd(dss);
00490 TObjString *os = 0;
00491 while ((os = dynamic_cast<TObjString*>(nxd()))) {
00492 nd++;
00493
00494 Printf("%s: start verification of dataset '%s' ...", action, os->GetName());
00495 if ((xrc = VerifyDataSet(os->GetName(), opt, redir)) < 0) {
00496 printerr = 1;
00497
00498 Printf("%s: ERROR: problems verifying dataset '%s'", action, os->GetName());
00499 continue;
00500 } else if (xrc > 0) {
00501
00502 rc = 1;
00503
00504 Printf("%s: WARNING: %s: some files not yet online (staged)", action, os->GetName());
00505 } else if (rc < 0) {
00506
00507 rc = 0;
00508 }
00509 }
00510 }
00511
00512
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
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
00531
00532
00533
00534 const char *action = "pq2-ana-dist";
00535
00536
00537 Bool_t plot_m = (plot && strlen(plot)) ? kTRUE : kFALSE;
00538 Bool_t plotonly_m = (plot_m && infile && strlen(infile)) ? kTRUE : kFALSE;
00539
00540
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
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
00576 Int_t optMet = 0;
00577 if (metrics && !strcmp(metrics, "S")) optMet = 1;
00578 if (gverbose > 0)
00579 Printf("%s: using metrics: '%s'", action, glabMet[optMet]);
00580
00581 TList distinfo;
00582 if (plotonly_m) {
00583
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
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
00601 fctot = fc;
00602 fcmap->Remove(k);
00603 } else {
00604
00605 fctot->Add(fc);
00606 }
00607 }
00608
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
00614 SafeDelete(fcmap);
00615 SafeDelete(fctot);
00616 }
00617
00618
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
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
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
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
00693
00694 const char *action = "pq2-ana-dist-ds";
00695
00696
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
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
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
00743
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
00761
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
00778 fcsls_title = (TNamed *) flist->Get("FileDistList_Title");
00779
00780 TParameter<Int_t> *psz = (TParameter<Int_t> *) flist->Get("Targets_Size");
00781 if (psz) targets_size = psz->GetVal();
00782
00783 flist->Close();
00784 SafeDelete(flist);
00785
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
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
00818 TFileInfo *fi = 0;
00819 if (fc) {
00820 TIter nxfi(fc->GetList());
00821 while ((fi = (TFileInfo *) nxfi())) {
00822
00823 TString key;
00824 do_anadist_getkey(fi->GetCurrentUrl(), key);
00825
00826 if (ignore && ignore->FindObject(key)) continue;
00827
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
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
00849 totsz += fi->GetSize();
00850 totfiles++;
00851 }
00852
00853
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
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
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
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
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
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
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
00946 fcsls->SetOwner(0);
00947 SDELTWO(fcsls, fcsls_title);
00948
00949
00950 if (!fc) {
00951 SDELETE(targets, fcsls, fcsls_title, excls, defls);
00952 return 0;
00953 }
00954
00955
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
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
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
00994 fcfiles++;
00995 fcsz += (fi->GetSize() / 1024. / 1024. / 1024.) ;
00996 if (!isTarget ||
00997 (((met == 0) && (fcfiles > avgfiles)) || ((met == 1) && (fcsz > avgsize)))) {
00998
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
01032 mvfiles++;
01033 }
01034 }
01035 }
01036
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
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
01071 SDELETE(targets, fcsls, fcsls_title, excls, defls);
01072
01073 return 0;
01074 }
01075
01076
01077 void do_anadist_getkey(const char *p, TString &key)
01078 {
01079
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
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
01111 return;
01112 }
01113
01114 int do_anadist_plot(TH1D *h1d, const char *)
01115 {
01116
01117
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 }