3 * @author Christian Holm Christensen <cholm@master.hehi.nbi.dk>
4 * @date Tue Oct 16 17:54:26 2012
8 * @ingroup pwglf_forward_trains_util
11 #ifndef CHAINBUILDER_C
12 #define CHAINBUILDER_C
16 # include <TSystemDirectory.h>
22 # include <TGridCollection.h>
23 # include <TFileCollection.h>
24 # include <THashList.h>
30 class TSystemDirectory;
33 // ===================================================================
37 * @ingroup pwglf_forward_trains_util
48 //------------------------------------------------------------------
49 static UShort_t CheckSource(TString& src)
54 // --- Normalize the path ----------------------------------------
55 if (tmp == ".") tmp = "";
56 if (!tmp.BeginsWith("/")) tmp.Prepend("../");
57 if (gSystem->ExpandPathName(tmp)) {
58 Error("ChainBuilder::CheckSource",
59 "Failed to expand source %s", src.Data());
63 // --- Stat the file ---------------------------------------------
65 if (gSystem->GetPathInfo(tmp, stat)) return kInvalid;
68 // --- Check if directory or file --------------------------------
69 if (R_ISDIR(stat.fMode)) return kDirectory;
71 // --- check file type -------------------------------------------
72 TString type(gSystem->GetFromPipe(Form("file -b %s", src.Data())));
73 if (type.Contains("ROOT")) return kROOT;
74 else if (type.Contains("XML")) return kXML;
75 else if (type.Contains("ASCII")) return kAscii;
77 Error("ChainBuilder::CheckSource",
78 "Do not now how to process %s of type %s",
79 src.Data(), type.Data());
82 //------------------------------------------------------------------
84 * Create the chain. User is owner.
86 * @return Null in case of problems, chain otherwise
88 static TChain* Create(const TString& src,
89 const TString& treeName,
90 const TString& pattern,
95 UShort_t type = CheckSource(tmp);
97 return Create(type, tmp, treeName, pattern, mc, recursive);
99 //------------------------------------------------------------------
101 * Create the chain. User is owner.
103 * @return Null in case of problems, chain otherwise
105 static TChain* Create(UShort_t type,
107 const TString& treeName,
108 const TString& pattern,
112 // --- check input -----------------------------------------------
113 if (type == kInvalid) {
114 Error("ChainBuilder::Create", "Source %s isn't a file or directory",
118 TString tN(treeName);
120 Warning("ChainBuilder::Create", "No tree name specified, assuming T");
122 TString pat(pattern);
124 if (tN.EqualTo("esdTree")) pat = "AliESD";
125 else if (tN.EqualTo("aodTree")) pat = "AliAOD";
128 // --- Create output ---------------------------------------------
129 TChain* chain = new TChain(tN);
131 // --- execute based on type
134 case kROOT: ret = CreateFromFile(chain, src); break;
135 case kXML: ret = CreateFromXML(chain, src); break;
136 case kAscii: ret = CreateFromList(chain, src); break;
137 case kDirectory: ret = CreateFromDirectory(chain, src,
140 default: ret = false;
143 // --- Clean-up --------------------------------------------------
144 if (chain->GetListOfFiles()->GetEntries() <= 0) ret = false;
151 //------------------------------------------------------------------
153 * Create a chain consiting of a single file
155 * @param fn File name.
157 * @return Chain or null
159 static Bool_t CreateFromFile(TChain* chain, const TString& src)
161 // Info("CreateFromFile", "Making from single file %s", src.Data());
162 if (!CheckFile(src, chain)) return false;
165 //------------------------------------------------------------------
167 * Create a chain from an XML containing an collection
169 * @return Newly allocated chain or null
171 static Bool_t CreateFromXML(TChain* chain, const TString& src)
173 Long_t ret = gROOT->ProcessLine(Form("TAlienCollection(\"%s\")",
176 Error("ChainBuilder::CreateFromXML",
177 "Cannot create AliEn collection from XML file %s", src.Data());
181 TGridCollection* collection = reinterpret_cast<TGridCollection*>(ret);
183 Error("ChainBuilder::CreateFromXML",
184 "Cannot create AliEn collection from XML file %s", src.Data());
189 while (collection->Next()) chain->Add(collection->GetTURL(""));
193 //------------------------------------------------------------------
195 * Create a chain from a file containing a list of files
197 * @return Newly allocated chain or null
199 static Bool_t CreateFromList(TChain* chain, const TString& src)
201 std::ifstream in(src.Data());
203 Error("ChainBuilder::CreateFromList",
204 "Failed to open list %s", src.Data());
210 line.ReadToDelim(in);
211 TString l(line.Strip(TString::kBoth));
212 if (l.IsWhitespace() || l.BeginsWith("#")) continue;
214 if (!CheckFile(l, chain))
215 Warning("ChainBuilder::CreateFromList",
216 "Failed to add %s to chain", l.Data());
220 //------------------------------------------------------------------
222 * Make a chain from a base directory, pattern, and treename -
223 * possibly recursively
225 * @return true on success
227 static Bool_t CreateFromDirectory(TChain* chain,
229 const TString& pattern,
233 // Info("", "Scanning src=%s, pattern=%s, mc=%d recursive=%d",
234 // src.Data(), pattern.Data(), mc, recursive);
235 // Save current directory
236 TString savdir(gSystem->WorkingDirectory());
237 TSystemDirectory d(gSystem->BaseName(src.Data()), src.Data());
238 // Info("", "Will scan %s", d.GetTitle());
239 if (!ScanDirectory(chain, &d, pattern, mc, recursive)) return false;
240 // Go back to the saved directory
241 gSystem->ChangeDirectory(savdir);
245 //------------------------------------------------------------------
247 * Check if we can add a file to the chain
249 * @param path Full path to file
252 * @return true on success, false otherwise
254 static Bool_t CheckFile(const TString& path, TChain* chain)
256 // Info("", "Checking %s", path.Data());
257 gSystem->RedirectOutput("/dev/null", "w");
258 TFile* test = TFile::Open(path, "READ");
259 gSystem->RedirectOutput(0);
261 Warning("ChainBuilder::CheckFile", "Failed to open %s", path.Data());
265 TObject* o = test->Get(chain->GetName());
267 // Let's try to find a TFileCollection
268 TList* l = test->GetListOfKeys();
272 while ((k = static_cast<TKey*>(next()))) {
273 TString cl(k->GetClassName());
274 if (!cl.EqualTo("TFileCollection")) continue;
275 TFileCollection* fc = dynamic_cast<TFileCollection*>(k->ReadObj());
276 Info("", "Adding file collection");
277 chain->AddFileInfoList(fc->GetList());
285 else if (dynamic_cast<TTree*>(o)) {
291 Warning("ChainBuilder::CheckFile",
292 "The file %s does not contain the tree %s or a file collection",
293 path.Data(), chain->GetName());
297 //------------------------------------------------------------------
299 * Scan directory @a dir (possibly recursive) for tree files to add
300 * to the chain. This does not follow sym-links
302 * @param dir Directory to scan
303 * @param chain Chain to add to
305 * @return true if any files where added
307 static Bool_t ScanDirectory(TChain* chain,
308 TSystemDirectory* dir,
309 const TString& pattern,
316 // Get list of files, and go back to old working directory
317 TString oldDir(gSystem->WorkingDirectory());
318 TList* files = dir->GetListOfFiles();
319 if (!gSystem->ChangeDirectory(oldDir)) {
320 Error("ChainBuilder::ScanDirectory", "Failed to go back to %s",
325 Warning("ChainBuilder::ScanDirectory", "No files");
331 Bool_t hasGAlice = (!(mc) ? true : false);
332 Bool_t hasKine = (!(mc) ? true : false);
333 Bool_t hasTrRef = (!(mc) ? true : false);
335 // Sort list of files and check if we should add it
338 TSystemFile* file = 0;
339 while ((file = static_cast<TSystemFile*>(next()))) {
340 TString name(file->GetName());
341 TString title(file->GetTitle());
342 TString full(gSystem->ConcatFileName(file->GetTitle(), name.Data()));
343 // Info("", "Got file %s", full.Data());
344 if (file->IsA()->InheritsFrom(TSystemDirectory::Class())) full = title;
345 // Ignore special links
346 if (name == "." || name == "..") {
347 // Info("ChainBuilder::ScanDirectory", "Ignoring %s", name.Data());
350 // Info("", "Got file %s", full.Data());
353 if (gSystem->GetPathInfo(full.Data(), fs)) {
354 Warning("ChainBuilder::ScanDirectory", "Cannot stat %s (%s)",
355 full.Data(), gSystem->WorkingDirectory());
358 // Check if this is a directory
359 if (file->IsDirectory(full)) {
360 // Info("", "Recursive scan of %s", full.Data());
362 // if (title[0] == '/')
363 TSystemDirectory* d = new TSystemDirectory(file->GetName(),
365 if (ScanDirectory(chain, d, pattern, mc, recursive))
372 // If this is not a root file, ignore
373 if (!name.EndsWith(".root")) {
374 // Info("ScanDirectory", "File %s does not end in .root", name.Data());
378 // If this file does not contain AliESDs, ignore
379 if (!name.Contains(pattern)) {
380 // Info("ChainBuilder::ScanDirectory", "%s does not match pattern %s",
381 // name.Data(), pattern.Data());
383 if (name.CompareTo("galice.root") == 0) hasGAlice = true;
384 if (name.CompareTo("Kinematics.root") == 0) hasKine = true;
385 if (name.CompareTo("TrackRefs.root") == 0) hasTrRef = true;
391 // Info("ChainBuilder::ScanDirectory", "Adding %s", full.Data());
392 toAdd.Add(new TObjString(full));
395 if (mc && toAdd.GetEntries() > 0 &&
396 (!hasGAlice || !hasKine || !hasTrRef)) {
397 Warning("ChainBuilder::ScanDirectory",
398 "one or more of {galice,Kinematics,TrackRefs}.root missing from "
399 "%s, not adding anything from this directory",
404 TIter nextAdd(&toAdd);
407 while ((s = static_cast<TObjString*>(nextAdd()))) {
408 // Info("ChainBuilder::ScanDirectory",
409 // "Adding %s", s->GetString().Data());
410 TString fn = s->GetString();
411 if (!CheckFile(fn, chain)) continue;
415 if (added > 0) ret = true;
417 gSystem->ChangeDirectory(oldDir);