// @(#)root/alien:$Id$ // Author: Andreas-Joachim Peters 9/5/2005 /************************************************************************* * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * * For the list of contributors see $ROOTSYS/README/CREDITS. * *************************************************************************/ ////////////////////////////////////////////////////////////////////////// // // // TAlienCollection // // // // Class which manages collection of files on AliEn middleware. // // The file collection is in the form of an XML file. // // // // The internal list is managed as follows: // // TList* ===> TMap*(file) ===> TMap*(attributes) // // // ////////////////////////////////////////////////////////////////////////// #include "TAlienCollection.h" #include "TAlienResult.h" #include "TAlienFile.h" #include "TDSet.h" #include "TMap.h" #include "TFile.h" #include "TXMLEngine.h" #include "TObjString.h" #include "TEntryList.h" #include "TObjArray.h" #include "TROOT.h" #include "TError.h" #include "TFileCollection.h" #include "TFileInfo.h" #include ClassImp(TAlienCollection) //______________________________________________________________________________ TAlienCollection::TAlienCollection(const char *localcollectionfile, UInt_t maxentries) { // Create Alien event collection by reading collection from the specified XML file. // You can restrict the number of importet entries using the maxentries value. fXmlFile = localcollectionfile; fFileGroupList = new TList(); fFileGroupList->SetOwner(kTRUE); fFileGroupListIter = new TIter(fFileGroupList); fCurrent = 0; fNofGroups = 0; fNofGroupfiles = 0; fHasSUrls = kFALSE; fHasSelection = kFALSE; fFileStager = 0; fExportUrl = ""; fInfoComment = ""; fCollectionName = "unnamed"; fTagFilterList = 0; if (localcollectionfile != 0) { ParseXML(maxentries); } } //______________________________________________________________________________ TAlienCollection::TAlienCollection(TList *eventlist, UInt_t nofgroups, UInt_t nofgroupfiles) { // Create Alien event collection using an event list. fFileGroupList = eventlist; fFileGroupList->SetOwner(kTRUE); fFileGroupListIter = new TIter(fFileGroupList); fCurrent = 0; fNofGroups = nofgroups; fNofGroupfiles = nofgroupfiles; fHasSUrls = kFALSE; fHasSelection = kFALSE; fFileStager = 0; fExportUrl = ""; fInfoComment = ""; fCollectionName = "unnamed"; fTagFilterList = 0; } //______________________________________________________________________________ TAlienCollection::~TAlienCollection() { // Clean up event file collection. if (fFileGroupList) delete fFileGroupList; if (fFileGroupListIter) delete fFileGroupListIter; if (fTagFilterList) delete fTagFilterList; } //______________________________________________________________________________ TGridCollection *TAlienCollection::Open(const char *collectionurl, UInt_t maxentries) { // Static method used to create an Alien event collection, by reading // an XML collection from the specified url. All ROOT URLs are supported. // You can restrict the number of importet entries using the maxentries value //! stage the url to /tmp/ TUUID uuid; TString rndname = "/tmp/"; rndname += "aliencollection."; rndname += uuid.AsString(); if (!TFile::Cp(collectionurl, rndname.Data())) { ::Error("TAlienCollection::Open", "Cannot make a local copy of collection with url %s", collectionurl); return 0; } TAlienCollection *collection = new TAlienCollection(rndname, maxentries); if (gSystem->Unlink(rndname.Data())) { ::Error("TAlienCollection::Open", "Cannot remove the local copy of the collection %s", rndname.Data()); } return dynamic_cast (collection); } //______________________________________________________________________________ TFile *TAlienCollection::OpenFile(const char *filename) { // Open the file specified by from the currently active file group in the collection via its TURL. const char *turl = GetTURL(filename); if (turl) { return TFile::Open(turl); } return 0; } //______________________________________________________________________________ TAlienCollection *TAlienCollection::OpenAlienCollection(TGridResult * queryresult, Option_t* /*option*/) { // Static method used to create an Alien event collection, by creating // collection from a TGridResult GetCollection result (TAlien::GetCollection) if (!queryresult) return 0; TList *filelist = new TList(); TIterator* fileiter = queryresult->MakeIterator(); TMap *filemap = 0; while ((filemap = ((TMap *) fileiter->Next()))) { if (!filemap->GetValue("origLFN")) continue; filemap->Add(new TObjString("lfn"), new TObjString(filemap->GetValue("origLFN")->GetName())); filemap->Add(new TObjString("turl"), new TObjString(Form("alien://%s", filemap->GetValue("origLFN")->GetName()))); TString bname = gSystem->BaseName(filemap->GetValue("origLFN")->GetName()); filemap->Add(new TObjString("name"), new TObjString(bname.Data())); TMap* filegroup = new TMap(); filegroup->Add(new TObjString(bname.Data()), filemap); filegroup->Add(new TObjString(""), filemap); // store the filegroup filelist->Add(filegroup); } delete fileiter; return new TAlienCollection(filelist, filelist->GetEntries(), 1);; } //______________________________________________________________________________ TGridCollection *TAlienCollection::OpenQuery(TGridResult * queryresult, Bool_t nogrouping) { // Static method used to create an Alien event collection, by creating // collection from a TGridResult Query result (TAlien::Query) // nogrouping means that files in the same directory are treated as not belonging to a file group UInt_t nofgroups = 0; UInt_t nofgroupfiles = 0; if (!queryresult) { return 0; } TIterator *fileiter = queryresult->MakeIterator(); TMap *filemap = 0; TString prev_bname = ""; TString prev_dname = ""; TMap *filegroup = 0; TList *filelist = new TList(); while ((filemap = ((TMap *) fileiter->Next()))) { if (!filemap->GetValue("lfn")) continue; TString dname = gSystem->DirName(filemap->GetValue("lfn")->GetName()); TString bname = gSystem->BaseName(filemap->GetValue("lfn")->GetName()); filemap->Add(new TObjString("name"), new TObjString(bname.Data())); if ((!nogrouping) && ((bname != prev_bname) && (dname == prev_dname) && (filegroup))) { // add to group filegroup->Add(new TObjString(bname.Data()), filemap); if (nofgroups == 0) nofgroupfiles++; } else { // new group if (filegroup) { // store the old filegroup filelist->Add(filegroup); nofgroups++; } if (nofgroups == 0) nofgroupfiles++; filegroup = new TMap(); filegroup->Add(new TObjString(bname.Data()), filemap); filegroup->Add(new TObjString(""), filemap); } prev_bname = bname; prev_dname = dname; } if (filegroup) { nofgroups++; filelist->Add(filegroup); } // set tag filter list TList *filterlist = new TList(); filterlist->Add(new TObjString("type")); filterlist->Add(new TObjString("dir")); filterlist->Add(new TObjString("perm")); filterlist->Add(new TObjString("owner")); filterlist->Add(new TObjString("ctime")); filterlist->Add(new TObjString("seStringlist")); filterlist->Add(new TObjString("aclId")); filterlist->Add(new TObjString("expiretime")); filterlist->Add(new TObjString("replicated")); filterlist->Add(new TObjString("entryId")); filterlist->Add(new TObjString("gowner")); filterlist->Add(new TObjString("selist")); filterlist->Add(new TObjString("select")); filterlist->Add(new TObjString("online")); TAlienCollection *newcollection = new TAlienCollection(filelist, nofgroups, nofgroupfiles); if (newcollection) { newcollection->SetTagFilterList(filterlist); } return dynamic_cast (newcollection); } //______________________________________________________________________________ void TAlienCollection::Reset() { // Reset file iterator. fFileGroupListIter->Reset(); fCurrent = 0; } //______________________________________________________________________________ void TAlienCollection::ParseXML(UInt_t maxentries) { // Parse event file collection XML file. // stops the parsing after . TXMLEngine xml; UInt_t parsedentries = 0; XMLDocPointer_t xdoc = xml.ParseFile(fXmlFile); if (!xdoc) { Error("ParseXML", "cannot parse the xml file %s", fXmlFile.Data()); return; } XMLNodePointer_t xalien = xml.DocGetRootElement(xdoc); if (!xalien) { Error("ParseXML", "cannot find the tag in %s", fXmlFile.Data()); return; } XMLNodePointer_t xcollection = xml.GetChild(xalien); if (!xcollection) { Error("ParseXML", "cannot find the tag in %s", fXmlFile.Data()); return; } if (xml.GetAttr(xcollection,"name")) { fCollectionName = TString(xml.GetAttr(xcollection,"name")); } else { fCollectionName = ("unnamed"); } XMLNodePointer_t xevent = xml.GetChild(xcollection);; if (!xevent) { Error("ParseXML", "cannot find the tag in %s", fXmlFile.Data()); return; } if (!xevent) return; fNofGroups = 0; fNofGroupfiles = 0; fHasSUrls = kFALSE; fHasOnline = kFALSE; do { if (TString(xml.GetNodeName(xevent)) == "event") { parsedentries++; fNofGroups++; TMap *files = new TMap(); // here is our event // printf("Found event: %s\n",xml.GetAttr(xevent,"name")); // files XMLNodePointer_t xfile = xml.GetChild(xevent); if (!xfile) continue; Bool_t firstfile = kTRUE; do { // here we have an event file // get the attributes; xml.GetAttr(xfile, "lfn"); xml.GetAttr(xfile, "turl"); TMap *attributes = new TMap(); TObjString *oname = new TObjString(xml.GetAttr(xfile, "name")); TObjString *oturl = new TObjString(xml.GetAttr(xfile, "turl")); TObjString *olfn = new TObjString(xml.GetAttr(xfile, "lfn")); TObjString *omd5 = new TObjString(xml.GetAttr(xfile, "md5")); TObjString *osize = new TObjString(xml.GetAttr(xfile, "size")); TObjString *oguid = new TObjString(xml.GetAttr(xfile, "guid")); TObjString *osurl = new TObjString(xml.GetAttr(xfile, "surl")); TObjString *osselect = new TObjString(xml.GetAttr(xfile, "select")); TObjString *ossexporturl = new TObjString(xml.GetAttr(xfile, "exporturl")); TObjString *osonline = new TObjString(xml.GetAttr(xfile, "online")); TObjString *oseStringlist = new TObjString(xml.GetAttr(xfile, "seStringlist")); TObjString *oevlist = new TObjString(xml.GetAttr(xfile, "evlist")); // if oevlist is defined, we parse it and fill a TEntyList if (oevlist && strlen(oevlist->GetName())) { TEntryList *xmlentrylist = new TEntryList(oturl->GetName(), oguid->GetName()); TString stringevlist = oevlist->GetName(); TObjArray *evlist = stringevlist.Tokenize(","); for (Int_t n = 0; n < evlist->GetEntries(); n++) { xmlentrylist-> Enter(atol (((TObjString *) evlist->At(n))->GetName())); } attributes->Add(new TObjString("evlist"), xmlentrylist); } attributes->Add(new TObjString("name"), oname); attributes->Add(new TObjString("turl"), oturl); attributes->Add(new TObjString("lfn"), olfn); attributes->Add(new TObjString("md5"), omd5); attributes->Add(new TObjString("size"), osize); attributes->Add(new TObjString("guid"), oguid); attributes->Add(new TObjString("seStringlist"), oseStringlist); if (osurl && strlen(osurl->GetName())) { attributes->Add(new TObjString("surl"), osurl); fHasSUrls = kTRUE; } if (osselect && strlen(osselect->GetName())) { attributes->Add(new TObjString("select"), osselect); fHasSelection = kTRUE; } if (osonline && strlen(osonline->GetName())) { attributes->Add(new TObjString("online"), osonline); fHasOnline = kTRUE; } if (ossexporturl && strlen(ossexporturl->GetName())) { attributes->Add(new TObjString("exporturl"), ossexporturl); fExportUrl = ossexporturl->GetName(); } files->Add(new TObjString(xml.GetAttr(xfile, "name")), attributes); // we add the first file always as a file without name to the map if (firstfile) { files->Add(new TObjString(""), attributes); firstfile = kFALSE; } if (fNofGroups == 1) fNofGroupfiles++; } while ((xfile = xml.GetNext(xfile))); fFileGroupList->Add(files); } if (TString(xml.GetNodeName(xevent)) == "info") { if (xml.GetAttr(xevent,"comment")) { fInfoComment = TString(xml.GetAttr(xevent,"comment")); } else { fInfoComment = ""; } } if (TString(xml.GetNodeName(xevent)) == "export") { if (xml.GetAttr(xevent,"url")) { SetExportUrl(xml.GetAttr(xevent,"url")); } else { fExportUrl = ""; } } if (parsedentries >= maxentries) return; } while ((xevent = xml.GetNext(xevent))); } //______________________________________________________________________________ TMap *TAlienCollection::Next() { // Return next event file map. fCurrent = (TMap *) fFileGroupListIter->Next(); return fCurrent; } //______________________________________________________________________________ void TAlienCollection::Status() { // Prints statistics, selection and status about the loaded collection. TIter *statuslist = new TIter(fFileGroupList); statuslist->Reset(); TMap *oldcurrent = fCurrent; TMap *nextgroup = 0; UInt_t gc; UInt_t fc; UInt_t onlinegroups; UInt_t offlinegroups; UInt_t onlinefiles; UInt_t offlinefiles; UInt_t totalfiles; Long64_t totalfilesize; Long64_t onlinefilesize; Long64_t offlinefilesize; gc = 0; fc = 0; onlinegroups = offlinegroups = onlinefiles = offlinefiles = totalfiles = totalfilesize = onlinefilesize = offlinefilesize = 0; while ((nextgroup = (TMap *) statuslist->Next())) { gc++; fc = 0; Bool_t online; Bool_t selected; online = kTRUE; selected = kFALSE; TMap *attributes; TIterator *nextfile = nextgroup->MakeIterator(); nextfile->Reset(); while ((attributes = (TMap *) nextfile->Next())) { fCurrent = nextgroup; if (TString(attributes->GetName()) != "") { totalfiles++; totalfilesize += GetSize(attributes->GetName()); } if (IsSelected(attributes->GetName())) { selected = kTRUE; if (TString(attributes->GetName()) != "") { fc++; fCurrent = nextgroup; if (!IsOnline(attributes->GetName())) { online = kFALSE; offlinefiles++; offlinefilesize += GetSize(attributes->GetName()); } else { onlinefiles++; onlinefilesize += GetSize(attributes->GetName()); } } } } if (selected) { if (online) onlinegroups++; else offlinegroups++; } } fCurrent = oldcurrent; Info("Status", "========================================="); Info("Status", " Tot. Number of files: %u", totalfiles); Info("Status", " Tot. Size: %0.2f GB", totalfilesize / 1024.0 / 1024.0 / 1024.0); Info("Status", " Number of file groups: %u", gc); Info("Status", "Number of files per group: %u", fc); Info("Status", "-----------------------------------------"); Info("Status", "Online (staged [selected]):"); Info("Status", " Number of file groups: %u", onlinegroups); Info("Status", " Number of files: %u", onlinefiles); Info("Status", " Size: %0.2f GB", onlinefilesize / 1024.0 / 1024.0 / 1024.0); Info("Status", " Fraction avail: %0.2f %%", 100.0 * onlinefilesize / (onlinefilesize + offlinefilesize + 0.0000001)); Info("Status", "-----------------------------------------"); Info("Status", "Offline (to be staged [selected]):"); Info("Status", " Number of file groups: %u", offlinegroups); Info("Status", " Number of files: %u", offlinefiles); Info("Status", " Size: %0.2f GB", offlinefilesize / 1024.0 / 1024.0 / 1024.0); Info("Status", " Fraction miss: %0.2f %%", 100.0 * offlinefilesize / (onlinefilesize + offlinefilesize + 0.0000001)); Info("Status", "=========================================\n"); } //______________________________________________________________________________ void TAlienCollection::SetTag(const char *tag, const char *value, TMap * tagmap) { // Set's a key value pair in a tagmap. If it is existing, the existing tag is overwritten. If not, it is created. if ((!tag) || (!value) || (!tagmap)) { return; } TObject *delobject = tagmap->FindObject(tag); if (delobject) { TObject *keyobject = ((TPair *) delobject)->Key(); tagmap->Remove(keyobject);; } tagmap->Add(new TObjString(tag), new TObjString(value)); } //______________________________________________________________________________ Bool_t TAlienCollection::SelectFile(const char *filename, Int_t nstart, Int_t nstop) { // Selects all files with name in the collection // All files can be selected using "*" as filename Int_t cnt=0; fHasSelection = kTRUE; Reset(); TMap *nextgroup; while ((nextgroup = (TMap *) Next())) { cnt++; TMap *attributes; TIterator *nextfile = nextgroup->MakeIterator(); nextfile->Reset(); if ( ((nstart == -1 ) && (nstop == -1)) || ((nstart != -1 ) && (cnt >= nstart) && (nstop == -1)) || ((nstart != -1 ) && (cnt >= nstart) && (nstop != -1) && (cnt <= nstop)) || ((nstop != -1 ) && (cnt <= nstop) && (nstart == -1))) { while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { if ((TString(attributes->GetName()) == TString(filename)) || (TString(filename) == TString("*"))) { SetTag("select", "1", ((TMap *) nextgroup->GetValue(attributes->GetName()))); } } } } } return kTRUE; } //______________________________________________________________________________ Bool_t TAlienCollection::DeselectFile(const char *filename, Int_t nstart, Int_t nstop) { // Deselects the file from the loaded collection // All files can be deselected using "*" as Int_t cnt=0; Reset(); TMap *nextgroup; while ((nextgroup = (TMap *) Next())) { cnt++; TMap *attributes; TIterator *nextfile = nextgroup->MakeIterator(); nextfile->Reset(); if ( ((nstart == -1 ) && (nstop == -1)) || ((nstart != -1 ) && (cnt >= nstart) && (nstop == -1)) || ((nstart != -1 ) && (cnt >= nstart) && (nstop != -1) && (cnt <= nstop)) || ((nstop != -1 ) && (cnt <= nstop) && (nstart == -1))) { while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { if ((TString(attributes->GetName()) == TString(filename)) || (TString(filename) == TString("*"))) { SetTag("select", "0", ((TMap *) nextgroup->GetValue(attributes->GetName()))); } } } } } return kTRUE; } //______________________________________________________________________________ Bool_t TAlienCollection::InvertSelection() { // Invert the selection. Int_t cnt=0; fHasSelection = kTRUE; Reset(); TMap *nextgroup; while ((nextgroup = (TMap *) Next())) { cnt++; TMap *attributes; TIterator *nextfile = nextgroup->MakeIterator(); nextfile->Reset(); while ((attributes = (TMap *) nextfile->Next())) { if (IsSelected(attributes->GetName())) { SetTag("select", "0", ((TMap *) nextgroup->GetValue(attributes->GetName()))); } else { SetTag("select", "1", ((TMap *) nextgroup->GetValue(attributes->GetName()))); } } } return kTRUE; } //______________________________________________________________________________ Bool_t TAlienCollection::DownscaleSelection(UInt_t scaler) { // downscales the selection with scaler Int_t cnt = 0; Reset(); TMap *nextgroup; while ((nextgroup = (TMap *) Next())) { cnt++; TMap *attributes; TIterator *nextfile = nextgroup->MakeIterator(); nextfile->Reset(); if (cnt%scaler) { while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { SetTag("select", "0", ((TMap *) nextgroup->GetValue(attributes->GetName()))); } } } } return kTRUE; } //______________________________________________________________________________ Bool_t TAlienCollection::Remove(TMap * map) { // Return next event file map. if (fFileGroupList->Remove(map)) { return kTRUE; } else { return kFALSE; } } //______________________________________________________________________________ const char *TAlienCollection::GetTURL(const char *filename) { // Get a file's transport URL (TURL). Returns 0 in case of error. if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("turl")) { return (((TObjString *) obj->GetValue("turl"))->GetName()); } } } Error("GetTURL", "cannot get TURL of file %s", filename); return 0; } //______________________________________________________________________________ const char *TAlienCollection::GetSURL(const char *filename) { // Get a file's storage URL (SURL). Returns 0 in case of error. if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("surl")) { return (((TObjString *) obj->GetValue("surl"))->GetName()); } } } Error("GetSURL", "cannot get SURL of file %s", filename); return 0; } //______________________________________________________________________________ Bool_t TAlienCollection::IsOnline(const char *filename) { // Get a file's online tag. Returns false if not online or CheckIfOnline was never executed, true if online if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("online")) { TString online = (((TObjString *) obj->GetValue("online"))->GetName()); if (online == "1") { return kTRUE; } else { return kFALSE; } } } } // Error("IsOnline", "cannot get online tag of file %s", filename); return kFALSE; } //______________________________________________________________________________ Bool_t TAlienCollection::IsSelected(const char *filename) { // Get a file's online tag. Returns false if not online or CheckIfOnline was never executed, true if online if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("select")) { TString selected; selected = (((TObjString *) obj->GetValue("select"))->GetName()); if (selected == TString("1")) { return kTRUE; } else { return kFALSE; } } } } return kFALSE; } //______________________________________________________________________________ TEntryList *TAlienCollection::GetEntryList(const char *filename) { // Get a file's event list. Returns 0 in case of error. if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("evlist")) { return ((TEntryList *) obj->GetValue("evlist")); } } } Error("GetEntryList", "cannot get evelist of file %s", filename); return 0; } //______________________________________________________________________________ const char *TAlienCollection::GetLFN(const char *filename) { // Get a file's LFN. Returns 0 in case of error. if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("lfn")) { return (((TObjString *) obj->GetValue("lfn"))->GetName()); } } } Error("GetLFN", "cannot get LFN"); return 0; } //______________________________________________________________________________ Long64_t TAlienCollection::GetSize(const char *filename) { // Get a file's LFN. Returns 0 in case of error. if (fCurrent) { TMap *obj = (TMap *) fCurrent->GetValue(filename); if (obj) { if (obj->GetValue("size")) { TString ssize = (((TObjString *) obj->GetValue("size"))->GetName()); return ssize.Atoll(); } } } Error("GetSize", "cannot get size of %s", filename); return 0; } //______________________________________________________________________________ void TAlienCollection::Print(Option_t *) const { // Print event file collection. Info("Print", "dumping %d elements", fFileGroupList->GetSize()); TIter next(fFileGroupList); TMap *filemap; Int_t count = 0; while ((filemap = (TMap *) next())) { count++; Info("Print", "printing element %d", count); filemap->Print(); } } //______________________________________________________________________________ TDSet *TAlienCollection::GetDataset(const char *type, const char *objname, const char *dir) { // Return a TDSet from a collection. Filter, Selections and online tags are not // taken into account. Reset(); TMap *mapp; TDSet *dset = new TDSet(type, objname, dir); if (!dset) { return 0; } while ((mapp = Next())) { if (((TObjString *) fCurrent->GetValue(""))) dset->Add(((TMap *) (fCurrent->GetValue("")))->GetValue("turl")-> GetName());; } return dset; } //______________________________________________________________________________ TGridResult *TAlienCollection::GetGridResult(const char *filename, Bool_t onlyonline, Bool_t publicaccess) { // Return a TGridResult. // If files have been selected in this collection, only the selected files // are returned. If is set to kTRUE, only files which are // 'online' (staged) are included. If no online check was done, TGridResult // will be empty. adds the publicaccess option to the TGridResult entries Reset(); TMap *mapp; TGridResult *result = new TAlienResult(); while ((mapp = Next())) { if (((TObjString *) fCurrent->GetValue(filename))) { TMap *attributes = (TMap *) fCurrent->GetValue(filename)->Clone(); if (publicaccess) { attributes->Add(new TObjString("options"), new TObjString("&publicaccess=1")); } if ((!fHasSelection) || (IsSelected(filename))) { if ((!onlyonline) || (fHasOnline && IsOnline(filename))) { result->Add(attributes); } } } } return dynamic_cast < TGridResult * >(result); } //______________________________________________________________________________ Bool_t TAlienCollection::OverlapCollection(TGridCollection * comparator) { // return kTRUE if comparator overlaps with this // all objects in this collection, which are not defined in the collection are removed. if ((!comparator)) { return kFALSE; } loopagain: // loop over col1 and try to find it in col2 this->Reset(); // loop over all elements in reference (=this) TMap *overlapmap; while ((overlapmap = this->Next())) { comparator->Reset(); Bool_t found = kFALSE; // try to find in the comparator collection while ((comparator->Next())) { TString s1 = this->GetLFN(); TString s2 = comparator->GetLFN(); if (s1 == s2) { found = kTRUE; break; } } if (!found) { this->Remove(overlapmap); goto loopagain; } } return kTRUE; } //______________________________________________________________________________ void TAlienCollection::Add(TGridCollection * addcollection) { // adds to this collection - equal elements are skipped if ((!addcollection)) { return; } // loop over col1 and try to find it in col2 addcollection->Reset(); // loop over all elements in reference (=this) TMap *addmap; TMap *thismap; while ((addmap = addcollection->Next())) { Reset(); // try to find in the comparator collection TString s2 = addcollection->GetLFN(); while ((thismap = Next())) { TString s1 = GetLFN(); // printf("%s = %s\n", s1.Data(), s2.Data()); if (s1 == s2) { Error("Add", "File group with lfn %s exists already in this collection - skipping", GetLFN()); goto leaveloop; } } TMap *clonemap; clonemap = (TMap *) addmap->Clone(); fFileGroupList->Add(clonemap); leaveloop: ; } } //______________________________________________________________________________ void TAlienCollection::AddFast(TGridCollection * addcollection) { // adds to this collection - NO check for identical elements if ((!addcollection)) { return; } addcollection->Reset(); TMap *addmap, *clonemap; while ((addmap = addcollection->Next())) { clonemap = (TMap *) addmap->Clone(); fFileGroupList->Add(clonemap); } } //______________________________________________________________________________ Bool_t TAlienCollection::LookupSUrls(Bool_t verbose) { // retrieves all the SURLS for the LFNS Bool_t ok = kTRUE; UInt_t lc = 0; Reset(); TMap *filemap; while ((filemap = Next())) { // loop over all files in this map TIterator *nextfile = filemap->MakeIterator(); TMap *attributes; while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { lc++; if (fHasSelection && (!IsSelected(attributes->GetName()))) continue; // there is always an "" entry in the map to point to the first file of a file group if (verbose) Info("LookupSUrls", "Lookup SURL for %s [%u/%u]", GetTURL(attributes->GetName()), lc, fNofGroups * fNofGroupfiles); TString surl = TAlienFile::SUrl(GetTURL(attributes->GetName())); if (!surl.Data()) { ok = kFALSE; } else { // delete the surl map entry, if it exists already TObject *delobject = ((TMap *) filemap->GetValue(attributes->GetName()))-> FindObject("surl"); if (delobject) { TObject *keyobject = ((TPair *) delobject)->Key(); ((TMap *) filemap->GetValue(attributes->GetName()))-> Remove(keyobject);; } ((TMap *) filemap->GetValue(attributes->GetName()))-> Add(new TObjString("surl"), new TObjString(surl.Data())); if (verbose) Info("LookupSUrls", "SURL = %s", surl.Data()); } } } } if (ok) { fHasSUrls = kTRUE; } return ok; } //_____________________________________________________________________________ Bool_t TAlienCollection::Stage(Bool_t bulk,Option_t* option) { // Execute the 'stage' method for all files in this collection (trigger staging). // The stage method is currently not working. if (!fHasSUrls) { Error("Stage", "You have to execute LookupSUrls() before you can stage this collection"); return kFALSE; } UInt_t fc = 0; Reset(); TMap *filemap; if (!bulk) { while ((filemap = Next())) { // loop over all files in this map TIterator *nextfile = filemap->MakeIterator(); TMap *attributes; while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { fc++; if (fHasSelection && (!IsSelected(attributes->GetName()))) continue; if (!fFileStager) { fFileStager = TFileStager::Open(GetSURL(attributes->GetName())); } if ((fFileStager)->Stage(GetSURL(attributes->GetName()),option)) { // file staged Info("Stage", "[%05u/%05u] : %s", fc, GetNofGroups() * GetNofGroupfiles(), GetLFN(attributes->GetName())); } else { // file stage failed Error("Stage", "[%05u/%05u] : %s", fc, GetNofGroups() * GetNofGroupfiles(), GetLFN(attributes->GetName())); } } } } } else { // bulk request TList* stagelist = new TList(); stagelist->SetOwner(kTRUE); Bool_t stageresult=kFALSE; Reset(); while ((filemap = Next())) { TIterator *nextfile = filemap->MakeIterator(); TMap *attributes; while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { fc++; stagelist->Add( new TUrl((GetSURL(attributes->GetName())))); } } } if (fc) { if (!fFileStager) { fFileStager = TFileStager::Open(stagelist->First()->GetName()); } stageresult = (fFileStager)->Stage(stagelist,option); } delete stagelist; return stageresult; } return kTRUE; } //_____________________________________________________________________________ Bool_t TAlienCollection::CheckIfOnline(Bool_t bulk) { // Run an online check if files are currently accessible (staged) or offline (to be staged). // The check is currently not working. if (!fHasSUrls) { Error("CheckIfOnline", "You have to execute LookupSUrls() before you can prepare this collection"); return kFALSE; } Reset(); TMap *filemap; UInt_t fc=0; if (!bulk) { while ((filemap = Next())) { // loop over all files in this map TIterator *nextfile = filemap->MakeIterator(); TMap *attributes; while ((attributes = (TMap *) nextfile->Next())) { if (fHasSelection && (!IsSelected(attributes->GetName()))) continue; if (TString(attributes->GetName()) != "") { fc++; // check if we have a fFileStager if (!fFileStager) { fFileStager = TFileStager::Open(GetSURL(attributes->GetName())); } Bool_t online = kFALSE; if ((fFileStager)->IsStaged(GetSURL(attributes->GetName()))) { // file is online Info("CheckIfOnline", "[%05u/%05u] : %s", fc, GetNofGroups() * GetNofGroupfiles(), GetLFN(attributes->GetName())); online = kTRUE; } else { // file is offline Info("CheckIfOnline", "[%05u/%05u] : %s", fc, GetNofGroups() * GetNofGroupfiles(), GetLFN(attributes->GetName())); online = kFALSE; } { // set the online tag in the collection // delete the online tag entry, if it exists already TObject *delobject = ((TMap *) filemap->GetValue(attributes->GetName()))-> FindObject("online"); if (delobject) { TObject *keyobject = ((TPair *) delobject)->Key(); ((TMap *) filemap->GetValue(attributes->GetName()))-> Remove(keyobject);; } if (online) ((TMap *) filemap->GetValue(attributes->GetName()))-> Add(new TObjString("online"), new TObjString("1")); else ((TMap *) filemap->GetValue(attributes->GetName()))-> Add(new TObjString("online"), new TObjString("0")); } } } } } else { // bulk lookup TList *lookuplist = new TList(); if (lookuplist) { lookuplist->SetOwner(kTRUE); while ((filemap = Next())) { // loop over all files in this map TIterator *nextfile = filemap->MakeIterator(); TMap *attributes; while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { fc++; // check if we have a fFileStager if (!fFileStager) { fFileStager = TFileStager::Open(GetSURL(attributes->GetName())); } lookuplist-> Add(new TObjString(GetSURL(attributes->GetName()))); } } } TList *onlinelist = fFileStager->GetStaged(lookuplist); if (!onlinelist) return kFALSE; Reset(); fc=0; while ((filemap = Next())) { // loop over all files in this map TIterator *nextfile = filemap->MakeIterator(); TMap *attributes; while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { fc++; Bool_t online; // check if it is in the online list if (onlinelist-> FindObject(GetSURL(attributes->GetName()))) { // this file is online Info("CheckIfOnline", "[%05u/%05u] : %s", fc, GetNofGroups() * GetNofGroupfiles(), GetLFN(attributes->GetName())); online = kTRUE; } else { // this file is offline Info("CheckIfOnline", "[%05u/%05u] : %s", fc, GetNofGroups() * GetNofGroupfiles(), GetLFN(attributes->GetName())); online = kFALSE; } { // set the online tag in the collection // delete the online tag entry, if it exists already TObject *delobject = ((TMap *) filemap-> GetValue(attributes->GetName()))-> FindObject("online"); if (delobject) { TObject *keyobject = ((TPair *) delobject)->Key(); ((TMap *) filemap-> GetValue(attributes->GetName()))-> Remove(keyobject); } if (online) ((TMap *) filemap-> GetValue(attributes->GetName()))-> Add(new TObjString("online"), new TObjString("1")); else ((TMap *) filemap-> GetValue(attributes->GetName()))-> Add(new TObjString("online"), new TObjString("0")); } } } } SafeDelete(onlinelist); SafeDelete(lookuplist); } else { fHasOnline = kFALSE; return kFALSE; } } fHasOnline = kTRUE; return kTRUE; } //_____________________________________________________________________________ Bool_t TAlienCollection::ExportXML(const char *exporturl, Bool_t selected, Bool_t online, const char *name , const char *comment) { // Exports the contens of the TAlienCollection into an XML formatted file. // By default exports only selected files. By default exports only accessible (online) files. // You can change this behaviour by specifying online=kFALSE or selected=kFALSE. // specifies a name you want to assign to this collection. // can be a user comment to this collection. // If ="" the collection is exported to the URL which was stored inside the collection or // was specified by the ExportUrl(const char* url) method. TFile *exportfile; if ((exporturl == 0) || (TString(exporturl) == "")) { if (!(exporturl = GetExportUrl())) { Error("ExportXML", "You used the option to store to the collection export url, but this is not defined!"); return kFALSE; } } TUrl expfn(exporturl); TString options = expfn.GetOptions(); if (options.Length()) { options += ",filetype=raw"; } else { options = "filetype=raw"; } expfn.SetOptions(options.Data()); if (!(exportfile = TFile::Open(expfn.GetUrl(), "RECREATE"))) { Error("ExportXML", "Cannot open export URL %s", expfn.GetUrl()); return kFALSE; } Bool_t expret = ExportXML(exportfile, selected, online, name, comment); exportfile->Close(); return expret; } //_____________________________________________________________________________ Bool_t TAlienCollection::ExportXML(TFile * exportfile, Bool_t selected, Bool_t online, const char *name, const char *comment) { // Internal Export function to write a collection as an XML file. See above. char outline[4096]; // write headers snprintf(outline,4096, "\n\n \n", name); if ((exportfile->WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } // write events TMap *oldcurrent = fCurrent; TMap *nextgroup; TIter *filegroups = new TIter(fFileGroupList); filegroups->Reset(); UInt_t groupcnt = 0; while ((nextgroup = (TMap *) filegroups->Next())) { Bool_t isonline; Bool_t isselected; isonline = kTRUE; isselected = kFALSE; TMap *attributes; TIterator *nextfile = nextgroup->MakeIterator(); nextfile->Reset(); // check if something is selected while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { fCurrent = nextgroup; if (IsSelected(attributes->GetName())) { isselected = kTRUE; } if (!IsOnline(attributes->GetName())) { isonline = kFALSE; } } } if ((!selected) || isselected) { // loop again and export files nextfile->Reset(); groupcnt++; // open new event header snprintf(outline,4096, " \n", groupcnt); if ((exportfile->WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } while ((attributes = (TMap *) nextfile->Next())) { if (TString(attributes->GetName()) != "") { fCurrent = nextgroup; if ((!selected) || (IsSelected(attributes->GetName()))) { if ((!online) || (IsOnline(attributes->GetName()))) { // export this file ///////////////////////////////////////////////////////////// // open file tag snprintf(outline,4096, " WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } // loop over map keys TIterator *mkeys = ((TMap *) nextgroup-> GetValue(attributes->GetName()))->MakeIterator(); mkeys->Reset(); TObjString *tagname = 0; TObjString *tagval = 0; while ((tagname = (TObjString *) mkeys->Next())) { Bool_t filtered = kFALSE; // check for filtered tags from the filter list if (fTagFilterList) { TIter next(fTagFilterList); TObjString *filtertag; while ((filtertag = (TObjString *) next())) { if (TString(tagname->GetName()) == TString(filtertag->GetName())) { filtered = kTRUE; break; } } } if (!filtered) { tagval = (TObjString *) ((TMap *) nextgroup-> GetValue(attributes-> GetName()))-> GetValue(tagname); if (TString(tagname->GetName()) != "evlist") { snprintf(outline,4096, "%s=\"%s\" ", tagname->GetName(), tagval->GetName()); } else { // the eventlist has to be converted from TEventList to a string list with komma separation TEntryList *xmlentrylist = (TEntryList *) tagval; if (!xmlentrylist) continue; TString slist = ""; for (Int_t i = 0; i < xmlentrylist->GetN(); i++) { if (i > 0) slist += ","; slist += xmlentrylist->GetEntry(i); } snprintf(outline,4096, "%s=\"%s\" ", tagname->GetName(), slist.Data()); } if ((exportfile-> WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } } } // close file tag snprintf(outline,4096, "/>\n"); if ((exportfile-> WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } } } } } // close event snprintf(outline,4096, " \n"); if ((exportfile->WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } } } fCurrent = oldcurrent; // write export url if present if (GetExportUrl()) { snprintf(outline,4096, " \n",GetExportUrl()); if ((exportfile->WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } } // write trailer snprintf(outline,4096, " \n\n\n", comment); if ((exportfile->WriteBuffer(outline, strlen(outline)))) { Error("ExportXML", "Error writing XML to export file"); exportfile->Close(); return kFALSE; } return kTRUE; } //_____________________________________________________________________________ Bool_t TAlienCollection::SetExportUrl(const char *exporturl) { // Set the 'default' export URL for an XML collection. A collection can be restored to the export URL using ExportXML(""); if (exporturl) fExportUrl = exporturl; if (fExportUrl == "") { Info("ExportUrl", "There is no remote url defined in this collection"); return kFALSE; } return kTRUE; } //_____________________________________________________________________________ const char *TAlienCollection::GetOutputFileName(const char *infile, Bool_t rename, const char* suffix) { // Adds to a file given by infile the collection identification , f.e. // for collection files sitting in directories like 100/1/AliESD.root // ... // 110/1/AliESD.root // "./histo.root" will be converted to "./histo.100_1-110_1.230.root // // The name syntax is ._-...root // // By default the found files are renamed on the local disk // example: // - you specify f.e. as arguments GetOutputFileName("*.root",kTRUE); // --->> this renames all ROOT files corresponding to the collection contents Bool_t first = kTRUE; TString firstrun; TString firstevent; TString lastrun; TString lastevent; UInt_t nevents = 0; Reset(); while (Next()) { TString s1(gSystem->DirName(GetLFN(""))); TString s2(gSystem->BaseName(s1.Data())); TString s3(gSystem->DirName(s1.Data())); TString s4(gSystem->BaseName(s3.Data())); nevents++; if (first) { first = kFALSE; firstevent = s2; firstrun = s4; } lastevent = s2; lastrun = s4; } // list the matching files TString pcmd("ls "); pcmd += infile; //printf("Pipe is %s\n",pcmd.Data()); FILE *fp = gSystem->OpenPipe(pcmd.Data(), "r"); if (fp) { char rootfile[4096]; Int_t item; while ((item = fscanf(fp, "%s", rootfile)) == 1) { TString rootdir(gSystem->DirName(rootfile)); TString rootbase(gSystem->BaseName(rootfile)); TString rootbasenosuffix; rootbasenosuffix = rootbase(0, rootbase.First('.'));; // build new name like ._-_.root TString newrootname; if (rootdir.Length()) { newrootname += rootdir; newrootname += "/"; } newrootname += rootbasenosuffix; newrootname += "."; newrootname += firstrun; newrootname += "_"; newrootname += firstevent; newrootname += "-"; newrootname += lastrun; newrootname += "_"; newrootname += lastevent; newrootname += "."; newrootname += nevents; newrootname += "."; newrootname += suffix; Info("GetOutputFilename", "Renaming File %s to %s", rootfile, newrootname.Data()); fLastOutFileName = newrootname; if (rename) { gSystem->Rename(rootfile, newrootname.Data()); } } gSystem->ClosePipe(fp); } return fLastOutFileName.Data(); } //_____________________________________________________________________________ TFileCollection *TAlienCollection::GetFileCollection(const char* name, const char* title) const { // creates a TFileCollection objects and fills it with the information from this collection // note that TFileCollection has a flat structure and no groups --> all files are filles on a flat level // the TFileInfo of each file in the TFileCollection is filled with turl, size, md5, guid // // the object has to be deleted by the user TFileCollection* collection = new TFileCollection(name, title); TIter next(fFileGroupList); TMap* group = 0; while ((group = dynamic_cast(next()))) { TIter next2(group); TObjString* key = 0; while ((key = dynamic_cast (next2()))) { if (key->String().Length() == 0) continue; TMap* file = dynamic_cast (group->GetValue(key)); if (!file) continue; TObjString* turl = dynamic_cast (file->GetValue("turl")); TObjString* size = dynamic_cast (file->GetValue("size")); TObjString* md5 = dynamic_cast (file->GetValue("md5")); TObjString* guid = dynamic_cast (file->GetValue("guid")); if (!turl || turl->String().Length() == 0) continue; TFileInfo* fileInfo = new TFileInfo(turl->String(), size->String().Atoi(), guid->String(), md5->String()); collection->Add(fileInfo); } } collection->Update(); return collection; }