connected at task output slot <i>. Works also in PROOF mode now.
- Added kSpecialOutput user-settable flag to AliAnalysisDataContainer. Output
containers that are to be dumped to a special file will be copied in PROOF mode from each
slave to a default remote location specified via AliAnalysisManager::SetSpecialOutputLocation()
File names will be prepended with the host name of the slave they were produced on.
One needs to open the special file in MyTask::CreateOutputObjects():
OpenFile(iout_slot)
The files on the slaves will be closed by the system in SlaveTerminate phase.
Ex:
MyAnalysis.C
{
mgr = new AliAnalysisManager("demo","");
mgr->SetSpecialOutputLocation("root://lxb0000.cern.ch//alien/alice/"); // xrootd location
MyTask *task = new MyTask();
mgr->AddTask(task);
// Create output container to be written in file sptree.root
AliAnalysisDataContainer *coutput1 = mgr->CreateContainer("csp_tree", TTree::Class(), AliAnalysisManager::kOutputContainer, "sptree.root");
coutput1->SetSpecialOutput();
mgr->ConnectOutput(task,3,coutput1); // connect container to output #3 of MyTask
...
mgr->StartAnalysis("proof", chain,...);
}
void MyTask::MyTask()
{
...
DefineInput(3, TTree::Class());
...
}
void MyTask::CreateOutputObjects()
{
...
TFile *f = OpenFile(3);
...
fTreeOnOutput3 = new TTree(...)
}
void MyTask::Exec()
{
... processing ...
tree->Fill();
PostData(3,tree);
}
kFileChange
};
enum EAnalysisContainerFlags {
- kPostEventLoop = BIT(14)
+ kPostEventLoop = BIT(14),
+ kSpecialOutput = BIT(15)
};
AliAnalysisDataContainer();
AliAnalysisDataContainer(const AliAnalysisDataContainer &cont);
virtual Bool_t SetData(TObject *data, Option_t *option="");
void SetDataOwned(Bool_t flag) {fOwnedData = flag;}
void SetPostEventLoop(Bool_t flag=kTRUE) {TObject::SetBit(kPostEventLoop,flag);}
+ void SetSpecialOutput(Bool_t flag=kTRUE) {TObject::SetBit(kSpecialOutput,flag);}
void SetFileName(const char *filename) {fFileName = filename;}
void SetProducer(AliAnalysisTask *prod, Int_t islot);
void AddConsumer(AliAnalysisTask *cons, Int_t islot);
// Container status checking
Bool_t IsDataReady() const {return fDataReady;}
Bool_t IsPostEventLoop() const {return TObject::TestBit(kPostEventLoop);}
+ Bool_t IsSpecialOutput() const {return TObject::TestBit(kSpecialOutput);}
Bool_t IsOwnedData() const {return fOwnedData;}
Bool_t ClientsExecuted() const;
Bool_t HasConsumers() const {return (fConsumers != 0);}
if (fDebug > 1) printf(" Packing container %s...\n", output->GetName());
target->Add(wrap);
}
+ // Special outputs files are closed and copied on the remote location
+ if (output->IsSpecialOutput() && strlen(output->GetFileName())) {
+ TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(output->GetFileName());
+ if (!file) continue;
+ file->Close();
+ if (strlen(fSpecialOutputLocation.Data())) {
+ TString remote = fSpecialOutputLocation;
+ remote += "/";
+ remote += gSystem->HostName();
+ remote += output->GetFileName();
+ TFile::Cp(output->GetFileName(), remote.Data());
+ }
+ }
}
}
if (fDebug > 1) {
void SetAnalysisType(EAliAnalysisExecMode mode) {fMode = mode;}
void SetCurrentEntry(Long64_t entry) {fCurrentEntry = entry;}
void SetDebugLevel(UInt_t level) {fDebug = level;}
+ void SetSpecialOutputLocation(const char *location) {fSpecialOutputLocation = location;}
void SetDisableBranches(Bool_t disable=kTRUE) {TObject::SetBit(kDisableBranches,disable);}
void SetCollectSysInfoEach(Int_t nevents=0) {fNSysInfo = nevents;}
void SetInputEventHandler(AliVEventHandler* handler) {fInputEventHandler = handler;}
EAliAnalysisExecMode fMode; // Execution mode
Bool_t fInitOK; // Initialisation done
UInt_t fDebug; // Debug level
+ TString fSpecialOutputLocation; // URL/path where the special outputs will be copied
TObjArray *fTasks; // List of analysis tasks
TObjArray *fTopTasks; // List of top tasks
TObjArray *fZombies; // List of zombie tasks
TObjArray *fOutputs; // List of containers with results
static AliAnalysisManager *fgAnalysisManager; //! static pointer to object instance
- ClassDef(AliAnalysisManager,2) // Analysis manager class
+ ClassDef(AliAnalysisManager,3) // Analysis manager class
};
#endif
}
//______________________________________________________________________________
-void AliAnalysisTask::OpenFile(Int_t iout, Option_t *option) const
+TFile *AliAnalysisTask::OpenFile(Int_t iout, Option_t *option) const
{
// This method has to be called INSIDE the user redefined CreateOutputObjects
// method, before creating each object corresponding to the output containers
// fHist2 = new TH2F("my quality check hist2",...);
// }
- if (iout<0 || iout>=fNoutputs) return;
- AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
- if (!mgr || mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis) return;
+ if (iout<0 || iout>=fNoutputs) {
+ Error("OpenFile", "No output slot for task %s with index %d", GetName(), iout);
+ return NULL;
+ }
+ // We allow file opening also on the slaves (AG)
+// AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
+// if (!mgr || mgr->GetAnalysisType()==AliAnalysisManager::kProofAnalysis) return;
AliAnalysisDataContainer *cont = GetOutputSlot(iout)->GetContainer();
- if (strlen(cont->GetFileName())) new TFile(cont->GetFileName(), option);
+ TFile *f = NULL;
+ if (strlen(cont->GetFileName())) f = new TFile(cont->GetFileName(), option);
+ if (f && !f->IsZombie()) return f;
+ return NULL;
}
//______________________________________________________________________________
#endif
class TClass;
+class TFile;
class AliAnalysisDataSlot;
class AliAnalysisDataContainer;
//=====================================================================
// === CALL THIS IN CreateOutputObjects BEFORE CREATING THE OBJECT FOR EACH
// OUTPUT IOUT THAT HAS TO BE WRITTEN TO A FILE
- void OpenFile(Int_t iout, Option_t *option="RECREATE") const;
+ TFile *OpenFile(Int_t iout, Option_t *option="RECREATE") const;
public:
AliAnalysisTask();