Logo ROOT   6.12/07
Reference Guide
TPackMgr.cxx
Go to the documentation of this file.
1 // @(#)root/proof:$Id$
2 // Author: G. Ganis, Oct 2015
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TPackMgr
13 \ingroup proofkernel
14 
15 The PROOF package manager contains tools to manage packages.
16 This class has been created to eliminate duplications, and to allow for
17 standalone usage.
18 
19 */
20 
21 #include "TPackMgr.h"
22 
23 #include "TError.h"
24 #include "TFile.h"
25 #include "TFunction.h"
26 #include "THashList.h"
27 #include "TList.h"
28 #include "TMacro.h"
29 #include "TMD5.h"
30 #include "TMethodArg.h"
31 #include "TMethodCall.h"
32 #include "TObjString.h"
33 #include "TParameter.h"
34 #include "TMap.h"
35 #include "TProof.h" // for constants such as kRM and kLS.
36 #include "TROOT.h"
37 #include "TSystem.h"
38 
40 
41 
42 static void DefaultLogger(const char *msg) { Printf("%s", msg); }
43 
44 THashList *TPackMgr::fgGlobalPackMgrList = 0; // list of package managers for global packages
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// Create a PROOF package manager
48 
49 TPackMgr::TPackMgr(const char *dir, const char *key)
50  : fLogger(DefaultLogger), fName(key), fDir(dir), fLock(dir), fEnabledPackages(0)
51 {
52  // Work with full names
54  Warning("TPackMgr", "problems expanding path '%s'", fDir.Data());
55  // The lock file in temp
56  TString lockname = TString::Format("%s/packdir-lock-%s",
58  fLock.SetName(lockname);
59 }
60 
61 ////////////////////////////////////////////////////////////////////////////////
62 /// Destroy a TPackMgr instance
63 
65 {
66  // Destroy the lock file
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 /// Wrapper to notofuer / logger
72 
73 void TPackMgr::Log(const char *msg)
74 {
75  if (fLogger) {
76  if (fPfx.IsNull())
77  (*fLogger)(msg);
78  else
79  (*fLogger)(TString::Format("%s: %s", fPfx.Data(), msg));
80  }
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// Method to build a package.
85 /// Return -1 on error, 0 otherwise
86 
87 Int_t TPackMgr::Build(const char *pack, Int_t opt)
88 {
89  Int_t rc = 0;
90 
91  TLockPathGuard lp(&fLock);
92 
93  if (gDebug > 0)
94  Info("Build", "building package %s ...", pack);
95 
97  TString pdir = TString::Format("%s/%s", fDir.Data(), pack);
98  gSystem->ChangeDirectory(pdir);
99 
100  // check for BUILD.sh and execute
101  if (!gSystem->AccessPathName("PROOF-INF/BUILD.sh")) {
102  // Notify the upper level
103  Log(TString::Format("building %s ...", pack));
104 
105  // Read version from file proofvers.txt, and if current version is
106  // not the same do a "BUILD.sh clean"
107  Bool_t goodver = kTRUE;
108  Bool_t savever = kFALSE;
109  TString v, r;
110  FILE *f = fopen("PROOF-INF/proofvers.txt", "r");
111  if (f) {
112  v.Gets(f);
113  r.Gets(f);
114  fclose(f);
115  if (opt == TPackMgr::kCheckROOT && v != gROOT->GetVersion()) goodver = kFALSE;
116  }
117  if (!f || !goodver) {
118  if (!gSystem->AccessPathName(pdir, kWritePermission)) {
119  savever = kTRUE;
120  Log(TString::Format("%s: version change"
121  " (current: %s, build: %s): cleaning ... ",
122  pack, gROOT->GetVersion(), v.Data()));
123  // Hard cleanup: go up the dir tree
125  // remove package directory
126  gSystem->Exec(TString::Format("%s %s", kRM, pdir.Data()));
127  // find gunzip...
128  char *gunzip = gSystem->Which(gSystem->Getenv("PATH"), kGUNZIP,
130  if (gunzip) {
131  TString par;
132  par.Form("%s.par", pdir.Data());
133  // untar package
134  TString cmd;
135  cmd.Form(kUNTAR3, gunzip, par.Data());
136  rc = gSystem->Exec(cmd);
137  if (rc != 0) {
138  Error("Build", "failure executing: %s", cmd.Data());
139  } else {
140  // Store md5 in package/PROOF-INF/md5.txt
141  TMD5 *md5local = TMD5::FileChecksum(par);
142  if (md5local) {
143  TString md5f = pdir + "/PROOF-INF/md5.txt";
144  TMD5::WriteChecksum(md5f, md5local);
145  // Go down to the package directory
146  gSystem->ChangeDirectory(pdir);
147  // Cleanup
148  SafeDelete(md5local);
149  } else {
150  Warning("Build", "failure calculating/saving MD5sum for '%s'", par.Data());
151  }
152  }
153  delete [] gunzip;
154  } else {
155  Error("Build", "%s not found", kGUNZIP);
156  rc = -1;
157  }
158  } else {
159  Log(TString::Format("%s: ROOT version inconsistency (current: %s, build: %s):"
160  " directory not writable: cannot re-build!!! ",
161  pack, gROOT->GetVersion(), v.Data()));
162  rc = -1;
163  }
164 
165  if (rc == 0) {
166  // To build the package we execute PROOF-INF/BUILD.sh via a pipe
167  // so that we can send back the log in (almost) real-time to the
168  // (impatient) client. Note that this operation will block, so
169  // the messages from builds on the workers will reach the client
170  // shortly after the master ones.
171  TString ipath(gSystem->GetIncludePath());
172  ipath.ReplaceAll("\"","");
173  TString cmd;
174  cmd.Form("export ROOTINCLUDEPATH=\"%s\" ; PROOF-INF/BUILD.sh", ipath.Data());
175  rc = gSystem->Exec(cmd);
176  if (rc != 0) {
177  Error("Build", "failure executing: %s", cmd.Data());
178  } else {
179  // Success: write version file
180  if (savever) {
181  f = fopen("PROOF-INF/proofvers.txt", "w");
182  if (f) {
183  fputs(gROOT->GetVersion(), f);
184  fputs(TString::Format("\n%s", gROOT->GetGitCommit()), f);
185  fclose(f);
186  }
187  }
188  }
189  }
190  } else {
191  // Notify the user
192  if (gDebug > 0)
193  Info("Build", "no PROOF-INF/BUILD.sh found for package %s", pack);
194  }
195  }
196  // Always return to the initial directory
197  gSystem->ChangeDirectory(ocwd);
198 
199  return rc;
200 }
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 /// Method to load a package taking an option const char *
204 /// Return -1 on error, 0 otherwise
205 
206 Int_t TPackMgr::Load(const char *pack, const char *opts)
207 {
208  TList *optls = new TList;
209  optls->Add(new TObjString(opts));
210  Int_t rc = Load(pack, optls);
211  optls->SetOwner();
212  delete optls;
213  return rc;
214 }
215 
216 ////////////////////////////////////////////////////////////////////////////////
217 /// Method to load a package taking an option list
218 /// Return -1 on error, 0 otherwise
219 
220 Int_t TPackMgr::Load(const char *pack, TList *optls)
221 {
222  Int_t rc = 0;
223  TString emsg;
224 
225  // If already loaded don't do it again
227  Log(TString::Format("error: TPackMgr::Load: package %s already loaded", pack));
228  return 0;
229  }
230 
231  // Which pack mgr has the package?
232  if (!Has(pack)) {
233  // Check the global packages
234  TPackMgr *packmgr = 0;
235  if (!(packmgr = TPackMgr::GetPackMgr(pack, nullptr))) {
236  // Package not found
237  Log(TString::Format("error: TPackMgr::Load: failure locating %s ...", pack));
238  return -1;
239  }
240  // Load from there
241  return packmgr->Load(pack, optls);
242  }
243 
244  // We have the package
245  TString pdir = TString::Format("%s/%s", fDir.Data(), pack);
246 
247  // Check dependencies
248  TString deps = TString::Format("%s/PROOF-INF/depends", pdir.Data());
249  if (!gSystem->AccessPathName(deps)) {
250  TMacro mdeps("deps");
251  if (mdeps.ReadFile(deps) > 0) {
252  Log(TString::Format("info: TPackMgr::Load: checking dependencies for package %s ...", pack));
253  TIter nxl(mdeps.GetListOfLines());
254  TObjString *os = 0;
255  while ((os = (TObjString *)nxl())) {
256  if (!TPackMgr::IsEnabled(os->GetName(), this)) {
257  if (Load(os->GetName(), optls) < 0) {
258  // Package loading failure
259  Log(TString::Format("error: TPackMgr::Load: failure loading dep %s ...", os->GetName()));
260  return -1;
261  }
262  }
263  }
264  }
265  }
266 
267  // Make sure it has been build
268  Int_t chkveropt = kCheckROOT;
269  if (optls) {
270  TParameter<Int_t> *pcv = (TParameter<Int_t> *) optls->FindObject("PROOF_Package_CheckVersion");
271  if (pcv) {
272  chkveropt = pcv->GetVal();
273  optls->Remove(pcv);
274  delete pcv;
275  }
276  }
277  if (Build(pack, chkveropt) < 0) {
278  // Package not found
279  Log(TString::Format("error: TPackMgr::Load: package %s oes not build! ", pack));
280  return -1;
281  }
282 
283  TString ocwd = gSystem->WorkingDirectory();
284  gSystem->ChangeDirectory(pdir);
285 
286  // Shared lock from here
287  TLockPathGuard lp(&fLock, kTRUE);
288 
289  // Check for SETUP.C and execute
290  if (!gSystem->AccessPathName("PROOF-INF/SETUP.C")) {
291  // We need to change the name of the function to avoid problems when we load more packages
292  TString setup;
293  setup.Form("SETUP_%d_%x", gSystem->GetPid(), TString(pack).Hash());
294  // Remove special characters
295  TMacro setupmc("PROOF-INF/SETUP.C");
296  TObjString *setupline = setupmc.GetLineWith("SETUP(");
297  if (setupline) {
298  TString setupstring(setupline->GetString());
299  setupstring.ReplaceAll("SETUP(", TString::Format("%s(", setup.Data()));
300  setupline->SetString(setupstring);
301  } else {
302  // Macro does not contain SETUP()
303  Log(TString::Format("warning: macro '%s/PROOF-INF/SETUP.C' does not contain a SETUP()"
304  " function", pack));
305  }
306 
307  // Load the macro
308  if (!setupmc.Load()) {
309  // Macro could not be loaded
310  Log(TString::Format("error: macro '%s/PROOF-INF/SETUP.C' could not be loaded:"
311  " cannot continue", pack));
312  rc = -1;
313  } else {
314  // Check the signature
315  TFunction *fun = (TFunction *) gROOT->GetListOfGlobalFunctions()->FindObject(setup);
316  if (!fun) {
317  // Notify the upper level
318  Log(TString::Format("error: function SETUP() not found in macro '%s/PROOF-INF/SETUP.C':"
319  " cannot continue", pack));
320  rc = -1;
321  } else {
322  TMethodCall callEnv;
323  // Check the number of arguments
324  if (fun->GetNargs() == 0) {
325  // No arguments (basic signature)
326  callEnv.Init(fun);
327  if (optls && optls->GetSize() > 0) {
328  Log(TString::Format("warning: loaded SETUP() for '%s' does not take any argument:"
329  " the specified argument will be ignored", pack));
330  }
331  } else if (fun->GetNargs() == 1) {
332  TMethodArg *arg = (TMethodArg *) fun->GetListOfMethodArgs()->First();
333  if (arg) {
334  callEnv.Init(fun);
335  // Check argument type
336  TString argsig(arg->GetTitle());
337  if (argsig.BeginsWith("TList")) {
338  callEnv.ResetParam();
339  callEnv.SetParam((Long_t) optls);
340  } else if (argsig.BeginsWith("const char")) {
341  callEnv.ResetParam();
342  TObjString *os = optls ? dynamic_cast<TObjString *>(optls->First()) : 0;
343  if (os) {
344  callEnv.SetParam((Long_t) os->GetName());
345  } else {
346  if (optls && optls->First()) {
347  Log(TString::Format("warning: found object argument of type %s:"
348  " SETUP expects 'const char *': ignoring",
349  optls->First()->ClassName()));
350  }
351  callEnv.SetParam((Long_t) 0);
352  }
353  } else {
354  // Notify the upper level
355  Log(TString::Format("error: unsupported SETUP signature: SETUP(%s)"
356  " cannot continue", arg->GetTitle()));
357  rc = -1;
358  }
359  } else {
360  // Notify the upper level
361  Log("error: cannot get information about the SETUP() argument:"
362  " cannot continue");
363  rc = -1;
364  }
365  } else if (fun->GetNargs() > 1) {
366  // Notify the upper level
367  Log("error: function SETUP() can have at most a 'TList *' argument:"
368  " cannot continue");
369  rc = -1;
370  }
371  // Execute
372  Long_t setuprc = (rc == 0) ? 0 : -1;
373  if (rc == 0) {
374  callEnv.Execute(setuprc);
375  if (setuprc < 0) rc = -1;
376  }
377  }
378  }
379  }
380 
381  gSystem->ChangeDirectory(ocwd);
382 
383  if (rc == 0) {
384  // create link to package in working directory
385  gSystem->Symlink(pdir, pack);
386 
387  // add package to list of include directories to be searched
388  // by ACliC
389  gSystem->AddIncludePath(TString::Format("-I%s", pack));
390 
391  // add package to list of include directories to be searched by CINT
392  gROOT->ProcessLine(TString::Format(".I %s", pack));
393 
394  TPair *pck = (optls && optls->GetSize() > 0) ? new TPair(new TObjString(pack), optls->Clone())
395  : new TPair(new TObjString(pack), 0);
396  if (!fEnabledPackages) {
397  fEnabledPackages = new TList;
399  }
400  fEnabledPackages->Add(pck);
401  }
402 
403  return rc;
404 }
405 
406 
407 ////////////////////////////////////////////////////////////////////////////////
408 /// Method to unload a package.
409 /// Return -1 on error, 0 otherwise
410 
411 Int_t TPackMgr::Unload(const char *pack)
412 {
413  Int_t rc = 0;
414 
415  if (fEnabledPackages && fEnabledPackages->GetSize() > 0) {
416  TPair *ppack = 0;
417  if (pack && strlen(pack) > 0) {
418  if ((ppack = (TPair *) fEnabledPackages->FindObject(pack))) {
419 
420  // Remove entry from include path
421  TString aclicincpath = gSystem->GetIncludePath();
422  TString cintincpath = gInterpreter->GetIncludePath();
423  // remove interpreter part of gSystem->GetIncludePath()
424  aclicincpath.Remove(aclicincpath.Length() - cintincpath.Length() - 1);
425  // remove package's include path
426  aclicincpath.ReplaceAll(TString(" -I") + pack, "");
427  gSystem->SetIncludePath(aclicincpath);
428 
429  //TODO reset interpreter include path
430 
431  // remove entry from enabled packages list
432  delete fEnabledPackages->Remove(ppack);
433  }
434 
435  // Cleanup the link, if there
436  if (!gSystem->AccessPathName(pack))
437  if (gSystem->Unlink(pack) != 0) rc = -1;
438 
439  } else {
440 
441  // Iterate over packages and remove each package
442  TIter nxp(fEnabledPackages);
443  while ((ppack = (TPair *) nxp())) {
444  if (Unload(ppack->GetName()) != 0) rc = -1;
445  }
446 
447  }
448  }
449 
450  // We are done
451  return rc;
452 }
453 
454 ////////////////////////////////////////////////////////////////////////////////
455 /// Method to check if this package manager has package 'pack'.
456 /// Return kTRUE or kFALSE
457 
458 Bool_t TPackMgr::Has(const char *pack)
459 {
460  // always follows BuildPackage so no need to check for PROOF-INF
461  TString pdir = TString::Format("%s/%s", fDir.Data(), pack);
462 
463  // Shared lock from here
464  TLockPathGuard lp(&fLock, kTRUE);
465 
466  if (gSystem->AccessPathName(pdir, kReadPermission) ||
467  gSystem->AccessPathName(pdir + "/PROOF-INF", kReadPermission))
468  return kFALSE;
469 
470  // Relevant directories exist and ar readable
471  return kTRUE;
472 }
473 
474 ////////////////////////////////////////////////////////////////////////////////
475 /// Method to check if 'path' is in the managed directory
476 /// Return kTRUE or kFALSE
477 
478 Bool_t TPackMgr::IsInDir(const char *path)
479 {
480  return strncmp(fDir.Data(), path, fDir.Length()) ? kFALSE : kTRUE ;
481 }
482 
483 ////////////////////////////////////////////////////////////////////////////////
484 /// Method to get the path of the dir for package 'pack'.
485 /// Return -1 in case of error (not found), 0 otherwise
486 
487 Int_t TPackMgr::GetPackDir(const char *pack, TString &pdir)
488 {
489  // Make sure the extension is not ".par"
490  TString pn(pack);
491  if (strstr(pack, ".par")) pn.Remove(pn.Last('.'));
492  pdir.Form("%s/%s", fDir.Data(), pn.Data());
493  if (gSystem->AccessPathName(pdir, kReadPermission)) return -1;
494  return 0;
495 }
496 
497 ////////////////////////////////////////////////////////////////////////////////
498 /// Method to get a semi-colon separated list with the names of the enabled
499 /// packages.
500 
502 {
503  packlist = "";
504  if (!fEnabledPackages) return;
505 
506  TIter nxp(fEnabledPackages);
507  TPair *pck= 0;
508  while ((pck = (TPair *)nxp())) {
509  if (packlist.Length() <= 0)
510  packlist = pck->GetName();
511  else
512  packlist += TString::Format(";%s", pck->GetName());
513  }
514  return;
515 }
516 
517 ////////////////////////////////////////////////////////////////////////////////
518 /// Method to get the path of the PAR file for package 'pack'.
519 /// Return -1 in case of error (not found), 0 otherwise
520 
521 Int_t TPackMgr::GetParPath(const char *pack, TString &path)
522 {
523  // Make sure the extension is ".par"
524  const char *fm = (strstr(pack, ".par")) ? "%s/%s" : "%s/%s.par";
525  path.Form(fm, fDir.Data(), pack);
526  if (gSystem->AccessPathName(path, kReadPermission)) return -1;
527  return 0;
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////////
531 /// Method to get the download dir; create if not existing
532 /// Return -1 in case of error (not found; not created), 0 otherwise
533 
535 {
536  dldir.Form("%s/downloaded", fDir.Data());
537  if (gSystem->AccessPathName(dldir, kReadPermission)) {
538  if (gSystem->mkdir(dldir, kTRUE) != 0) return -1;
539  if (gSystem->AccessPathName(dldir, kReadPermission)) return -1;
540  }
541  return 0;
542 }
543 
544 ////////////////////////////////////////////////////////////////////////////////
545 /// Show available packages
546 ///
547 
548 void TPackMgr::Show(const char *title)
549 {
551  // Scan the list of global packages dirs
553  TPackMgr *pm = 0;
554  while ((pm = (TPackMgr *)nxpm())) {
555  pm->Show(TString::Format("*** Global Package cache %s %s:%s ***\n",
556  pm->GetName(), gSystem->HostName(), pm->GetTitle()));
557  }
558  }
559 
560  if (title && strlen(title) > 0)
561  printf("%s\n", title);
562  else
563  printf("*** Package cache %s:%s ***\n", gSystem->HostName(), fDir.Data());
564  fflush(stdout);
565  // Shared lock from here
566  TLockPathGuard lp(&fLock, kTRUE);
567  gSystem->Exec(TString::Format("%s %s", kLS, fDir.Data()));
568  printf("\n");
569 }
570 
571 ////////////////////////////////////////////////////////////////////////////////
572 /// Clean dir for package 'pack'
573 /// Return -1 in case of error, 0 otherwise
574 ///
575 
576 Int_t TPackMgr::Clean(const char *pack)
577 {
578  // Shared lock from here
579  TLockPathGuard lp(&fLock);
580  Int_t rc = 0;
581  if (pack && strlen(pack)) {
582  // remove package directory and par file
583  rc = gSystem->Exec(TString::Format("%s %s/%s/*", kRM, fDir.Data(), pack));
584  }
585  return rc;
586 }
587 
588 ////////////////////////////////////////////////////////////////////////////////
589 /// Remove package 'pack'
590 /// If 'pack' is null or empty all packages are cleared
591 ///
592 
593 Int_t TPackMgr::Remove(const char *pack, Bool_t dolock)
594 {
595  // Shared lock from here
596  if (dolock) fLock.Lock();
597  Int_t rc1 = 0, rc2 = 0, rc3 = 0;
598  if (pack && strlen(pack)) {
599  // remove package directory and par file
600  TString path = TString::Format("%s/downloaded/%s.par", fDir.Data(), pack);
601  gSystem->Exec(TString::Format("%s %s", kRM, path.Data()));
602  if (!gSystem->AccessPathName(path, kFileExists)) rc1 = -1;
603  path.ReplaceAll("/downloaded/", "/");
604  gSystem->Exec(TString::Format("%s %s", kRM, path.Data()));
605  if (!gSystem->AccessPathName(path, kFileExists)) rc2 = -1;
606  path.Remove(path.Last('.'));
607  gSystem->Exec(TString::Format("%s %s", kRM, path.Data()));
608  if (!gSystem->AccessPathName(path, kFileExists)) rc3 = -1;
609  } else {
610  // Clear all packages
611  rc1 = gSystem->Exec(TString::Format("%s %s/*", kRM, fDir.Data()));
612  }
613  if (dolock) fLock.Unlock();
614  return (rc1 + rc2 + rc3);
615 }
616 
617 ////////////////////////////////////////////////////////////////////////////////
618 /// Get list of available packages
619 /// Returns a pointer to a TList object, transferring ownership to the caller
620 
622 {
623  TList *plist = new TList;
624  void *dir = gSystem->OpenDirectory(fDir);
625  if (dir) {
626  TString pac(gSystem->GetDirEntry(dir));
627  while (pac.Length() > 0) {
628  if (pac.EndsWith(".par")) {
629  pac.ReplaceAll(".par","");
630  plist->Add(new TObjString(pac.Data()));
631  }
632  pac = gSystem->GetDirEntry(dir);
633  }
634  }
635  gSystem->FreeDirectory(dir);
636 
637  return plist;
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////////
641 /// Get list of enabled packages
642 /// Returns a pointer to a TList object, transferring ownership to the caller
643 
645 {
646  TList *epl = nullptr;
647  if (fEnabledPackages && fEnabledPackages->GetSize() > 0) {
648  epl = new TList;
649  TIter nxp(fEnabledPackages);
650  TObject *o = 0;
651  while ((o = nxp())) {
652  epl->Add(new TObjString(o->GetName()));
653  }
654  }
655  return epl;
656 }
657 
658 ////////////////////////////////////////////////////////////////////////////////
659 /// Show enabled packages
660 ///
661 
662 void TPackMgr::ShowEnabled(const char *title)
663 {
665  // Scan the list of global packages dirs
667  TPackMgr *pm = 0;
668  while ((pm = (TPackMgr *)nxpm())) {
669  pm->ShowEnabled(TString::Format("*** Global Package cache %s %s:%s ***\n",
670  pm->GetName(), gSystem->HostName(), pm->GetTitle()));
671  }
672  }
673 
674  if (!fEnabledPackages || fEnabledPackages->GetSize() <= 0) return;
675 
676  if (title && strlen(title) > 0)
677  printf("%s\n", title);
678  else
679  printf("*** Package enabled on %s ***\n", gSystem->HostName());
680  fflush(stdout);
681 
682  TIter next(fEnabledPackages);
683  while (TPair *pck = (TPair *) next()) {
684  printf("%s\n", pck->GetName());
685  }
686 }
687 
688 ////////////////////////////////////////////////////////////////////////////////
689 /// Get MD5 checksum of the PAR file corresponding to given package
690 /// Returns a pointer to a TMD5 object, transferring ownership to the caller
691 
692 TMD5 *TPackMgr::GetMD5(const char *pack)
693 {
694  // Shared lock from here
695  TLockPathGuard lp(&fLock, kTRUE);
696  // PAR file path
697  const char *fm = (strstr(pack, ".par")) ? "%s/%s" : "%s/%s.par";
698  TString parfile = TString::Format(fm, fDir.Data(), pack);
699 
700  return TMD5::FileChecksum(parfile);
701 }
702 
703 
704 ////////////////////////////////////////////////////////////////////////////////
705 /// Read MD5 checksum of the PAR file from the PROOF-INF/md5.txt file.
706 /// Returns a pointer to a TMD5 object, transferring ownership to the caller
707 
708 TMD5 *TPackMgr::ReadMD5(const char *pack)
709 {
710  TString pn(pack);
711  if (pn.EndsWith(".par")) pn.Remove(pn.Last('.'));
712 
713  TString md5f = TString::Format("%s/%s/PROOF-INF/md5.txt", fDir.Data(), pn.Data());
714  TLockPathGuard lp(&fLock, kTRUE);
715  return TMD5::ReadChecksum(md5f);
716 }
717 
718 
719 ////////////////////////////////////////////////////////////////////////////////
720 /// Read MD5 checksum of the PAR file from the PROOF-INF/md5.txt file.
721 /// Returns a pointer to a TMD5 object, transferring ownership to the caller
722 
723 Int_t TPackMgr::Unpack(const char *pack, TMD5 *sum)
724 {
725  Int_t rc = 0;
726  TString fn(pack), pn(pack);
727  if (!fn.EndsWith(".par")) fn += ".par";
728  if (pn.EndsWith(".par")) pn.Remove(pn.Last('.'));
729 
730  // Find gunzip...
731  char *gunzip = gSystem->Which(gSystem->Getenv("PATH"), kGUNZIP, kExecutePermission);
732  if (gunzip) {
733  // untar package
734  TString cmd;
735  cmd.Form(kUNTAR, gunzip, fDir.Data(), fn.Data(), fDir.Data());
736  rc = gSystem->Exec(cmd);
737  if (rc != 0)
738  Error("Unpack", "failure executing: %s (rc: %d)", cmd.Data(), rc);
739  delete [] gunzip;
740  } else {
741  Error("Unpack", "%s not found", kGUNZIP);
742  rc = -2;
743  }
744  // check that fDir/pack now exists
746  // par file did not unpack itself in the expected directory, failure
747  rc = -1;
748  Error("Unpack", "package %s did not unpack into %s", fn.Data(), pn.Data());
749  } else {
750  // store md5 in package/PROOF-INF/md5.txt
751  if (sum) {
752  TString md5f = TString::Format("%s/%s/PROOF-INF/md5.txt", fDir.Data(), pn.Data());
753  TMD5::WriteChecksum(md5f, sum);
754  }
755  }
756 
757  return rc;
758 }
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 /// Install package from par (unpack the file in the directory); par can be an
762 /// URL for remote retrieval. If rmold is kTRUE an existing version of the package
763 /// is removed if existing.
764 /// Returns 0 on success, <0 otherwise
765 
766 Int_t TPackMgr::Install(const char *parpath, Bool_t rmold)
767 {
768  Int_t rc = 0;
769 
770  Info("Install", "installing %s ...", parpath);
771  const char *par = gSystem->ExpandPathName(parpath);
772 
773  // Does par exists?
775  Error("Install", "%s is invalid", par);
776  return -1;
777  }
778  TString parname = gSystem->BaseName(par);
779  TString pack = parname(0, parname.Last('.'));
780  TString dest = TString::Format("%s/%s", fDir.Data(), parname.Data());
781  TString psrc = par, ssrc;
782  TMD5 *sums = 0, *md5 = 0, *md5d = 0;
783 
784  // Check if we need to download: get the remote checksum
785  // Retrieve the checksum of the file, if available
786  // Dowload checksum file, if available
787  TString dldir;
788  if (GetDownloadDir(dldir) != 0) {
789  Error("Install", "could not create/get download directory");
790  return -1;
791  }
792 
794 
795  TString parsum(par);
796  parsum.ReplaceAll(".par", ".md5sum");
797  if (!gSystem->AccessPathName(parsum, kReadPermission)) {
798  ssrc.Form("%s/%s", dldir.Data(), gSystem->BaseName(parsum));
799  if (!TFile::Cp(parsum, ssrc)) {
800  Warning("Install", "could not retrieve %s", parsum.Data());
801  } else {
802  md5 = TMD5::ReadChecksum(ssrc);
803  }
804  }
805 
806  // Do we have already the file?
807  Bool_t parexists = (!gSystem->AccessPathName(dest)) ? kTRUE : kFALSE;
808 
809  Bool_t install = kTRUE;
810  // If yes and we are asked to clean the old one, do it
811  if (parexists) {
812  install = kFALSE;
813  if (rmold) {
814  // Asked to remove: do it
815  if (Remove(pack, kFALSE) < 0) {
816  Error("Install", "could not remove existing version of '%s'", pack.Data());
817  if (md5) delete md5;
818  return -1;
819  }
820  install = kTRUE;
821  } else {
822  if (!md5) {
824  if (ft == TFile::kWeb || ft == TFile::kNet) {
825  psrc.Form("%s/%s", dldir.Data(), parname.Data());
826  if (!TFile::Cp(par, psrc)) {
827  Error("Install", "could not retrieve %s", par);
828  return -1;
829  }
830  }
831  // psrc is either the original par or the downloaded path
832  md5 = TMD5::FileChecksum(psrc);
833  }
834  // Now we need to compare with the local one
835  sums = TMD5::FileChecksum(dest);
836  if (sums && md5 && (*sums != *md5)) install = kTRUE;
837  }
838  }
839  if (sums) delete sums;
840 
841  // Install if required
842  if (install) {
843  if (!TFile::Cp(psrc, dest)) {
844  Error("Install", "could not copy %s to %s", psrc.Data(), dest.Data());
845  if (md5) delete md5;
846  return -1;
847  }
848  }
849  md5d = TMD5::FileChecksum(dest);
850 
851  if (md5 && *md5 != *md5d)
852  Warning("Install", "checksums do not match:\n\tdownloaded:\t%s\n\texpected:\t%s",
853  md5d->AsString(), md5->AsString());
854  if (Unpack(pack, md5d) != 0) {
855  Error("Install", "could not unpack %s", dest.Data());
856  rc = -1;
857  }
858  if (md5) delete md5;
859  if (md5d) delete md5d;
860  return rc;
861 }
862 
863 //---------------------------------------------------------------------------------------------------
864 // Static methods
865 //---------------------------------------------------------------------------------------------------
866 
867 ////////////////////////////////////////////////////////////////////////////////
868 /// Parse one or more paths as possible sources of packages
869 /// Returns number of paths added; or -1 in case of problems
870 
872 {
873  Int_t ng = 0;
874  // List of directories where to look for global packages
875  TString globpack(paths);
876  if (globpack.Length() > 0) {
877  Int_t from = 0;
878  TString ldir;
879  while (globpack.Tokenize(ldir, from, ":")) {
880  if (gSystem->AccessPathName(ldir, kReadPermission)) {
881  ::Warning("TPackMgr::RegisterGlobalPath",
882  "directory for global packages %s does not"
883  " exist or is not readable", ldir.Data());
884  } else {
885  // Add to the list, key will be "G<ng>", i.e. "G0", "G1", ...
886  TString key;
887  key.Form("G%d", ng++);
888  if (!fgGlobalPackMgrList) {
891  }
892  TPackMgr *pmgr = new TPackMgr(ldir);
893  pmgr->SetName(key);
894  fgGlobalPackMgrList->Add(pmgr);
895  ::Info("TPackMgr::RegisterGlobalPath",
896  "manager for global packages directory %s added to the list",
897  ldir.Data());
898  }
899  }
900  }
901  // Number of registered packages
902  return ng;
903 }
904 
905 
906 ////////////////////////////////////////////////////////////////////////////////
907 /// Get the package manager having 'pack'; priority is given to packmgr, if
908 /// defined.
909 /// Returns packmgr or nullptr
910 
911 TPackMgr *TPackMgr::GetPackMgr(const char *pack, TPackMgr *packmgr)
912 {
913  if (packmgr && packmgr->Has(pack)) return packmgr;
914 
916  // Scan the list of global packages managers
918  TPackMgr *pm = 0;
919  while ((pm = (TPackMgr *)nxpm())) {
920  if (pm->Has(pack)) return pm;
921  }
922  }
923  return nullptr;
924 }
925 
926 
927 ////////////////////////////////////////////////////////////////////////////////
928 /// Get the full path to PAR, looking also in the global dirs.
929 /// Returns -1 if not found, 0 if available in global dirs, 1 if it can be
930 /// uploaded from the local package dir.
931 /// For the cases >= 0, par is filled with the path of the PAR file
932 
933 Int_t TPackMgr::FindParPath(TPackMgr *packmgr, const char *pack, TString &par)
934 {
935  // Try the package dir
936  if (packmgr && packmgr->GetParPath(pack, par) == 0) return 1;
937 
938  // Try global package dirs
940  // Scan the list of global packages dirs
942  TPackMgr *pm = 0;
943  while ((pm = (TPackMgr *)nxpm())) {
944  if (pm->GetParPath(pack, par) == 0) {
945  // Package found, stop searching
946  break;
947  }
948  par = "";
949  }
950  if (par.Length() > 0) return 0;
951  }
952  return -1;
953 }
954 
955 ////////////////////////////////////////////////////////////////////////////////
956 /// Check if the package is enabled; priority is given to packmgr, if
957 /// defined.
958 /// Returns kTRUE if enabled
959 
960 Bool_t TPackMgr::IsEnabled(const char *pack, TPackMgr *packmgr)
961 {
962  if (packmgr && packmgr->IsPackageEnabled(pack)) return kTRUE;
963 
965  // Scan the list of global packages managers
967  TPackMgr *pm = 0;
968  while ((pm = (TPackMgr *)nxpm())) {
969  if (pm->IsPackageEnabled(pack)) return kTRUE;
970  }
971  }
972  // Not Enabled
973  return kFALSE;
974 }
static Int_t FindParPath(TPackMgr *packmgr, const char *pack, TString &par)
Get the full path to PAR, looking also in the global dirs.
Definition: TPackMgr.cxx:933
static THashList * fgGlobalPackMgrList
Definition: TPackMgr.h:49
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:932
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition: TSystem.cxx:1276
TList * GetListOfLines() const
Definition: TMacro.h:51
Bool_t IsPackageEnabled(const char *pack)
Definition: TPackMgr.h:82
TMD5 * ReadMD5(const char *pack)
Read MD5 checksum of the PAR file from the PROOF-INF/md5.txt file.
Definition: TPackMgr.cxx:708
The PROOF package manager contains tools to manage packages.
Definition: TPackMgr.h:37
static long int sum(long int i)
Definition: Factory.cxx:2173
void GetEnabledPackages(TString &packlist)
Method to get a semi-colon separated list with the names of the enabled packages. ...
Definition: TPackMgr.cxx:501
Int_t Unlock()
Unlock the directory.
Definition: TLockPath.cxx:80
virtual int GetPid()
Get process id.
Definition: TSystem.cxx:715
Int_t Lock(Bool_t shared=kFALSE)
Definition: TLockPath.cxx:43
static Bool_t IsEnabled(const char *pack, TPackMgr *packmgr=nullptr)
Check if the package is enabled; priority is given to packmgr, if defined.
Definition: TPackMgr.cxx:960
const char *const kGUNZIP
Definition: TProof.h:147
const char * GetName() const
Returns name of object.
Definition: TMap.h:116
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
virtual const char * WorkingDirectory()
Return working directory.
Definition: TSystem.cxx:869
static TMD5 * FileChecksum(const char *file)
Returns checksum of specified file.
Definition: TMD5.cxx:474
const char *const kLS
Definition: TProof.h:143
Collectable string class.
Definition: TObjString.h:28
virtual ~TPackMgr()
Destroy a TPackMgr instance.
Definition: TPackMgr.cxx:64
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:638
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Int_t Unload(const char *pack)
Method to unload a package.
Definition: TPackMgr.cxx:411
Int_t GetParPath(const char *pack, TString &path)
Method to get the path of the PAR file for package &#39;pack&#39;.
Definition: TPackMgr.cxx:521
virtual Bool_t ChangeDirectory(const char *path)
Change directory.
Definition: TSystem.cxx:860
static TPackMgr * GetPackMgr(const char *pack, TPackMgr *packmgr=nullptr)
Get the package manager having &#39;pack&#39;; priority is given to packmgr, if defined.
Definition: TPackMgr.cxx:911
#define gROOT
Definition: TROOT.h:402
Class supporting a collection of lines with C++ code.
Definition: TMacro.h:31
Basic string class.
Definition: TString.h:125
Int_t Clean(const char *pack)
Clean dir for package &#39;pack&#39; Return -1 in case of error, 0 otherwise.
Definition: TPackMgr.cxx:576
Int_t GetPackDir(const char *pack, TString &pdir)
Method to get the path of the dir for package &#39;pack&#39;.
Definition: TPackMgr.cxx:487
int Int_t
Definition: RtypesCore.h:41
Int_t Load(const char *pack, TList *optls=0)
Method to load a package taking an option list Return -1 on error, 0 otherwise.
Definition: TPackMgr.cxx:220
bool Bool_t
Definition: RtypesCore.h:59
TList * fEnabledPackages
Definition: TPackMgr.h:47
const char *const kRM
Definition: TProof.h:142
#define gInterpreter
Definition: TInterpreter.h:526
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1522
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition: TMethodArg.h:31
TString fPfx
Definition: TPackMgr.h:46
TPackMgr(const TPackMgr &)
void Show(const char *title=0)
Show available packages.
Definition: TPackMgr.cxx:548
Int_t Unpack(const char *pack, TMD5 *sum=0)
Read MD5 checksum of the PAR file from the PROOF-INF/md5.txt file.
Definition: TPackMgr.cxx:723
virtual TObject * Clone(const char *newname="") const
Make a clone of an collection using the Streamer facility.
UInt_t Hash(ECaseCompare cmp=kExact) const
Return hash value.
Definition: TString.cxx:616
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
Make a file system directory.
Definition: TSystem.cxx:904
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual Bool_t Cp(const char *dst, Bool_t progressbar=kTRUE, UInt_t buffersize=1000000)
Allows to copy this file to the dst URL.
Definition: TFile.cxx:4848
Int_t Install(const char *par, Bool_t rmold=kFALSE)
Install package from par (unpack the file in the directory); par can be an URL for remote retrieval...
Definition: TPackMgr.cxx:766
TList * GetListOfEnabled() const
Get list of enabled packages Returns a pointer to a TList object, transferring ownership to the calle...
Definition: TPackMgr.cxx:644
TString fDir
Definition: TPackMgr.h:44
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:851
#define SafeDelete(p)
Definition: RConfig.h:509
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1357
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
virtual TObjString * GetLineWith(const char *text) const
Search the first line containing text.
Definition: TMacro.cxx:301
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
Definition: TString.cxx:2365
THashList implements a hybrid collection class consisting of a hash table and a list to store TObject...
Definition: THashList.h:34
This code implements the MD5 message-digest algorithm.
Definition: TMD5.h:44
static EFileType GetType(const char *name, Option_t *option="", TString *prefix=0)
Resolve the file type as a function of the protocol field in &#39;name&#39;.
Definition: TFile.cxx:4665
void SetName(const char *name)
Set the name of the TNamed.
Definition: TPackMgr.h:62
void ShowEnabled(const char *title=0)
Show enabled packages.
Definition: TPackMgr.cxx:662
void Init(const TFunction *func)
Initialize the method invocation environment based on the TFunction object.
virtual const char * Getenv(const char *env)
Get environment variable.
Definition: TSystem.cxx:1638
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2231
TLockPath fLock
Definition: TPackMgr.h:45
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
Definition: TSystem.cxx:1458
Method or function calling interface.
Definition: TMethodCall.h:37
const char * GetTitle() const
Returns title of object.
Definition: TPackMgr.h:63
virtual Bool_t Load() const
Load the macro into the interpreter.
Definition: TMacro.cxx:247
A doubly linked list.
Definition: TList.h:44
TList * GetList() const
Get list of available packages Returns a pointer to a TList object, transferring ownership to the cal...
Definition: TPackMgr.cxx:621
const char * GetName() const
Returns name of object.
Definition: TObjString.h:39
Named parameter, streamable and storable.
Definition: TParameter.h:37
const TString & GetString() const
Definition: TObjString.h:47
EFileType
File type.
Definition: TFile.h:174
Int_t Build(const char *pack, Int_t opt=TPackMgr::kCheckROOT)
Method to build a package.
Definition: TPackMgr.cxx:87
Bool_t IsInDir(const char *path)
Method to check if &#39;path&#39; is in the managed directory Return kTRUE or kFALSE.
Definition: TPackMgr.cxx:478
Int_t GetNargs() const
Number of function arguments.
Definition: TFunction.cxx:164
void SetName(const char *path)
Definition: TLockPath.h:36
virtual TObject * First() const
Return the first object in the list. Returns 0 when list is empty.
Definition: TList.cxx:655
ROOT::R::TRInterface & r
Definition: Object.C:4
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
static Int_t WriteChecksum(const char *file, const TMD5 *md5)
Writes checksum in ASCII format to specified file.
Definition: TMD5.cxx:452
SVector< double, 2 > v
Definition: Dict.h:5
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
Bool_t Gets(FILE *fp, Bool_t chop=kTRUE)
Read one line from the stream, including the , or until EOF.
Definition: Stringio.cxx:198
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2343
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
Ssiz_t Length() const
Definition: TString.h:386
const char * GetName() const
Returns name of object.
Definition: TPackMgr.h:61
virtual Int_t ReadFile(const char *filename)
Read lines in filename in this macro.
Definition: TMacro.cxx:336
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition: TSystem.cxx:661
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:843
#define Printf
Definition: TGeoToOCC.h:18
const Bool_t kFALSE
Definition: RtypesCore.h:88
TString & Remove(Ssiz_t pos)
Definition: TString.h:619
long Long_t
Definition: RtypesCore.h:50
Class used by TMap to store (key,value) pairs.
Definition: TMap.h:102
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2251
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3858
#define ClassImp(name)
Definition: Rtypes.h:359
void ResetParam()
Reset parameter list. To be used before the first call the SetParam().
TList * GetListOfMethodArgs()
Return list containing the TMethodArgs of a TFunction.
Definition: TFunction.cxx:126
virtual const char * HostName()
Return the system&#39;s host name.
Definition: TSystem.cxx:311
virtual int Symlink(const char *from, const char *to)
Create a symbolic link from file1 to file2.
Definition: TSystem.cxx:1348
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:875
TPackMgrLog_t fLogger
Definition: TPackMgr.h:42
static Int_t RegisterGlobalPath(const char *paths)
Parse one or more paths as possible sources of packages Returns number of paths added; or -1 in case ...
Definition: TPackMgr.cxx:871
Bool_t IsNull() const
Definition: TString.h:383
Bool_t Has(const char *pack)
Method to check if this package manager has package &#39;pack&#39;.
Definition: TPackMgr.cxx:458
Mother of all ROOT objects.
Definition: TObject.h:37
Global functions class (global functions are obtained from CINT).
Definition: TFunction.h:28
Int_t GetDownloadDir(TString &dldir)
Method to get the download dir; create if not existing Return -1 in case of error (not found; not cre...
Definition: TPackMgr.cxx:534
virtual void Add(TObject *obj)
Definition: TList.h:87
void Execute(const char *, const char *, int *=0)
Execute method on this object with the given parameter string, e.g.
Definition: TMethodCall.h:64
#define dest(otri, vertexptr)
Definition: triangle.c:1040
const char *const kUNTAR
Definition: TProof.h:144
const char *const kUNTAR3
Definition: TProof.h:146
void SetParam(Long_t l)
Add a long method parameter.
void Log(const char *msg)
Wrapper to notofuer / logger.
Definition: TPackMgr.cxx:73
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:834
R__EXTERN Int_t gDebug
Definition: Rtypes.h:86
Int_t Remove(const char *pack=0, Bool_t dolock=kTRUE)
Remove package &#39;pack&#39; If &#39;pack&#39; is null or empty all packages are cleared.
Definition: TPackMgr.cxx:593
virtual void AddIncludePath(const char *includePath)
Add includePath to the already set include path.
Definition: TSystem.cxx:4025
const AParamType & GetVal() const
Definition: TParameter.h:69
TMD5 * GetMD5(const char *pack)
Get MD5 checksum of the PAR file corresponding to given package Returns a pointer to a TMD5 object...
Definition: TPackMgr.cxx:692
virtual Bool_t ExpandPathName(TString &path)
Expand a pathname getting rid of special shell characters like ~.
Definition: TSystem.cxx:1254
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual Int_t GetSize() const
Definition: TCollection.h:180
static TMD5 * ReadChecksum(const char *file)
Returns checksum stored in ASCII in specified file.
Definition: TMD5.cxx:422
void SetString(const char *s)
Definition: TObjString.h:46
const Bool_t kTRUE
Definition: RtypesCore.h:87
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
static void DefaultLogger(const char *msg)
Definition: TPackMgr.cxx:42
virtual void SetIncludePath(const char *includePath)
IncludePath should contain the list of compiler flags to indicate where to find user defined header f...
Definition: TSystem.cxx:4060
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
const char * Data() const
Definition: TString.h:345