]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/trains/ChainBuilder.C
Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / trains / ChainBuilder.C
CommitLineData
fdfd93b4 1/**
2 * @file ChainBuilder.C
3 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4 * @date Tue Oct 16 17:54:26 2012
5 *
6 * @brief Build a chain
7 *
8 * @ingroup pwglf_forward_trains_util
9 */
10
11#ifndef CHAINBUILDER_C
12#define CHAINBUILDER_C
13#ifndef __CINT__
bfab35d9 14# include <TUrl.h>
fdfd93b4 15# include <TString.h>
16# include <TChain.h>
bfab35d9 17# include <TChainElement.h>
fdfd93b4 18# include <TSystemDirectory.h>
19# include <TSystem.h>
20# include <TFile.h>
bfab35d9 21# include <TFileInfo.h>
fdfd93b4 22# include <TList.h>
23# include <TError.h>
24# include <TROOT.h>
25# include <TGridCollection.h>
26# include <TFileCollection.h>
27# include <THashList.h>
28# include <TKey.h>
86d83db3 29# include <TRegexp.h>
fdfd93b4 30# include <fstream>
31#else
32class TString;
33class TChain;
34class TSystemDirectory;
bfab35d9 35class TUrl;
fdfd93b4 36#endif
37
38// ===================================================================
39/**
40 * Build a chain
41 *
42 * @ingroup pwglf_forward_trains_util
43 */
44struct ChainBuilder
45{
bfab35d9 46 enum {
47 kVerbose = 0x1,
48 kRecursive = 0x2,
49 kMC = 0x4,
50 kCheck = 0x8,
51 kClean = 0x10,
52 kScan = 0x20
53 };
fdfd93b4 54 enum {
55 kInvalid,
56 kDirectory,
57 kXML,
58 kAscii,
59 kROOT
60 };
61 //------------------------------------------------------------------
bfab35d9 62 static UShort_t CheckSource(TString& src, UShort_t flags)
fdfd93b4 63 {
64 // Local copy
65 TString tmp(src);
66
67 // --- Normalize the path ----------------------------------------
68 if (tmp == ".") tmp = "";
69 if (!tmp.BeginsWith("/")) tmp.Prepend("../");
70 if (gSystem->ExpandPathName(tmp)) {
71 Error("ChainBuilder::CheckSource",
72 "Failed to expand source %s", src.Data());
73 return kInvalid;
74 }
75
76 // --- Stat the file ---------------------------------------------
77 FileStat_t stat;
78 if (gSystem->GetPathInfo(tmp, stat)) return kInvalid;
79 src = tmp;
80
81 // --- Check if directory or file --------------------------------
024ec5ac 82 if (R_ISDIR(stat.fMode)) {
bfab35d9 83 if (flags & kVerbose)
84 Info("ChainBuilder::CheckSource", "%s is a directory", tmp.Data());
024ec5ac 85 return kDirectory;
86 }
fdfd93b4 87
88 // --- check file type -------------------------------------------
89 TString type(gSystem->GetFromPipe(Form("file -b %s", src.Data())));
bfab35d9 90 if ((flags & kVerbose))
91 Info("ChainBuilder::CheckSource", "file -b %s -> %s",
92 tmp.Data(), type.Data());
024ec5ac 93 UShort_t ret = kInvalid;
94 if (type.Contains("ROOT")) ret = kROOT;
95 else if (type.Contains("XML")) ret = kXML;
96 else if (type.Contains("ASCII")) ret = kAscii;
fdfd93b4 97
024ec5ac 98 if (ret == kInvalid) {
99 Error("ChainBuilder::CheckSource",
100 "Do not now how to process %s of type %s",
101 src.Data(), type.Data());
102 }
103 return ret;
fdfd93b4 104 }
105 //------------------------------------------------------------------
106 /**
bfab35d9 107 * Create a TChain from a URL specification.
108 *
109 * The URL should have the format
110 *
111 * @verbatim
112 * PROTOCOL://PATH?OPTIONS#TREENAME
113 * @endverbatim
114 *
115 * where
116 * - @c PROTOCOL is any protocol
117 * - @c PATH is a file, top-directory, file containing a
118 * TFileCollection, ASCII file with list of files, etc.
119 * - @c OPTIONS is a list of options, separate by @c &
120 * - @c TREENAME is the tree name
121 *
122 * @c OPTIONS can be one or more of
123 * - @c mc Also check for auxiliary MC files
124 * - @c recursive When scanning directories, do so recursively
125 * - @c verbose Be verbose
126 * - @c check Check files by trying to open them
127 * - @c clean Remove invalid files
128 * - @c pattern=PATTERN Search pattern when scanning directories
129 *
130 * @param url The input url
131 *
132 * @return Pointer to newly allocated TChain object or null
133 */
134 static TChain* Create(const TUrl& url)
135 {
136 TString source = url.GetFile();
137 TString treeName = url.GetAnchor();
138 TString pattern = "";
139 UShort_t flags = 0;
140 TString options = url.GetOptions();
141 TObjArray* tokens = options.Tokenize("&");
142 TObjString* token = 0;
143 TIter next(tokens);
144 while ((token = static_cast<TObjString*>(next()))) {
145 const TString& str = token->String();
146 if (str.EqualTo("mc", TString::kIgnoreCase))
147 flags |= kMC;
148 else if (str.EqualTo("recursive", TString::kIgnoreCase))
149 flags |= kRecursive;
150 else if (str.EqualTo("verbose", TString::kIgnoreCase))
151 flags |= kVerbose;
152 else if (str.EqualTo("check", TString::kIgnoreCase))
153 flags |= kCheck;
154 else if (str.EqualTo("clean", TString::kIgnoreCase))
155 flags |= kClean;
156 else if (str.EqualTo("scan", TString::kIgnoreCase))
157 flags |= kScan;
158 else if (str.BeginsWith("pattern=", TString::kIgnoreCase)) {
159 Int_t eq = str.Index("=");
160 pattern = str(eq+1, str.Length()-eq-1);
161 pattern.ReplaceAll("@", "#");
162 }
163 else
164 Warning("", "Option %s unknown", str.Data());
165 }
166 delete tokens;
167
168 TString tmp(source);
169 UShort_t type = CheckSource(tmp, flags);
170
171 return Create(type, tmp, treeName, pattern, flags);
172 }
173 //------------------------------------------------------------------
174 /**
175 * Create a chain
176 *
177 * @param src Source
178 * @param treeName Tree name
179 * @param pattern Pattern for scans
180 * @param mc If true, check for MC files
181 * @param recursive If true, scan recursively
182 * @param verbose If true, be verbose
183 * @param checkFiles If true, check that files can be opened
184 * @param removeFiles If true, remove bad files
fdfd93b4 185 *
bfab35d9 186 * @return Pointer to newly allocated TChain or null
fdfd93b4 187 */
188 static TChain* Create(const TString& src,
189 const TString& treeName,
190 const TString& pattern,
191 Bool_t mc,
bfab35d9 192 Bool_t recursive,
193 Bool_t verbose=false,
194 Bool_t checkFiles=false,
195 Bool_t removeFiles=false)
196 {
197 UShort_t flags = 0;
198 if (verbose) flags |= kVerbose;
199 if (recursive) flags |= kRecursive;
200 if (mc) flags |= kMC;
201 if (checkFiles) flags |= kCheck;
202 if (removeFiles) flags |= kClean;
203
204 TString tmp(src);
205 UShort_t type = CheckSource(tmp, flags);
206
207 return Create(type, tmp, treeName, pattern, flags);
208 }
209 //------------------------------------------------------------------
210 /**
211 * Create a chain
212 *
213 * @param type Type of input
214 * @param src Source
215 * @param treeName Tree name
216 * @param pattern Pattern for scans
217 * @param mc If true, check for MC files
218 * @param recursive If true, scan recursively
219 * @param verbose If true, be verbose
220 * @param checkFiles If true, check that files can be opened
221 * @param removeFiles If true, remove bad files
222 *
223 * @return Pointer to newly allocated TChain or null
224 */
225 static TChain* Create(UShort_t type,
226 const TString& src,
227 const TString& treeName,
228 const TString& pattern,
229 Bool_t mc,
230 Bool_t recursive,
231 Bool_t verbose=false,
232 Bool_t checkFiles=false,
233 Bool_t removeFiles=false)
fdfd93b4 234 {
024ec5ac 235 // Info("ChainBuilder::Create",
236 // "src=%s treeName=%s pattern=%s mc=%s recursive=%s",
237 // src.Data(), treeName.Data(), pattern.Data(),
238 // (mc ? "true" : "false"), (recursive ? "true" : "false"));
bfab35d9 239 // --- Create flags
240 UShort_t flags = 0;
241 if (verbose) flags |= kVerbose;
242 if (recursive) flags |= kRecursive;
243 if (mc) flags |= kMC;
244 if (checkFiles) flags |= kCheck;
245 if (removeFiles) flags |= kClean;
fdfd93b4 246
bfab35d9 247 return Create(type, src, treeName, pattern, flags);
fdfd93b4 248 }
249 //------------------------------------------------------------------
250 /**
bfab35d9 251 * Create a chain from the inputs
252 *
253 * @param type Type of input
254 * @param src Source
255 * @param treeName Tree name
256 * @param pattern Pattern for scans
257 * @param flags Flags
fdfd93b4 258 *
bfab35d9 259 * @return Pointer to newly allocated TChain object or null
fdfd93b4 260 */
261 static TChain* Create(UShort_t type,
262 const TString& src,
263 const TString& treeName,
bfab35d9 264 const TString& pattern,
265 UShort_t flags)
fdfd93b4 266 {
267 // --- check input -----------------------------------------------
268 if (type == kInvalid) {
269 Error("ChainBuilder::Create", "Source %s isn't a file or directory",
270 src.Data());
271 return 0;
272 }
024ec5ac 273
fdfd93b4 274 TString tN(treeName);
275 if (tN.IsNull())
276 Warning("ChainBuilder::Create", "No tree name specified, assuming T");
277
278 TString pat(pattern);
279 if (pat.IsNull()) {
7095962e
CHC
280 if (tN.EqualTo("esdTree")) pat = "AliESD*";
281 else if (tN.EqualTo("aodTree")) pat = "AliAOD*";
bfab35d9 282 if ((flags & kVerbose)) Info("", "Pattern set to %s", pat.Data());
fdfd93b4 283 }
bfab35d9 284 if ((flags & kVerbose))
285 Info("ChainBuilder::Create", "Type=%s, tree=%s, pattern=%s",
286 (type == kDirectory ? "directory" :
287 type == kXML ? "XML" :
288 type == kAscii ? "ASCII" :
289 type == kROOT ? "ROOT" : "unknown"),
290 tN.Data(), pat.Data());
291
fdfd93b4 292 // --- Create output ---------------------------------------------
293 TChain* chain = new TChain(tN);
294
bfab35d9 295 // --- ZIP archives ----------------------------------------------
296 TString anchor;
297 TString tmp(pat);
298 ExtractAnchor(pat, anchor);
299 if ((flags & kVerbose))
300 Info("", "Full pattern: '%s' filename pattern: '%s' anchor: '%s'",
301 tmp.Data(), pat.Data(), anchor.Data());
302
fdfd93b4 303 // --- execute based on type
304 Bool_t ret = true;
305 switch (type) {
bfab35d9 306 case kROOT: ret = CreateFromFile(chain, src, anchor, flags); break;
fdfd93b4 307 case kXML: ret = CreateFromXML(chain, src); break;
308 case kAscii: ret = CreateFromList(chain, src); break;
309 case kDirectory: ret = CreateFromDirectory(chain, src,
bfab35d9 310 pat, anchor,
311 flags); break;
fdfd93b4 312 default: ret = false;
313 }
314
315 // --- Clean-up --------------------------------------------------
316 if (chain->GetListOfFiles()->GetEntries() <= 0) ret = false;
317 if (!ret) {
318 delete chain;
319 chain = 0;
320 }
321 return chain;
322 }
bfab35d9 323 //------------------------------------------------------------------
1de8812e 324 /**
325 * Create a collection
326 *
327 * @param output Output file
328 * @param url Input url
329 */
bfab35d9 330 static void CreateCollection(const TString& output,
331 const TUrl& url)
332 {
333 TChain* chain = Create(url);
334 if (!chain) return;
335
336 CreateCollection(output, chain);
337 }
338 //------------------------------------------------------------------
1de8812e 339 /**
340 * Create a collection
341 *
342 * @param output Input url
343 * @param chain Chain to make collection from
344 */
bfab35d9 345 static void CreateCollection(const TString& output,
346 const TChain* chain)
347 {
348 if (!chain) return;
a19faec0 349 TDirectory* savDir = gDirectory;
bfab35d9 350 TFile* out = TFile::Open(output, "RECREATE");
d7a13787 351 if (!out) {
352 Error("", "Failed to open %s for output", output.Data());
353 return;
354 }
bfab35d9 355 TFileCollection* collection = new TFileCollection(chain->GetName());
356 TObjArray* files = chain->GetListOfFiles();
357 TChainElement* element = 0;
358 TIter next(files);
359
360
361 collection->SetDefaultTreeName(chain->GetName());
871d7b56 362 Long64_t nEntries = 0;
bfab35d9 363 while ((element = static_cast<TChainElement*>(next()))) {
364 Info("", "Element: '%s' - '%s' %lld",
365 element->GetName(), element->GetTitle(),
366 element->GetEntries());
367 TFileInfo* info = new TFileInfo(element->GetTitle());
368 TFileInfoMeta* meta = new TFileInfoMeta(Form("/%s",element->GetName()),
369 "TTree", element->GetEntries());
370 info->AddMetaData(meta);
371 info->SetBit(TFileInfo::kStaged);
372 // info->AddUrl(Form("file://%s", element->GetTitle()));
373 collection->Add(info);
374
871d7b56
CHC
375 Long64_t n = element->GetEntries();
376 if (n >= 0) nEntries += n;
377
bfab35d9 378 }
379 collection->Update();
871d7b56
CHC
380 TFileInfoMeta* cMeta = new TFileInfoMeta(chain->GetName(),
381 "TTree", nEntries);
382 collection->AddMetaData(cMeta);
a19faec0 383 out->cd();
bfab35d9 384 collection->Write();
871d7b56 385 Printf("A total of %lld entries", nEntries);
bfab35d9 386 // collection->Print("MFL");
387 out->Close();
a19faec0 388 savDir->cd();
bfab35d9 389 }
390 //------------------------------------------------------------------
1de8812e 391 /**
392 * Exrtact the anchor
393 *
394 * @param src Source url
395 * @param anchor On return, contains the anchor
396 */
bfab35d9 397 static void ExtractAnchor(TString& src, TString& anchor)
398 {
399 anchor = "";
400 Int_t idxHash = src.Index("#");
401
402 if (idxHash == kNPOS) return;
403
404 TString tmp = src(0,idxHash);
405 anchor = src(idxHash+1, src.Length()-idxHash-1);
406 src = tmp;
407 }
408
fdfd93b4 409 //------------------------------------------------------------------
410 /**
411 * Create a chain consiting of a single file
412 *
33438b4c 413 * @param chain The chain
1de8812e 414 * @param anchor Anchor (tree name)
33438b4c 415 * @param src File name.
1de8812e 416 * @param flags Flags
fdfd93b4 417 *
418 * @return Chain or null
419 */
bfab35d9 420 static Bool_t CreateFromFile(TChain* chain,
421 const TString& src,
422 const TString& anchor,
423 UShort_t flags=0)
fdfd93b4 424 {
425 // Info("CreateFromFile", "Making from single file %s", src.Data());
bfab35d9 426
427 if (!CheckFile(src, anchor, chain, flags)) return false;
fdfd93b4 428 return true;
429 }
430 //------------------------------------------------------------------
431 /**
432 * Create a chain from an XML containing an collection
433 *
434 * @return Newly allocated chain or null
435 */
436 static Bool_t CreateFromXML(TChain* chain, const TString& src)
437 {
024ec5ac 438 // Info("ChainBuilder::CreateFromXML", "Create from XML");
fdfd93b4 439 Long_t ret = gROOT->ProcessLine(Form("TAlienCollection(\"%s\")",
440 src.Data()));
441 if (!ret) {
442 Error("ChainBuilder::CreateFromXML",
443 "Cannot create AliEn collection from XML file %s", src.Data());
444 return false;
445 }
446
447 TGridCollection* collection = reinterpret_cast<TGridCollection*>(ret);
73b32206 448#if 0
fdfd93b4 449 if (!collection) {
450 Error("ChainBuilder::CreateFromXML",
451 "Cannot create AliEn collection from XML file %s", src.Data());
452 return false;
453 }
73b32206 454#endif
455
fdfd93b4 456 collection->Reset();
457 while (collection->Next()) chain->Add(collection->GetTURL(""));
458
459 return true;
460 }
461 //------------------------------------------------------------------
462 /**
463 * Create a chain from a file containing a list of files
464 *
465 * @return Newly allocated chain or null
466 */
bfab35d9 467 static Bool_t CreateFromList(TChain* chain,
468 const TString& src,
469 UShort_t flags=0)
fdfd93b4 470 {
024ec5ac 471 // Info("ChainBuilder::CreateFromList", "Creating from list");
fdfd93b4 472 std::ifstream in(src.Data());
473 if (!in) {
474 Error("ChainBuilder::CreateFromList",
475 "Failed to open list %s", src.Data());
476 return false;
477 }
478
479 while (in.good()) {
480 TString line;
481 line.ReadToDelim(in);
482 TString l(line.Strip(TString::kBoth));
483 if (l.IsWhitespace() || l.BeginsWith("#")) continue;
484
bfab35d9 485 TString anchor;
486 ExtractAnchor(l, anchor);
487 if (!CheckFile(l, anchor, chain, flags))
fdfd93b4 488 Warning("ChainBuilder::CreateFromList",
489 "Failed to add %s to chain", l.Data());
490 }
491 return true;
492 }
493 //------------------------------------------------------------------
494 /**
495 * Make a chain from a base directory, pattern, and treename -
496 * possibly recursively
497 *
498 * @return true on success
499 */
500 static Bool_t CreateFromDirectory(TChain* chain,
501 const TString& src,
502 const TString& pattern,
bfab35d9 503 const TString& anchor,
504 UShort_t flags)
fdfd93b4 505 {
506 // Info("", "Scanning src=%s, pattern=%s, mc=%d recursive=%d",
024ec5ac 507 // src.Data(), pattern.Data(), mc, recursive);
fdfd93b4 508 // Save current directory
509 TString savdir(gSystem->WorkingDirectory());
510 TSystemDirectory d(gSystem->BaseName(src.Data()), src.Data());
bfab35d9 511 if (flags & kVerbose) Info("", "Will scan %s", d.GetTitle());
512 if (!ScanDirectory(chain, &d, pattern, anchor, flags))
513 return false;
fdfd93b4 514 // Go back to the saved directory
515 gSystem->ChangeDirectory(savdir);
516
517 return true;
518 }
bfab35d9 519 static void RemoveFile(const TString& path)
520 {
521 Info("", "Removing bad file %s", path.Data());
522 gSystem->RedirectOutput("/dev/null", "w");
871d7b56
CHC
523 // gSystem->Unlink(path);
524 gSystem->Rename(path, Form("%s.bad", path.Data()));
bfab35d9 525 gSystem->RedirectOutput(0);
526 }
fdfd93b4 527 //------------------------------------------------------------------
528 /**
529 * Check if we can add a file to the chain
530 *
531 * @param path Full path to file
1de8812e 532 * @param anchor Anchor (tree name)
fdfd93b4 533 * @param chain Chain
1de8812e 534 * @param flags Some flags
fdfd93b4 535 *
536 * @return true on success, false otherwise
537 */
bfab35d9 538 static Bool_t CheckFile(const TString& path,
539 const TString& anchor,
540 TChain* chain,
541 UShort_t flags=0)
fdfd93b4 542 {
543 // Info("", "Checking %s", path.Data());
bfab35d9 544 TString fn = path;
545 if (!anchor.IsNull()) fn.Append(TString::Format("#%s", anchor.Data()));
546
fdfd93b4 547 gSystem->RedirectOutput("/dev/null", "w");
bfab35d9 548 TFile* test = TFile::Open(fn, "READ");
fdfd93b4 549 gSystem->RedirectOutput(0);
550 if (!test) {
bfab35d9 551 Warning("ChainBuilder::CheckFile", "Failed to open %s", fn.Data());
552 if (flags & kClean) RemoveFile(path);
fdfd93b4 553 return false;
554 }
bfab35d9 555
556 Bool_t ok = false;
557 TObject* o = test->Get(chain->GetName());
558 TTree* t = dynamic_cast<TTree*>(o);
559 TFileCollection* c = dynamic_cast<TFileCollection*>(o);
560 if (t) {
561 test->Close();
562 ok = true;
563 if (flags & kMC) {
564 const char* auxs[] = { "galice", "Kinematics", "TrackRefs", 0 };
565 const char** aux = auxs;
566 while ((*aux)) {
567 TString t1;
568 if (anchor.IsNull())
569 t1 = gSystem->ConcatFileName(gSystem->DirName(path.Data()),
570 Form("%s.root", *aux));
571 else
572 t1 = TString::Format("%s#%s.root", path.Data(), *aux);
573
574 TFile* t2 = TFile::Open(t1, "READ");
575 if (!t2) {
576 Error("", "Needed MC file %s not found", t1.Data());
577 ok = false;
578 break;
579 }
580 t2->Close();
581 aux++;
582 }
583 }
584 if (ok) chain->Add(fn, kScan ? -1 : TChain::kBigNumber);
585 } else if (c) {
586 chain->AddFileInfoList(c->GetList());
587 ok = true;
588 } else {
fdfd93b4 589 // Let's try to find a TFileCollection
590 TList* l = test->GetListOfKeys();
591 TIter next(l);
592 TKey* k = 0;
fdfd93b4 593 while ((k = static_cast<TKey*>(next()))) {
594 TString cl(k->GetClassName());
595 if (!cl.EqualTo("TFileCollection")) continue;
bfab35d9 596 c = dynamic_cast<TFileCollection*>(k->ReadObj());
597 if (!c) {
73b32206 598 Warning("", "Returned collection invalid");
599 continue;
600 }
024ec5ac 601 // Info("", "Adding file collection");
bfab35d9 602 chain->AddFileInfoList(c->GetList());
fdfd93b4 603 ok = true;
604 }
fdfd93b4 605 test->Close();
fdfd93b4 606 }
bfab35d9 607
608 if (!ok) {
609 Warning("ChainBuilder::CheckFile",
610 "The file %s does not contain the tree %s or a file collection",
611 path.Data(), chain->GetName());
612 if (flags & kClean) RemoveFile(path);
613 }
614 return ok;
fdfd93b4 615 }
616 //------------------------------------------------------------------
617 /**
618 * Scan directory @a dir (possibly recursive) for tree files to add
619 * to the chain. This does not follow sym-links
620 *
621 * @param dir Directory to scan
622 * @param chain Chain to add to
33438b4c 623 * @param pattern File name pattern
1de8812e 624 * @param anchor Anchor (tree name)
625 * @param flags Flags
fdfd93b4 626 *
627 * @return true if any files where added
628 */
629 static Bool_t ScanDirectory(TChain* chain,
630 TSystemDirectory* dir,
631 const TString& pattern,
bfab35d9 632 const TString& anchor,
633 UShort_t flags)
fdfd93b4 634 {
635 // Assume failure
636 Bool_t ret = false;
86d83db3 637 TRegexp wild(pattern, true);
fdfd93b4 638
639 // Get list of files, and go back to old working directory
640 TString oldDir(gSystem->WorkingDirectory());
641 TList* files = dir->GetListOfFiles();
642 if (!gSystem->ChangeDirectory(oldDir)) {
643 Error("ChainBuilder::ScanDirectory", "Failed to go back to %s",
644 oldDir.Data());
645 return false;
646 }
647 if (!files) {
648 Warning("ChainBuilder::ScanDirectory", "No files");
649 return false;
650 }
651
652 TList toAdd;
653 toAdd.SetOwner();
fdfd93b4 654
655 // Sort list of files and check if we should add it
656 files->Sort();
657 TIter next(files);
658 TSystemFile* file = 0;
659 while ((file = static_cast<TSystemFile*>(next()))) {
660 TString name(file->GetName());
661 TString title(file->GetTitle());
662 TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data()));
fdfd93b4 663 if (file->IsA()->InheritsFrom(TSystemDirectory::Class())) full = title;
664 // Ignore special links
665 if (name == "." || name == "..") {
666 // Info("ChainBuilder::ScanDirectory", "Ignoring %s", name.Data());
667 continue;
668 }
bfab35d9 669 if ((flags & kVerbose)) Info("", "Got file %s", full.Data());
fdfd93b4 670
671 FileStat_t fs;
672 if (gSystem->GetPathInfo(full.Data(), fs)) {
673 Warning("ChainBuilder::ScanDirectory", "Cannot stat %s (%s)",
674 full.Data(), gSystem->WorkingDirectory());
675 continue;
676 }
677 // Check if this is a directory
678 if (file->IsDirectory(full)) {
bfab35d9 679 if ((flags & kVerbose)) Info("", "Recursive scan of %s", full.Data());
680 if ((flags & kRecursive)) {
fdfd93b4 681 // if (title[0] == '/')
682 TSystemDirectory* d = new TSystemDirectory(file->GetName(),
683 full.Data());
bfab35d9 684 if (ScanDirectory(chain, d, pattern, anchor, flags))
fdfd93b4 685 ret = true;
686 delete d;
687 }
688 continue;
689 }
690
691 // If this is not a root file, ignore
bfab35d9 692 if (!name.EndsWith(".root") && !name.EndsWith(".zip")) {
693 if ((flags & kVerbose))
694 Info("ScanDirectory", "File %s does not end in .root/.zip",
695 name.Data());
fdfd93b4 696 continue;
697 }
698
699 // If this file does not contain AliESDs, ignore
86d83db3 700 if (!name.Contains(wild)) {
d7a13787 701 if ((flags & kVerbose))
702 Info("ChainBuilder::ScanDirectory",
703 "%s does not match pattern %s",
704 name.Data(), pattern.Data());
fdfd93b4 705 continue;
706 }
707
708 // Add
709 // Info("ChainBuilder::ScanDirectory", "Adding %s", full.Data());
710 toAdd.Add(new TObjString(full));
711 }
712
fdfd93b4 713 TIter nextAdd(&toAdd);
714 TObjString* s = 0;
715 Int_t added = 0;
716 while ((s = static_cast<TObjString*>(nextAdd()))) {
717 // Info("ChainBuilder::ScanDirectory",
718 // "Adding %s", s->GetString().Data());
719 TString fn = s->GetString();
bfab35d9 720 if (!CheckFile(fn, anchor, chain, flags)) continue;
fdfd93b4 721
722 added++;
723 }
724 if (added > 0) ret = true;
725
726 gSystem->ChangeDirectory(oldDir);
727 return ret;
728 }
729};
730#endif
86d83db3 731//
732// EOF
733//