Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TFileInfo.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Andreas-Joachim Peters 20/9/2005
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 TFileInfo
13 \ingroup Base
14 
15 Class describing a generic file including meta information.
16 */
17 
18 #include "Riostream.h"
19 #include "TFileInfo.h"
20 #include "TRegexp.h"
21 #include "TSystem.h"
22 #include "TClass.h"
23 
24 
25 ClassImp(TFileInfo);
26 ClassImp(TFileInfoMeta);
27 
28 ////////////////////////////////////////////////////////////////////////////////
29 /// Constructor.
30 
31 TFileInfo::TFileInfo(const char *in, Long64_t size, const char *uuid,
32  const char *md5, TObject *meta)
33  : fCurrentUrl(0), fUrlList(0), fSize(-1), fUUID(0), fMD5(0),
34  fMetaDataList(0), fIndex(-1)
35 {
36  // Get initializations form the input string: this will set at least the
37  // current URL; but it may set more: see TFileInfo::ParseInput(). Please note
38  // that MD5 sum should be provided as a string in md5ascii form.
39  ParseInput(in);
40 
41  // Now also honour the input arguments: the size
42  if (size > -1) fSize = size;
43  // The UUID
44  if (uuid) {
45  SafeDelete(fUUID);
46  fUUID = new TUUID(uuid);
47  } else if (!fUUID) {
48  fUUID = new TUUID;
49  }
50  // The MD5
51  if (md5) {
52  SafeDelete(fMD5);
53  fMD5 = new TMD5();
54  fMD5->SetDigest(md5); // sets digest from md5ascii representation
55  }
56  // The meta information
57  if (meta) {
58  RemoveMetaData(meta->GetName());
59  AddMetaData(meta);
60  }
61 
62  // Now set the name from the UUID
63  SetName(fUUID->AsString());
64  SetTitle("TFileInfo");
65 
66  // By default we ignore the index
67  ResetBit(TFileInfo::kSortWithIndex);
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 /// Copy constructor.
72 
73 TFileInfo::TFileInfo(const TFileInfo &fi) : TNamed(fi.GetName(), fi.GetTitle()),
74  fCurrentUrl(0), fUrlList(0),
75  fSize(fi.fSize), fUUID(0), fMD5(0),
76  fMetaDataList(0), fIndex(fi.fIndex)
77 {
78  if (fi.fUrlList) {
79  fUrlList = new TList;
80  fUrlList->SetOwner();
81  TIter nxu(fi.fUrlList);
82  TUrl *u = 0;
83  while ((u = (TUrl *)nxu())) {
84  fUrlList->Add(new TUrl(u->GetUrl(), kTRUE));
85  }
86  ResetUrl();
87  }
88  fSize = fi.fSize;
89 
90  if (fi.fUUID)
91  fUUID = new TUUID(fi.fUUID->AsString());
92 
93  if (fi.fMD5)
94  fMD5 = new TMD5(*(fi.fMD5));
95 
96  // Staged and corrupted bits
97  ResetBit(TFileInfo::kStaged);
98  ResetBit(TFileInfo::kCorrupted);
99  if (fi.TestBit(TFileInfo::kStaged)) SetBit(TFileInfo::kStaged);
100  if (fi.TestBit(TFileInfo::kCorrupted)) SetBit(TFileInfo::kCorrupted);
101 
102  if (fi.fMetaDataList) {
103  fMetaDataList = new TList;
104  fMetaDataList->SetOwner();
105  TIter nxm(fi.fMetaDataList);
106  TFileInfoMeta *fim = 0;
107  while ((fim = (TFileInfoMeta *)nxm())) {
108  fMetaDataList->Add(new TFileInfoMeta(*fim));
109  }
110  }
111 
112  // By default we ignore the index
113  ResetBit(TFileInfo::kSortWithIndex);
114 }
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 /// Destructor.
118 
119 TFileInfo::~TFileInfo()
120 {
121  SafeDelete(fMetaDataList);
122  SafeDelete(fUUID);
123  SafeDelete(fMD5);
124  SafeDelete(fUrlList);
125 }
126 
127 ////////////////////////////////////////////////////////////////////////////////
128 /// Parse the input line to extract init information from 'in'; the input
129 /// string is tokenized on ' '; the tokens can be prefixed by the following
130 /// keys:
131 ///
132 /// - `url:<url1>,<url2>,...` URLs for the file; stored in the order given
133 /// - `sz:<size>` size of the file in bytes
134 /// - `md5:<md5_ascii>` MD5 sum of the file in ASCII form
135 /// - `uuid:<uuid>` UUID of the file
136 ///
137 /// - `tree:<name>,<entries>,<first>,<last>`
138 /// meta-information about a tree in the file; the
139 /// should be in the form "<subdir>/tree-name";'entries' is
140 /// the number of entries in the tree; 'first' and 'last'
141 /// define the entry range.
142 ///
143 /// - `obj:<name>,<class>,<entries>`
144 /// meta-information about a generic object in the file;
145 /// the should be in the form "<subdir>/obj-name"; 'class'
146 /// is the object class; 'entries' is the number of occurrences
147 /// for this object.
148 ///
149 /// - `idx:<index>` Index of this file if sorting with index
150 ///
151 /// Multiple occurrences of 'tree:' or 'obj:' can be specified.
152 /// The initializations done via the input string are super-seeded by the ones by other
153 /// parameters in the constructor, if any.
154 /// If no key is given, the token is interpreted as URL(s).
155 
156 void TFileInfo::ParseInput(const char *in)
157 {
158  // Nothing to do if the string is empty
159  if (!in || strlen(in) <= 0) return;
160 
161  TString sin(in), t;
162  Int_t f1 = 0;
163  while (sin.Tokenize(t, f1, " ")) {
164  if (t.BeginsWith("sz:")) {
165  // The size
166  t.Replace(0, 3, "");
167  if (t.IsDigit()) sscanf(t.Data(), "%lld", &fSize);
168  } else if (t.BeginsWith("md5:")) {
169  // The MD5
170  t.Replace(0, 4, "");
171  if (t.Length() >= 32) {
172  fMD5 = new TMD5;
173  if (fMD5->SetDigest(t) != 0)
174  SafeDelete(fMD5);
175  }
176  } else if (t.BeginsWith("uuid:")) {
177  // The UUID
178  t.Replace(0, 5, "");
179  if (t.Length() > 0) fUUID = new TUUID(t);
180  } else if (t.BeginsWith("tree:")) {
181  // A tree
182  t.Replace(0, 5, "");
183  TString nm, se, sf, sl;
184  Long64_t ent = -1, fst= -1, lst = -1;
185  Int_t f2 = 0;
186  if (t.Tokenize(nm, f2, ","))
187  if (t.Tokenize(se, f2, ","))
188  if (t.Tokenize(sf, f2, ","))
189  t.Tokenize(sl, f2, ",");
190  if (!(nm.IsNull())) {
191  if (se.IsDigit()) sscanf(se.Data(), "%lld", &ent);
192  if (sf.IsDigit()) sscanf(sf.Data(), "%lld", &fst);
193  if (sl.IsDigit()) sscanf(sl.Data(), "%lld", &lst);
194  TFileInfoMeta *meta = new TFileInfoMeta(nm, "TTree", ent, fst, lst);
195  RemoveMetaData(meta->GetName());
196  AddMetaData(meta);
197  }
198  } else if (t.BeginsWith("obj:")) {
199  // A generic object
200  t.Replace(0, 4, "");
201  TString nm, cl, se;
202  Long64_t ent = -1;
203  Int_t f2 = 0;
204  if (t.Tokenize(nm, f2, ","))
205  if (t.Tokenize(cl, f2, ","))
206  t.Tokenize(se, f2, ",");
207  if (cl.IsNull()) cl = "TObject";
208  if (!(nm.IsNull())) {
209  if (se.IsDigit()) sscanf(se.Data(), "%lld", &ent);
210  TFileInfoMeta *meta = new TFileInfoMeta(nm, cl, ent);
211  AddMetaData(meta);
212  }
213  } else if (t.BeginsWith("idx:")) {
214  // The size
215  t.Replace(0, 4, "");
216  if (t.IsDigit()) sscanf(t.Data(), "%d", &fIndex);
217  } else {
218  // A (set of) URL(s)
219  if (t.BeginsWith("url:")) t.Replace(0, 4, "");
220  TString u;
221  Int_t f2 = 0;
222  while (t.Tokenize(u, f2, ",")) {
223  if (!(u.IsNull())) AddUrl(u);
224  }
225  }
226  }
227 }
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 /// Set the UUID to the value associated to the string 'uuid'. This is
231 /// useful to set the UUID to the one of the ROOT file during verification.
232 ///
233 /// NB: we do not change the name in here, because this would screw up lists
234 /// of these objects hashed on the name. Those lists need to be rebuild.
235 /// TFileCollection does that in RemoveDuplicates.
236 
237 void TFileInfo::SetUUID(const char *uuid)
238 {
239  if (uuid) {
240  if (fUUID) delete fUUID;
241  fUUID = new TUUID(uuid);
242  }
243 }
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 /// Return the current url.
247 
248 TUrl *TFileInfo::GetCurrentUrl() const
249 {
250  if (!fCurrentUrl)
251  const_cast<TFileInfo*>(this)->ResetUrl();
252  return fCurrentUrl;
253 }
254 
255 ////////////////////////////////////////////////////////////////////////////////
256 /// Iterator function, start iteration by calling ResetUrl().
257 /// The first call to NextUrl() will return the 1st element,
258 /// the seconde the 2nd element etc. Returns 0 in case no more urls.
259 
260 TUrl *TFileInfo::NextUrl()
261 {
262  if (!fUrlList)
263  return 0;
264 
265  TUrl *returl = fCurrentUrl;
266 
267  if (fCurrentUrl)
268  fCurrentUrl = (TUrl*)fUrlList->After(fCurrentUrl);
269 
270  return returl;
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 /// Find an element from a URL. Returns 0 if not found.
275 
276 TUrl *TFileInfo::FindByUrl(const char *url, Bool_t withDeflt)
277 {
278  TIter nextUrl(fUrlList);
279  TUrl *urlelement;
280 
281  TRegexp rg(url);
282  while ((urlelement = (TUrl*) nextUrl())) {
283  if (TString(urlelement->GetUrl(withDeflt)).Index(rg) != kNPOS) {
284  return urlelement;
285  }
286  }
287  return 0;
288 }
289 
290 ////////////////////////////////////////////////////////////////////////////////
291 /// Add a new URL. If 'infront' is TRUE the new url is pushed at the beginning
292 /// of the list; otherwise is pushed back.
293 /// Returns kTRUE if successful, kFALSE otherwise.
294 
295 Bool_t TFileInfo::AddUrl(const char *url, Bool_t infront)
296 {
297  if (FindByUrl(url))
298  return kFALSE;
299 
300  if (!fUrlList) {
301  fUrlList = new TList;
302  fUrlList->SetOwner();
303  }
304 
305  TUrl *newurl = new TUrl(url, kTRUE);
306  // We set the current Url to the first url added
307  if (fUrlList->GetSize() == 0)
308  fCurrentUrl = newurl;
309 
310  if (infront)
311  fUrlList->AddFirst(newurl);
312  else
313  fUrlList->Add(newurl);
314  return kTRUE;
315 }
316 
317 ////////////////////////////////////////////////////////////////////////////////
318 /// Remove an URL. Returns kTRUE if successful, kFALSE otherwise.
319 
320 Bool_t TFileInfo::RemoveUrl(const char *url)
321 {
322  TUrl *lurl;
323  if ((lurl = FindByUrl(url))) {
324  fUrlList->Remove(lurl);
325  if (lurl == fCurrentUrl)
326  ResetUrl();
327  delete lurl;
328  return kTRUE;
329  }
330  return kFALSE;
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 /// Remove URL at given position. Returns kTRUE on success, kFALSE on error.
335 
336 Bool_t TFileInfo::RemoveUrlAt(Int_t i)
337 {
338  TUrl *tUrl;
339  if ((tUrl = dynamic_cast<TUrl *>(fUrlList->At(i))) != NULL) {
340  fUrlList->Remove(tUrl);
341  if (tUrl == fCurrentUrl)
342  ResetUrl();
343  delete tUrl;
344  return kTRUE;
345  }
346 
347  return kFALSE;
348 }
349 
350 ////////////////////////////////////////////////////////////////////////////////
351 /// Set 'url' as current URL, if in the list
352 /// Return kFALSE if not in the list
353 
354 Bool_t TFileInfo::SetCurrentUrl(const char *url)
355 {
356  TUrl *lurl;
357  if ((lurl = FindByUrl(url))) {
358  fCurrentUrl = lurl;
359  return kTRUE;
360  }
361  return kFALSE;
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Set 'url' as current URL, if in the list
366 /// Return kFALSE if not in the list
367 
368 Bool_t TFileInfo::SetCurrentUrl(TUrl *url)
369 {
370  if (url && fUrlList && fUrlList->FindObject(url)) {
371  fCurrentUrl = url;
372  return kTRUE;
373  }
374  return kFALSE;
375 }
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// Add's a meta data object to the file info object. The object will be
379 /// adopted by the TFileInfo and should not be deleted by the user.
380 /// Typically objects of class TFileInfoMeta or derivatives should be added,
381 /// but any class is accepted.
382 /// Returns kTRUE if successful, kFALSE otherwise.
383 
384 Bool_t TFileInfo::AddMetaData(TObject *meta)
385 {
386  if (meta) {
387  if (!fMetaDataList) {
388  fMetaDataList = new TList;
389  fMetaDataList->SetOwner();
390  }
391  fMetaDataList->Add(meta);
392  return kTRUE;
393  }
394  return kFALSE;
395 }
396 
397 ////////////////////////////////////////////////////////////////////////////////
398 /// Remove the metadata object. If meta is 0 remove all meta data objects.
399 /// Returns kTRUE if successful, kFALSE otherwise.
400 
401 Bool_t TFileInfo::RemoveMetaData(const char *meta)
402 {
403  if (fMetaDataList) {
404  if (!meta || strlen(meta) <= 0) {
405  SafeDelete(fMetaDataList);
406  return kTRUE;
407  } else {
408  TObject *o = fMetaDataList->FindObject(meta);
409  if (o) {
410  fMetaDataList->Remove(o);
411  delete o;
412  return kTRUE;
413  }
414  }
415  }
416  return kFALSE;
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////////
420 /// Get meta data object with specified name. If meta is 0
421 /// get first meta data object. Returns 0 in case no
422 /// suitable meta data object is found.
423 
424 TFileInfoMeta *TFileInfo::GetMetaData(const char *meta) const
425 {
426  if (fMetaDataList) {
427  TFileInfoMeta *m;
428  if (!meta || strlen(meta) <= 0)
429  m = (TFileInfoMeta *) fMetaDataList->First();
430  else
431  m = (TFileInfoMeta *) fMetaDataList->FindObject(meta);
432  if (m) {
433  TClass *c = m->IsA();
434  return (c && c->InheritsFrom(TFileInfoMeta::Class())) ? m : 0;
435  }
436  }
437  return 0;
438 }
439 
440 ////////////////////////////////////////////////////////////////////////////////
441 /// Compare TFileInfo object by their first urls.
442 
443 Int_t TFileInfo::Compare(const TObject *obj) const
444 {
445  Int_t rc = 0;
446  if (TestBit(TFileInfo::kSortWithIndex)) {
447  const TFileInfo *fi = dynamic_cast<const TFileInfo *>(obj);
448  if (!fi) {
449  rc = -1;
450  } else {
451  if (fIndex < fi->fIndex) {
452  rc = -1;
453  } else if (fIndex > fi->fIndex) {
454  rc = 1;
455  }
456  }
457  } else {
458  if (this == obj) {
459  rc = 0;
460  } else if (TFileInfo::Class() != obj->IsA()) {
461  rc = -1;
462  } else {
463  rc = (GetFirstUrl()->Compare(((TFileInfo*)obj)->GetFirstUrl()));
464  }
465  }
466  // Done
467  return rc;
468 }
469 
470 ////////////////////////////////////////////////////////////////////////////////
471 /// Print information about this object. If option contains 'L' a long listing
472 /// will be printed (on multiple lines). Otherwise one line is printed with the
473 /// following information: current url, default tree name|class|entries, md5;
474 /// the default tree name is passed via the option ("T:<default_tree>") by the
475 /// owning TFileCollection.
476 
477 void TFileInfo::Print(Option_t *option) const
478 {
479  if (GetMD5()) GetMD5()->Final();
480  TString opt(option);
481  if (opt.Contains("L", TString::kIgnoreCase)) {
482 
483  Printf("UUID: %s\nMD5: %s\nSize: %lld\nIndex: %d",
484  GetUUID() ? GetUUID()->AsString() : "undef",
485  GetMD5() ? GetMD5()->AsString() : "undef",
486  GetSize(), GetIndex());
487 
488  TIter next(fUrlList);
489  TUrl *u;
490  Printf(" === URLs ===");
491  while ((u = (TUrl*)next()))
492  Printf(" URL: %s", u->GetUrl());
493 
494  TIter nextm(fMetaDataList);
495  TObject *m = 0; // can be any TObject not only TFileInfoMeta
496  while ((m = (TObject*) nextm())) {
497  Printf(" === Meta Data Object ===");
498  m->Print();
499  }
500  } else {
501  TString out("current-url-undef -|-|- md5-undef");
502  if (GetCurrentUrl()) out.ReplaceAll("current-url-undef", GetCurrentUrl()->GetUrl());
503  // Extract the default tree name, if any
504  TString deft;
505  if (opt.Contains("T:")) deft = opt(opt.Index("T:")+2, opt.Length());
506  TFileInfoMeta *meta = 0;
507  if (fMetaDataList && !deft.IsNull()) meta = (TFileInfoMeta *) fMetaDataList->FindObject(deft);
508  if (fMetaDataList && !meta) meta = (TFileInfoMeta *) fMetaDataList->First();
509  if (meta) out.ReplaceAll("-|-|-", TString::Format("%s|%s|%lld", meta->GetName(),
510  meta->GetTitle(), meta->GetEntries()));
511  if (GetMD5())
512  out.ReplaceAll("md5-undef", TString::Format("%s", GetMD5()->AsString()));
513  Printf("%s", out.Data());
514  }
515 }
516 
517 
518 ////////////////////////////////////////////////////////////////////////////////
519 /// Create file meta data object.
520 
521 TFileInfoMeta::TFileInfoMeta(const char *objPath, const char *objClass,
522  Long64_t entries, Long64_t first, Long64_t last,
523  Long64_t totbytes, Long64_t zipbytes)
524  : TNamed(objPath, objClass), fEntries(entries), fFirst(first),
525  fLast(last), fTotBytes(totbytes), fZipBytes(zipbytes)
526 {
527  TString p = objPath;
528  if (!p.BeginsWith("/")) {
529  p.Prepend("/");
530  SetName(p);
531  }
532 
533  TClass *c = TClass::GetClass(objClass);
534  fIsTree = (c && c->InheritsFrom("TTree")) ? kTRUE : kFALSE;
535  ResetBit(TFileInfoMeta::kExternal);
536 }
537 
538 ////////////////////////////////////////////////////////////////////////////////
539 /// Create file meta data object.
540 
541 TFileInfoMeta::TFileInfoMeta(const char *objPath, const char *objDir,
542  const char *objClass, Long64_t entries,
543  Long64_t first, Long64_t last,
544  Long64_t totbytes, Long64_t zipbytes)
545  : TNamed(objPath, objClass), fEntries(entries), fFirst(first),
546  fLast(last), fTotBytes(totbytes), fZipBytes(zipbytes)
547 {
548  TString sdir = objDir;
549  if (!sdir.BeginsWith("/"))
550  sdir.Prepend("/");
551  if (!sdir.EndsWith("/"))
552  sdir += "/";
553  sdir += objPath;
554  SetName(sdir);
555 
556  TClass *c = TClass::GetClass(objClass);
557  fIsTree = (c && c->InheritsFrom("TTree")) ? kTRUE : kFALSE;
558  ResetBit(TFileInfoMeta::kExternal);
559 }
560 
561 ////////////////////////////////////////////////////////////////////////////////
562 /// Copy constructor
563 
564 TFileInfoMeta::TFileInfoMeta(const TFileInfoMeta &m)
565  : TNamed(m.GetName(), m.GetTitle())
566 {
567  fEntries = m.fEntries;
568  fFirst = m.fFirst;
569  fLast = m.fLast;
570  fIsTree = m.fIsTree;
571  fTotBytes = m.fTotBytes;
572  fZipBytes = m.fZipBytes;
573  ResetBit(TFileInfoMeta::kExternal);
574  if (m.TestBit(TFileInfoMeta::kExternal)) SetBit(TFileInfoMeta::kExternal);
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 /// Get the object's directory in the ROOT file.
579 
580 const char *TFileInfoMeta::GetDirectory() const
581 {
582  return gSystem->DirName(GetName());
583 }
584 
585 ////////////////////////////////////////////////////////////////////////////////
586 /// Get the object name, with path stripped off. For full path
587 /// use GetName().
588 
589 const char *TFileInfoMeta::GetObject() const
590 {
591  return gSystem->BaseName(GetName());
592 }
593 
594 ////////////////////////////////////////////////////////////////////////////////
595 /// Print information about this object.
596 
597 void TFileInfoMeta::Print(Option_t * /* option */) const
598 {
599  Printf(" Name: %s\n Class: %s\n Entries: %lld\n"
600  " First: %lld\n Last: %lld",
601  fName.Data(), fTitle.Data(), fEntries, fFirst, fLast);
602 }