#include <string.h>
#include <iostream>
#include <iomanip>
#include "TClass.h"
#include "TROOT.h"
#include "TFile.h"
#include "TTree.h"
#include "TBranch.h"
#include "TInterpreter.h"
#include "TDatime.h"
#include "TSystem.h"
#include "TChain.h"
#include "hades.h"
#include "htree.h"
#include "hdebug.h"
#include "hruntimedb.h"
#include "htaskset.h"
#include "hreconstructor.h"
#include "hspectrometer.h"
#include "hdatasource.h"
#include "heventheader.h"
#include "hevent.h"
#include "hrecevent.h"
#include "hmessagemgr.h"
#include "hldfileoutput.h"
#include "hpario.h"
#include "hldfilesource.h"
#include "hrootsource.h"
#include "hgeantmedia.h"
#include "hsrckeeper.h"
using namespace std;
Int_t Hades::EventCounter = 0;
Int_t Hades::doEmbedding  = 0;
Int_t Hades::doEmbeddingDebug  = 0;
Bool_t Hades::forceNoSkip = kFALSE;
Int_t Hades::fembeddingRealTrackId=-500;
ClassImp(Hades)
Hades::Hades(void)
{
    
    
    gHades = this;
    if (!gDebuger) { gDebuger = new HDebug; }
    fCurrentEvent     = NULL;
    fDataSource       = NULL;
    fSecondDataSource = NULL;
    fHldOutput        = NULL;
    fOutputFile       = NULL;
    fSplitLevel       = 2;
    fTree             = NULL;
    fCounter          = 0;
    rtdb              = HRuntimeDb::instance();
    setup             = new HSpectrometer();
    defineTaskSets();
    quiet            = 0;
    fFirstEventLoop  = kTRUE;
    fCycleNumber     = 0;
    fOutputSizeLimit = 1900000000;
    TTree::SetMaxTreeSize(2000000000); 
    
    treeBufferSize   = 8000;
    
    oldHdlr    = GetErrorHandler();
    msgHandler = new HMessageMgr("Hades","Hades");
    SetErrorHandler(&msgHandler->hydraErrorHandler);
    reqEvents  = 0;
    enableCloseInput = kTRUE;
    isHldSource = kFALSE;
    writeHades  = kFALSE;
    writeEvent  = kTRUE;
    fTaskListStatus = 0;
    fgeantMedia = 0;
    fsrckeeper  = new HSrcKeeper("Hades_src","Hades_src");
    fbeamtimeID = 0; 
    fExtEvent   = kFALSE;
}
Hades::~Hades(void)
{
    
    
    
    closeOutput();
    if (fTree)             delete fTree;
    if (fCurrentEvent)     delete fCurrentEvent;
    if (fHldOutput)        delete fHldOutput;
    if (fDataSource)       delete fDataSource;
    if (fSecondDataSource) delete fSecondDataSource;
    if (rtdb)              delete rtdb;
    if (setup)             delete setup;
    if (fTaskList) {
	fTaskList->Delete();
	delete fTaskList;
	fTaskList = NULL;
	fTask     = NULL;
    }
    if(msgHandler) delete msgHandler;
    SetErrorHandler(oldHdlr);
    if(fgeantMedia) {
	delete fgeantMedia;
	fgeantMedia = NULL;
    }
    gHades = NULL;
}
void Hades::defineTaskSets()
{  
    
    
    
    
    fTask = NULL;
    fTaskList = new TObjArray(25);
    fTaskList->AddAt(new HTaskSet("simulation"        ,"Main task for simulation events")       , 0);
    fTaskList->AddAt(new HTaskSet("real1"             ,"Main task for real1 events")            , 1);
    fTaskList->AddAt(new HTaskSet("real2"             ,"Main task for real2 events")            , 2);
    fTaskList->AddAt(new HTaskSet("real3"             ,"Main task for real3 events")            , 3);
    fTaskList->AddAt(new HTaskSet("real4"             ,"Main task for real4 events")            , 4);
    fTaskList->AddAt(new HTaskSet("real5"             ,"Main task for real5 events")            , 5);
    fTaskList->AddAt(new HTaskSet("real6"             ,"Main task for real6 events")            , 6);
    fTaskList->AddAt(new HTaskSet("real7"             ,"Main task for real7 events")            , 7);
    fTaskList->AddAt(new HTaskSet("real8"             ,"Main task for real8 events")            , 8);
    fTaskList->AddAt(new HTaskSet("MDCcalibration"    ,"Main task for MDC calibration events")  , 9);
    fTaskList->AddAt(new HTaskSet("SHOWERcalibration" ,"Main task for SHOWERcalibration events"), 10);
    fTaskList->AddAt(new HTaskSet("SHOWERpedestals"   ,"SHOWERpedestals")                       , 11);
    fTaskList->AddAt(new HTaskSet("RICHpedestals"     ,"RICHpedestals")                         , 12);
    fTaskList->AddAt(new HTaskSet("CTSStatusConfig"   ,"CTSStatusConfig")                       , 14);
    fTaskList->AddAt(new HTaskSet("real"              ,"Main task for all real events")         , 16);
    fTaskList->AddAt(new HTaskSet("calibration"       ,"Main task for all calibration events")  , 17);
    fTaskList->AddAt(new HTaskSet("all"               ,"Main task for all events")              , 18);
    
    fTaskList->AddAt(new HTaskSet("special1","sep03")      ,19);
    fTaskList->AddAt(new HTaskSet("offspill","sep03")      ,20);
    fTaskList->AddAt(new HTaskSet("special3","sep03")      ,21);
    fTaskList->AddAt(new HTaskSet("special5","sep03")      ,22);
    fTaskList->AddAt(new HTaskSet("beginrun","sep03")      ,23);
    fTaskList->AddAt(new HTaskSet("endrun"  ,"sep03")      ,24);
}
Int_t Hades::mapId(Int_t id)
{
    if (id >= 0 && id < MAXEVID) return evIdMap[id];
    else                         return -1;
}
Int_t Hades::setAlgorithmLayout(Text_t *fileName)
{
    
    
    
    
    return gROOT->Macro(fileName);
}
Int_t Hades::setEventLayout(Text_t *fileName)
{
    
    
    
    
    if (fTree) delete fTree;
    fTree = NULL;
    return gROOT->Macro(fileName);
}
Int_t Hades::setConfig(Text_t *fileName)
{
    
    
    
    
    
    
    
    
    
    
    if (gROOT->Macro(fileName)) return kTRUE;
    else                        return kFALSE;
}
Bool_t Hades::init(Bool_t externInit)
{
    
    
    rtdb->initContainers(fDataSource->getCurrentRunId(),
			 fDataSource->getCurrentRefId());
    if(!setup->init()) return kFALSE;
    if(!externInit){
	fDataSource->setEventAddress(&fCurrentEvent);
	if (!fDataSource->init()){
	    Error("init","Error in fDataSource->init()");
	    return kFALSE;
	}
	TString sourcetype = fDataSource->IsA()->GetName();
	if(sourcetype.CompareTo("HldFileSource") == 0)isHldSource = kTRUE;
	else                                          isHldSource = kFALSE;
	if (fSecondDataSource) {
	    fSecondDataSource->setEventAddress(&fCurrentEvent);
	    if (!fSecondDataSource->init()){
		Error("init","Error in fSecondDataSource->init()");
		return kFALSE;
	    }
	}
    }
    Int_t vers = ((fCurrentEvent->getHeader()->getVersion()));
    initTaskSetsIDs(vers);
    if (!initTasks()) return kFALSE;
    else              return kTRUE;
}
Bool_t Hades::isCalibration()
{ 
    HEventHeader *head = fCurrentEvent->getHeader();
    if (!head) {
	Error("isCalibration", "No event header found, exiting...");
	exit(1);
    }
    Int_t id = head->getId();
    Int_t version = head->getVersion() & 0xF;
    if (version == 0) {
	if (id == 2 || id == 3 || id == 4 || id == 5 || id == 6 || id == 7 || id == 8 || id == 9){
	    return kTRUE;
	}
    }
    else if (version == 1) {
	if (id == 7 || id == 9) { return kTRUE; }
    }
    else if (version == 2) {
	if (id >= 9 && id <= 12) { return kTRUE; }
    }
    return kFALSE;
}
Bool_t Hades::isReal()
{ 
    
    
    
    
    
    HEventHeader *head = fCurrentEvent->getHeader();
    if (!head) {
	Error("isReal", "No event header found, exiting...");
	exit(1);
    }
    Int_t id = head->getId();
    Int_t version = head->getVersion() & 0xF;
    if (head->getEventSeqNumber() == 0) {
	if (version == 0 && id == 2) { return kTRUE; }
    } else {
	if (version == 0) {
	    if (id == 1) { return kTRUE; }
	}
	else if (version == 1) {
	    if (id == 1 || id == 2 || id == 3 || id == 4 || id == 5) { return kTRUE; }
	}
        else if (version == 2) {
	    if (id >= 1 && id <= 8 ) { return kTRUE; }
	}
    }
    return kFALSE;
}
Bool_t  Hades::initTasks()
{
    HTaskSet* task;
    TIter iter(fTaskList);
    while((task = (HTaskSet*)iter())) {
	if (!task->init()) { Error("init()","Error returned from %s!",task->GetName()); return kFALSE; }
    }
    return kTRUE;
}
Bool_t Hades::reinitTasks()
{
    HTaskSet* task;
    TIter iter(fTaskList);
    while((task = (HTaskSet*)iter())) {
	if (!task->reinit()) { Error("reinit()","Error returned from %s!",task->GetName());return kFALSE; }
    }
    return kTRUE;
}
Bool_t Hades::finalizeTasks()
{
    HTaskSet* task;
    TIter iter(fTaskList);
    while((task = (HTaskSet*)iter())) {
	if (!task->finalize()) { return kFALSE; }
    }
    return kTRUE;
}
Int_t Hades::executeTasks()
{
    HTaskSet* task;
    TIter iter(fTaskList);
    Int_t returnVal = 0;
    UInt_t evtId = fCurrentEvent->getHeader()->getId();
    getTaskSet("all")->next(returnVal);  
    if (returnVal < 0 && returnVal != -99) return returnVal;
    while((task = (HTaskSet*)iter())) {
	if(mapId(evtId) !=-1) task->next(returnVal,evtId);  
	if (returnVal < 0 && returnVal != -99) { break; }   
    }
    return returnVal;
}
HTaskSet* Hades::getTask()
{  
    return getTaskSet("real");
}
HTask* Hades::getTask(const Char_t *name)
{   
    HTaskSet* taskSet;
    HTask* task = NULL;
    for (Int_t i = 0; i < fTaskList->GetSize(); i ++) {
	if ( (taskSet = (HTaskSet*)fTaskList->At(i)) ) {
	    if ( (task = taskSet->getTask(name)) ) { return task; } 
	}
    }
    return NULL;   
}
HTaskSet* Hades::getTaskSet(Int_t nEvtId)
{  
    Int_t ind = mapId(nEvtId);   
    if (ind >= 0 && ind < fTaskList->GetSize()) { return (HTaskSet*)fTaskList->At(ind); }
    else                                        { return NULL; }
}
HTaskSet* Hades::getTaskSet(const Char_t *evtTypeName)
{ 
    HTaskSet* taskSet;
    for (Int_t i = 0; i < fTaskList->GetSize(); i ++) {
	if ( (taskSet = (HTaskSet*)fTaskList->At(i)) ) {
	    if (strcmp(taskSet->GetName(),evtTypeName) == 0) { return taskSet; }
	}
    }
    return NULL;
}
HEvent *&Hades::getCurrentEvent(void)
{
    
    return fCurrentEvent;
}
void Hades::setEvent(HEvent *ev,Bool_t remove)
{
    
    
    
    
    
    
    if (fCurrentEvent&&remove) delete fCurrentEvent;
    fCurrentEvent = ev;
    if(!remove) fExtEvent = kTRUE;
}
void Hades::setDataSource(HDataSource *dataS)
{
    
    
    
    
    
    
    fDataSource=dataS;
}
void Hades::setSecondDataSource(HDataSource *dataS)
{
    
    
    if (dataS != NULL) {
	if (dataS->InheritsFrom("HRootSource") ) {
	    fSecondDataSource=dataS;
	} else {
	    Error("setSecondDataSource()","Second Datasource does not inherit from HRootSource! Ignored!");
	    fSecondDataSource = NULL;
	}
    } else { fSecondDataSource = NULL; }
}
Bool_t Hades::setHldOutput(Text_t* filedir,const Text_t* fileSuffix,const Option_t* option)
{
    
    if (fHldOutput) delete fHldOutput;
    if (fDataSource && fDataSource->InheritsFrom("HldSource")) {
	fHldOutput = new HldFileOutput((HldSource*)fDataSource,filedir,fileSuffix,option);
	return kTRUE;
    } else {
	Error("setHldOutput","No HLD data source!");
	return kFALSE;
    }
}
void Hades::setSplitLevel(Int_t splitLevel)
{
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    fSplitLevel = splitLevel;
}
Int_t Hades::getSplitLevel(void)
{
    
    return fSplitLevel;
}
Bool_t Hades::setOutputFile(Text_t *name,
			    Option_t *opt,
			    Text_t *title,
			    Int_t comp)
{
    
    
    
    
    
    
    
    
    fOutputFileName = name;
    fOutputFileName.Remove(fOutputFileName.Length() - 4 - 1);
    closeOutput();
    fOutputFile = new TFile(name,opt,title,comp);
    return kTRUE;
}
HTree *Hades::getTree(void)
{
    
    return fTree;
}
void Hades::activateTree(TTree *tree)
{
    
    
    
    
    
    
    
#if DEBUG_LEVEL>2
    gDebuger->enterFunc("Hades::activateTree");
#endif
    Int_t splitLevel = 2;
    TBranch *brEvent = 0;
    Char_t sl = *(strchr(tree->GetTitle(),'.') + 1);
    switch (sl) {
    case '0' : splitLevel = 0;
    break;
    case '1' : splitLevel = 1;
    break;
    case '2' : splitLevel = 2;
    break;
    default : splitLevel  = fSplitLevel;
    }
    if (fCurrentEvent)
    {
	tree->SetBranchStatus("*",1);   
	
	if (splitLevel == 0)
	{
	    tree->SetBranchAddress("Event",&fCurrentEvent);
	    tree->SetBranchStatus("Event",1);
	} else {
	    brEvent = tree->GetBranch("Event.");
	    if (brEvent) { 
		brEvent->SetAddress(&fCurrentEvent);
		tree->SetBranchStatus("Event.",1);
		tree->SetBranchStatus("Event.*",1);
	    } else { 
		brEvent = tree->GetBranch("Event");
		if (brEvent) {
		    tree->SetBranchAddress("Event",&fCurrentEvent);
		    tree->SetBranchStatus("Event",1);
		    tree->SetBranchStatus("Event.*",1);
		} else {
		    Warning("activateBranch","Event branch not found in tree");
		}
	    }
	    fCurrentEvent->activateBranch(tree,splitLevel);
	}
    }
#if DEBUG_LEVEL>2
    gDebuger->leaveFunc("Hades::activateTree");
#endif
}
Bool_t Hades::makeTree(void)
{
    
    
    TBranch *b = NULL;
    Bool_t r   = kFALSE;
    Text_t treeTitle[255];
    if (fTree) delete fTree;
    sprintf(treeTitle,"T.%i",fSplitLevel);
    if (fOutputFile) { fOutputFile->cd(); } 
    fTree = new HTree("T",treeTitle);
    gTree = fTree;
    if (fCurrentEvent && fTree)
    {
	if (fSplitLevel==0) {
	    b = fTree->Branch("Event",
			      fCurrentEvent->ClassName(),
			      &fCurrentEvent,64000,0);
	} else {
	    b = fTree->Branch("Event.",
			      fCurrentEvent->ClassName(),
			      &fCurrentEvent,getTreeBufferSize(),99);
	    fCurrentEvent->makeBranch(b,gHades->getTree());
	}
	if (b) {
	    r = kTRUE;
	}
    }
    return r;
}
Int_t Hades::getCurrentRunId(HDataSource* source)
{
    if(source->getCurrentRefId() == -1) return source->getCurrentRunId();
    else                                return source->getCurrentRefId();
}
Int_t Hades::eventLoop(Int_t nEvents, Int_t firstEvent, Double_t timeQuota)
{
    
    
    
    
    
    
    
    
    
    
    
    
    
    
#if DEBUG_LEVEL > 2
    gDebuger->enterFunc("Hades::eventLoop");
#endif
    
    
    Int_t evN       = 0;
    Int_t lastEvent = 0;
    
    
    
    
    Int_t err                    = 0;
    Int_t errAll                 = 0;
    EDsState dsCode              = kDsOk;
    EDsState dsCode2             = kDsOk;
    
    
    
    
    Int_t oldRunId            = -1;
    
    
    
    Bool_t initOk             = kTRUE;
    
    UInt_t evtId;
    TDatime dt;
    HTaskSet *taskSet;
    reqEvents = nEvents;
    if (!(fCurrentEvent && fDataSource)) {
	Error("eventLoop","No current event or no data source set!");
	return 0;
    }
    if (fCurrentEvent->InheritsFrom("HRecEvent")) {
	
	( (HRecEvent *)fCurrentEvent)->setExpandedStreamer(kFALSE);
    }
    if(!fExtEvent) fCurrentEvent->Clear();
    
    
    
    if (fFirstEventLoop) {
	if (!rtdb->initContainers(fDataSource->getCurrentRunId(),
				  fDataSource->getCurrentRefId(),
				  fDataSource->getCurrentFileName())) {
	    oldRunId = getCurrentRunId(fDataSource);
	    return 0;
	}
	if(fDataSource->InheritsFrom("HRootSource")){
	    HRootSource* rsrc = (HRootSource*) fDataSource;
            TFile* frsrc = rsrc->getChain()->GetCurrentFile();
	    if(frsrc){
		fgeantMedia = (HGeantMedia*) frsrc ->Get("GeantMedia");
                if(fgeantMedia) fgeantMedia->SetName("GeantMedia");
		if(!fgeantMedia) Warning("eventLoop()","Could not retrieve HGeantMedia from first datasource!");
	    } else Warning("eventLoop()","Could not retrieve file pointer from first datasource!");
	}
	if(!(reinitTasks())) {
	    gDebuger->message("An error occurred in the task list re-init");
	    return evN;
	}
	if(enableCloseInput) rtdb->disconnectInputs();
	fFirstEventLoop = kFALSE;
    }
    
    
    
    
    dsCode = fDataSource->skipEvents(firstEvent);
    if (dsCode == kDsOk) {
	evN = firstEvent;
    } else {
	evN = firstEvent;
	Warning("eventLoop","Condition %i while skipping events",dsCode);
    }
    if(nEvents != kMaxInt) {
	lastEvent = evN + nEvents;
    } else {
	lastEvent = nEvents;
    }
    
    
    
    
    Bool_t timerFlag = kTRUE;
    fTimer.Reset();
    timeQuota *= 60.;   
    
    
    
    
    if (!fDataSource->reinit()) {
	Error("eventLoop","An error occurred in fDataSource->reinit()");
    }
    if (fSecondDataSource) {
	if (!fSecondDataSource->reinit()) {
	    Error("eventLoop","An error occurred in fSecondDataSource->reinit()");
	}
	if(!fgeantMedia && fSecondDataSource->InheritsFrom("HRootSource")){
	    HRootSource* rsrc = (HRootSource*) fSecondDataSource;
            TFile* frsrc = rsrc->getChain()->GetCurrentFile();
	    if(frsrc){
		fgeantMedia = (HGeantMedia*) frsrc ->Get("GeantMedia");
                if(fgeantMedia) fgeantMedia->SetName("GeantMedia");
		if(!fgeantMedia) Warning("eventLoop()","Could not retrieve HGeantMedia from second datasource!");
	    } else Warning("eventLoop()","Could not retrieve file pointer from second datasource!");
	}
    }
    
    
    if (fHldOutput) {
	TString cf = fDataSource->getCurrentFileName();
	Int_t l = cf.Last('/');
	TString fn = cf(l + 1,cf.Length() - l);
	fHldOutput->open(fn);
    }
    
    oldRunId = getCurrentRunId(fDataSource);
    while ((evN < lastEvent) && (dsCode != kDsEndData) && (dsCode != kDsError)
	   && timerFlag)
    {
	
	
	while ((evN < lastEvent) && timerFlag)
	{
	    EventCounter ++;
	    fTimer.Start(kFALSE);
	    if(!fExtEvent) fCurrentEvent->Clear();
	    
            
	    if (fOutputFile) {
		if (fOutputFile->GetBytesWritten() > fOutputSizeLimit) {
		    recreateOutput();
		}
	    }
	    
	    
	    
            
	    if (fSecondDataSource) {
		dsCode2 = fSecondDataSource->getNextEvent();
		if(evN == 0 && isHldSource) { fSecondDataSource->setCursorToPreviousEvent(); }
		if (dsCode2 == kDsError  ) { break; }
		if (dsCode2 == kDsEndData) { dsCode = kDsEndData; break; } 
	    }
	    
	    
            
	    dsCode = fDataSource->getNextEvent();
 	    
 	    
	    
	    
	    if (dsCode == kDsError || dsCode == kDsEndData) {
		break;
	    }
	    
	    
	    
	    if (dsCode == kDsEndFile || (oldRunId != getCurrentRunId(fDataSource)))
	    {
		if(enableCloseInput) { initOk = rtdb->reconnectInputs(); }
		if (initOk) {
		    initOk = rtdb->initContainers(fDataSource->getCurrentRunId(),
						  fDataSource->getCurrentRefId(),
						  fDataSource->getCurrentFileName());
		}
		if (initOk) {
		    if(!(reinitTasks())) {
			gDebuger->message("An error occurred in the task list re-init");
			return evN;
		    }
		}
		if(enableCloseInput) { rtdb->disconnectInputs(); }
		if (initOk)
		{
		    if (!fDataSource->reinit()) {
			Error("eventLoop","An error occurred in fDataSource->reinit()");
		    }
		    if (fSecondDataSource) {
			if (!fSecondDataSource->reinit()) {
			    Error("eventLoop","An error occurred in fSecondDataSource->reinit()");
			}
		    }
		    if (fHldOutput) {
			TString cf = fDataSource->getCurrentFileName();
			Int_t l = cf.Last('/');
			TString fn = cf(l + 1,cf.Length() - l);
			fHldOutput->open(fn);
			fHldOutput->setHldSource((HldSource*)fDataSource);
		    }
		}
		oldRunId = getCurrentRunId(fDataSource);
	    }
	    
	    
	    
	    
	    if (dsCode == kDsSkip)
	    {
		
		
		if(fSecondDataSource)
		{
		    fSecondDataSource->setCursorToPreviousEvent();
		}
		
		
		continue;
	    }
	    
	    err    = 99;   
	    errAll = 99;   
	    
            
	    UInt_t firstev = fCurrentEvent->getHeader()->getId();
	    if((firstev != 2 && EventCounter == 1) || (EventCounter == 2) )
	    {   
		
		
		Int_t vers = ((fCurrentEvent->getHeader()->getVersion()));
		initTaskSetsIDs(vers);
		printDefinedTaskSets();
	    }
	    
	    getTaskSet("all")->next(errAll);  
            fTaskListStatus = errAll;
	    
	    
            
	    if (errAll != kSkipEvent)
	    {
		evtId = fCurrentEvent->getHeader()->getId();
		if (mapId(evtId) != -1)
		{
		    for (Int_t i = 0; i < fTaskList->GetSize(); i ++) {
			if ( (taskSet = (HTaskSet*)fTaskList->At(i)) ) {
			    taskSet->next(err,evtId); 
                            fTaskListStatus = errAll;
			    if (err < 0 && err != -99) { break; }      
			}
		    }
		    if(err != 0 )
		    {   
			if (err != kSkipEvent) {
			    if(!quiet && err != 99) Warning("eventLoop",
							    "Exiting task set with errCode %i at event %i (Id %i)\n",err,evN,evtId);
			    if (fTree)      { fTree->Fill(); }
			    if (fHldOutput) { fHldOutput->writeEvent(); }
			} else {
			    
			    
			    
			    if(fSecondDataSource)
			    {
				
				
				fSecondDataSource->setCursorToPreviousEvent();
			    }
			    
			}
		    } else { 
			if (fTree)      { fTree->Fill(); }
			if (fHldOutput) { fHldOutput->writeEvent(); }
		    }
		} else {
		    Warning("eventLoop","No tasklist defined for event id 0x%x.\n", evtId);
		    if (fHldOutput) { fHldOutput->writeEvent(); }
		}
	    }
	    else {
		
		
		
		if(fSecondDataSource)
		{
		    
		    
		    fSecondDataSource->setCursorToPreviousEvent();
		}
		
	    }
	    
	    
	    evN ++;
	    if(fCounter && (evN % fCounter == 0) && !quiet) {
		dt.Set();
		msgHandler->info(10,HMessageMgr::DET_ALL,GetName()," %s  Events processed: %i current Event: %i SequenceNumber: %i",
				 dt.AsSQLString() + 11, evN - firstEvent,evN,fCurrentEvent->getHeader()->getEventSeqNumber());
	    }
	    timerFlag = fTimer.RealTime() < timeQuota;
	}
    }
    if(dsCode == kDsError) { gDebuger->message("An error occurred in the event loop"); }
#if DEBUG_LEVEL > 2
    gDebuger->leaveFunc("Hades::eventLoop");
#endif
    fDataSource->finalize();
    if (!finalizeTasks()) Error("eventLoop","Unable to finalize");
    if(!timerFlag) msgHandler->info(10,HMessageMgr::DET_ALL,GetName(),"\n%.2f minutes time quota has expired.\n",
				    timeQuota / 60.);
    if(quiet != 2) {
	msgHandler->infoB(10,HMessageMgr::DET_ALL,"Total number of events processed: %i",evN - firstEvent);
	if (fHldOutput) {
	    msgHandler->infoB(10,HMessageMgr::DET_ALL,"\n\nWritten to HLD Output: Total number of events:    %i",
			      fHldOutput->getNumTotalEvt());
	    msgHandler->infoB(10,HMessageMgr::DET_ALL,"                       Number of filtered events: %i",
			      fHldOutput->getNumFilteredEvt());
	}
    }
    return evN - firstEvent;
}
Bool_t Hades::IsFolder(void) const
{
    
    
    return kTRUE;
}
void Hades::Browse(TBrowser *b)
{
    
    
    
    
    
#if DEBUG_LEVEL>2
    gDebuger->enterFunc("Hades::Browse");
#endif
    if (fTree) { b->Add(fTree,"Tree"); }
    
#if DEBUG_LEVEL>2
    gDebuger->message("Adding Task list");
#endif
    if (fTaskList) { b->Add(fTaskList,"Tasks"); }
#if DEBUG_LEVEL>2
    gDebuger->message("Adding current event");
#endif
    if (fCurrentEvent) { b->Add(fCurrentEvent,"Event"); }
#if DEBUG_LEVEL>2
    gDebuger->leaveFunc("Hades::Browse");
#endif
}
void   Hades::addObjectToOutput(TObject* obj)
{
    fObjectsAddedToOutput.AddLast(obj);
}
void Hades::closeOutput(void)
{
    if (fOutputFile)
    {
	fOutputFile->cd();
	this ->Write();
	if(fgeantMedia) fgeantMedia->Write();
	fsrckeeper->Write();
        if(fObjectsAddedToOutput.GetEntries()>0) fObjectsAddedToOutput.Write();
	fOutputFile->Write();
	delete fOutputFile;
	fOutputFile = NULL;
	fTree       = 0;
    }
}
void Hades::recreateOutput(void)
{
    fCycleNumber ++;
    Bool_t createTree = (fTree != 0);
    Char_t name[255];
    TString opt(fOutputFile->GetOption());
    TString title(fOutputFile->GetTitle());
    Int_t comp = fOutputFile->GetCompressionLevel();
    closeOutput();
    sprintf(name,"%s_%i.root",fOutputFileName.Data(),fCycleNumber);
    fOutputFile = new TFile(name,"RECREATE",title.Data(),comp);
    if (createTree) { makeTree(); }
}
void Hades::Streamer(TBuffer &R__b)
{
    if (R__b.IsReading())
    {
	Version_t R__v = R__b.ReadVersion(); if (R__v) { }
	TObject::Streamer(R__b);
	setup->Streamer(R__b);
	rtdb->Streamer(R__b);
	R__b >> fSplitLevel;
	R__b >> fTaskList;
	fDataSource = NULL;
	fOutputFile = NULL;
	fCurrentEvent = (HEvent *)gDirectory->Get("Event");
	fTree = (HTree *)gDirectory->Get("T");
    } else {
	R__b.WriteVersion(Hades::IsA());
	TObject::Streamer(R__b);
        setup->Streamer(R__b);
	if(writeHades)rtdb->Streamer(R__b);
	R__b << fSplitLevel;
	if(writeHades)R__b << fTaskList;
	if (writeEvent&&fCurrentEvent)
	{
	    if (fCurrentEvent->InheritsFrom("HRecEvent")) { 
		Bool_t expand = ((HRecEvent *)fCurrentEvent)->hasExpandedStreamer();
		( (HRecEvent *)fCurrentEvent)->setExpandedStreamer(kTRUE);
		fCurrentEvent->Clear();
		fCurrentEvent->Write("Event");
		( (HRecEvent *)fCurrentEvent)->setExpandedStreamer(expand);
	    } else {
		fCurrentEvent->Clear();
		fCurrentEvent->Write("Event");
	    }
	}
    }
}
void Hades::printDefinedTaskSets()
{
    HTaskSet* task;
    TIter iter(fTaskList);
    Int_t size = 0;
    Int_t* ids;
    Int_t version = ((fCurrentEvent->getHeader()->getVersion()) & 0xF);
    cout<<"#################### HADES TASKSETS ############################"<<endl;
    if(version == 0) {cout<<"#  Version Nov02"<<endl; }
    if(version == 1) {cout<<"#  Version Sep03"<<endl; }
    if(version == 2) {cout<<"#  Version June 2010"<<endl; }
    while((task = (HTaskSet*)iter()))
    {
	ids = task->getIds(size);
	cout<<"#  "<<setw(15)<<task->GetName()<<" for Ids : "<<flush;
	for(Int_t i = 0; i < size; i ++)
	{
	    if(ids[0] == -1){cout<<"not defined"<<flush;break;}
	    if(ids[i] != -1){cout<<ids[i]<<" "<<flush;}
	}
	cout<<""<<endl;
    }
    cout<<"################################################################"<<endl;
}
void  Hades::initTaskSetsIDs(Int_t version)
{
    
    
    
    
    
    Int_t evIdTable[3][MAXEVID] = { { 0,16,17,17,17,17,17,17, 
                                     17,17,-1,-1,-1,13,14,-1},
				    { 0, 1, 2, 3, 4, 5, 6, 7, 
				      8, 9,10,-1,-1,13,14,-1},
				    { 0, 1, 2, 3, 4, 5, 6, 7, 
				      8, 9,10,11,12,-1,14,-1}
    };
    for (Int_t i = 0; i < MAXEVID; i ++) { evIdMap[i] = evIdTable[version][i]; }
    if (version == 0) { 
	getTaskSet("simulation")    ->setIds(0);
	getTaskSet("real")          ->setIds(1);
	getTaskSet("calibration")   ->setIds(2,3,4,5,6,7,8,9);
	getTaskSet("beginrun")      ->setIds(13);
	getTaskSet("endrun")        ->setIds(14);
    }
    else if (version == 1) { 
	getTaskSet("simulation")    ->setIds(0);
	getTaskSet("real")          ->setIds(1,2,3,4,5);
	getTaskSet("calibration")   ->setIds(7,9);
	getTaskSet("real1")         ->setIds(1);
	getTaskSet("real2")         ->setIds(2);
	getTaskSet("real3")         ->setIds(3);
	getTaskSet("real4")         ->setIds(4);
	getTaskSet("real5")         ->setIds(5);
	getTaskSet("special1")      ->setIds(6);
	getTaskSet("offspill")      ->setIds(7);
	getTaskSet("special3")      ->setIds(8);
	getTaskSet("MDCcalibration")->setIds(9);
	getTaskSet("special5")      ->setIds(10);
	getTaskSet("beginrun")      ->setIds(13);
	getTaskSet("endrun")        ->setIds(14);
    }
    else if (version == 2) { 
	getTaskSet("simulation")    ->setIds(0);
	getTaskSet("real")          ->setIds(1,2,3,4,5,6,7,8);
	getTaskSet("calibration")   ->setIds(9,10,11,12);
	getTaskSet("real1")         ->setIds(1);
	getTaskSet("real2")         ->setIds(2);
	getTaskSet("real3")         ->setIds(3);
	getTaskSet("real4")         ->setIds(4);
	getTaskSet("real5")         ->setIds(5);
	getTaskSet("real6")         ->setIds(6);
	getTaskSet("real7")         ->setIds(7);
	getTaskSet("real8")         ->setIds(8);
	getTaskSet("MDCcalibration")   ->setIds(9);
	getTaskSet("SHOWERcalibration")->setIds(10);
	getTaskSet("SHOWERpedestals")  ->setIds(11);
	getTaskSet("RICHpedestals")    ->setIds(12);
        getTaskSet("CTSStatusConfig")  ->setIds(14);
	getTaskSet("beginrun") -> setIds(-1,-1,-1,-1,-1,-1,-1,-1) ;
	getTaskSet("endrun")   -> setIds(-1,-1,-1,-1,-1,-1,-1,-1) ;
    }
    else
    {
	Error("initTaskSetsIDs()","Unknown version %i ... exiting!",version);
	exit(EXIT_FAILURE);
    }
}
Hades *gHades;