/************************************************************************** * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * * * * Author: The ALICE Off-line Project. * * Contributors are mentioned in the code where appropriate. * * * * Permission to use, copy, modify and distribute this software and its * * documentation strictly for non-commercial purposes is hereby granted * * without fee, provided that the above copyright notice appears in all * * copies and that both the copyright notice and this permission notice * * appear in the supporting documentation. The authors make no claims * * about the suitability of this software for any purpose. It is * * provided "as is" without express or implied warranty. * **************************************************************************/ /* $Id$ */ ////////////////////////////////////////////////////////////////////////// // marian.ivanov@cern.ch // Utilities for file merging. // Additional functionality on top of the standard TFileMerger: // // 1. Possibility to Set the reject/accept list. // 1.a) Only entries selected in accept list are merged. By default all entries are selected // use AddAccept 0 to specify your desired entry // 1.b) Entries selected in reject list are not merged. By default the reject list is empty. // // 2. syswatch.log is created diring mergin procedure. // Memeory consumption - for reading and for merging can be monitored /* Usage: // Libraries for all classes to be merged should be loaded before using the class gSystem->Load("libANALYSIS"); gSystem->Load("libANALYSIScalib"); gSystem->Load("libTPCcalib"); TH1::AddDirectory(0); //Example usage starting from the input data list in text file: // AliFileMerger merger; merger.AddReject("esdFriend"); merger.IterTXT("calib.list","CalibObjects.root",kFALSE); // */ ////////////////////////////////////////////////////////////////////////// #include #include "TSystem.h" #include "TFile.h" #include "TGrid.h" #include "TGridResult.h" #include "TObjString.h" #include "TObjArray.h" #include "TMethodCall.h" #include "AliSysInfo.h" #include "AliFileMerger.h" ClassImp(AliFileMerger) //////////////////////////////////////////////////////////////////////// AliFileMerger::AliFileMerger(): TNamed(), fRejectMask(0), fAcceptMask(0) { // // Default constructor // } //______________________________________________________________________ AliFileMerger::AliFileMerger(const char* name): TNamed(name,name), fRejectMask(0), fAcceptMask(0) { // // // } void AliFileMerger::IterAlien(const char* outputDir, const char* outputFileName, const char* pattern){ // // Merge the files coming out of the calibration job // TObjArray * mergeArray= new TObjArray; TString outputFile(outputFileName); TString command; // looking for files to be merged in the output directory command = Form("find %s/ *%s", outputDir, pattern); printf("command: %s\n", command.Data()); TGrid::Connect("alien://"); TGridResult *res = gGrid->Command(command); if (!res) return; TIter nextmap(res); TMap *map = 0; // loop over the results while((map=(TMap*)nextmap())) { // getting the turl TObjString *objs = dynamic_cast(map->GetValue("turl")); if (!objs || !objs->GetString().Length()) { // Nothing found - skip this output delete res; break; } printf("looking for file %s\n",(objs->GetString()).Data()); TFile* currentFile=TFile::Open((objs->GetString()).Data()); if(!currentFile) continue; // protection Merge(currentFile, mergeArray); } Bool_t separate = kFALSE; if (separate) { StoreSeparateResults(mergeArray,outputFileName); } else { StoreResults(mergeArray,outputFileName); } delete mergeArray; delete res; } void AliFileMerger::IterTXT( const char * fileList, const char* outputFileName, Bool_t separate){ // Merge the files indicated in the list - fileList // ASCII file option example: // find `pwd`/ | grep AliESDfriends_v1.root > calib.list TObjArray * mergeArray= new TObjArray; // Open the input stream ifstream in; in.open(fileList); // Read the input list of files TString objfile; Int_t counter=0; while(in.good()) { in >> objfile; if (!objfile.Contains("root")) continue; // protection printf("Open file:Counter\t%d\tMerging file %s\n",counter++,objfile.Data()); TFile currentFile(objfile.Data()); Merge(¤tFile, mergeArray); } if (separate) { StoreSeparateResults(mergeArray, outputFileName); } else { StoreResults(mergeArray, outputFileName); } delete mergeArray; } void AliFileMerger::StoreResults(TObjArray * array, const char* outputFileName){ // // Storing the results in one single file // TFile *f = new TFile(outputFileName,"recreate"); for (Int_t i=0; iGetEntries(); i++){ TObject *object0 = array->At(i); if (!object0) continue; object0->Write(); } f->Close(); delete f; } void AliFileMerger::StoreSeparateResults(TObjArray * array, const char* outputFileName){ // // Store the results in separate files (one per object) // for (Int_t i=0; iGetEntries(); i++){ TObject *object0 = array->At(i); if (!object0) continue; TFile *f = new TFile(Form("%s_%s.root",outputFileName,object0->GetName()),"recreate"); object0->Write(); f->Close(); delete f; } } void AliFileMerger::Merge(TFile* fileIn, TObjArray * array){ // // Merging procedure // static Int_t counter=-1; counter++; TObjArray *carray = new TObjArray; //array of the objects inside current file carray->SetOwner(kTRUE); // load all objects to memory TList *farr = fileIn->GetListOfKeys(); if (!farr) { delete carray; return; } for (Int_t ical=0; icalGetEntries(); ical++){ if (!farr->At(ical)) continue; TString name(farr->At(ical)->GetName()); if (!IsAccepted(name)) continue; // skip not accepted entries TObject *obj = fileIn->Get(name.Data()); if (obj) carray->AddLast(obj); AliSysInfo::AddStamp(name.Data(),1,ical,counter); } if (carray->GetEntries()==0) { delete carray; return; } TMethodCall callEnv; for (Int_t i=0; iGetEntries(); i++){ TObjArray *templist = new TObjArray(1); templist->SetOwner(kFALSE); TObject *currentObject = carray->At(i); if (!currentObject) { delete templist; continue; } printf("%s\n",currentObject->GetName()); callEnv.InitWithPrototype(currentObject->IsA(), "Merge", "TCollection*"); if (!callEnv.IsValid()) { delete templist; continue; } TString oname=currentObject->GetName(); TObject *mergedObject = array->FindObject(currentObject->GetName()); if (!mergedObject) { array->AddLast(currentObject); carray->RemoveAt(i); delete templist; continue; } templist->AddLast(currentObject); callEnv.SetParam((Long_t) templist); callEnv.Execute(mergedObject); AliSysInfo::AddStamp(currentObject->GetName(),2,i,counter); delete templist; } delete carray; } Bool_t AliFileMerger::IsAccepted(TString name){ // // Accept/reject logic // name - name of the entry // // if fAcceptMask specified - entry has to be in list of selected // if fRejectMask speciefied - entry with name speciief in the list are rejected // Bool_t accept=kTRUE; if (fAcceptMask){ // accept=kFALSE; for (Int_t iaccept=0; iacceptGetEntries(); iaccept++){ if (name.Contains(fAcceptMask->At(iaccept)->GetName())) accept=kTRUE; // entry was selected } } if (!accept) return kFALSE; if (fRejectMask){ // for (Int_t ireject=0; irejectGetEntries(); ireject++){ if (name.Contains(fRejectMask->At(ireject)->GetName())) accept=kFALSE; // entry was rejected } } return accept; } void AliFileMerger::AddReject(const char *reject){ // // add reject string to the list of entries to be rejected for merging // if (!fRejectMask) fRejectMask = new TObjArray; fRejectMask->AddLast(new TObjString(reject)); } void AliFileMerger::AddAccept(const char *accept){ // // add reject string to the list of entries to be rejected for merging // if (!fAcceptMask) fAcceptMask = new TObjArray; fAcceptMask->AddLast(new TObjString(accept)); }