"Original container name" + "_" + "Context name"Having different names, they can be read and written from/to the same ROOT file without the need to change the version management. Each parameter container has a default context. As long as a parameter container does not support deffferent context, the default context is an empty string. When implementing differend contexts, one is choosen as default (e.g. RichAnaNormalBias for the RICH analysis parameters). For backward compatibility the name of the parameter container is the original container name and not the concatinated name.
(See .../base/runtimedb/hcontfact.h) class HContainer : public TNamed { private: HContainer(); protected: TList* contexts; // available contexts for this parameter container TString actualContext; // actual context set by the user public: HContainer( const char*, const char*, const char*); ~HContainer(); void addContext(const char*); Bool_t setActualContext(const char* c); const char* getDefaultContext(); const char* getActualContext() { return actualContext.Data(); } void print(); TString getConcatName(); const char* getContext(); ClassDef(HContainer,0) // class for list elements in class HContFact }; class HContFact : public TNamed { protected: TList* containers; // all parameter containers managed by this factory public: HContFact(); virtual ~HContFact(); Bool_t addContext(const char* name); void print(); HParSet* getContainer(const char*); virtual HParSet* createContainer(HContainer*) {return 0;} protected: const char* getActualContext(const char* name) { return ((HContainer*)containers->FindObject(name))->getActualContext(); } ClassDef(HContFact,0) // base class of all factories for parameter containers };(See .../base/runtimedb/hcontfact.cc) ///////////////////////////////////////////////////////////// // // HContFact // // Base class of all factories for the parameter containers // ///////////////////////////////////////////////////////////// #include "hcontfact.h" #include "hades.h" #include "hruntimedb.h" #include "TObjString.h" #include <iostream.h> ClassImp(HContainer) ClassImp(HContFact) HContainer::HContainer() { contexts=0; } // Default constructor HContainer::HContainer(const char* name, const char* title, const char* defContext) : TNamed(name, title) { // Constructor // Arguments: name = name of the corresponding parameter container // title = title of this parameter container // defContext = default context of this parameter container contexts=new TList; addContext(defContext); actualContext=""; } HContainer::~HContainer() { // Destructor deletes the list of accepted contexts if (contexts) { contexts->Delete(); delete contexts; } } void HContainer::addContext(const char* name) { // Adds a context to the list of accepted contexts TObjString* c=new TObjString(name); contexts->Add(c); } Bool_t HContainer::setActualContext(const char* c) { // The function sets the actual context for the container, if it is in the list of // accepted contexts. When the actual context was already set before, it prints a warning // and ignores the second setting. // The function returns kFALSE, when the context is not in the list. if (contexts->FindObject(c)) { if (actualContext.IsNull()) actualContext=c; else Warning("addContext", "Actual context of parameter container %s already defined as %s", GetName(),actualContext.Data()); return kTRUE; } return kFALSE; } const char* HContainer::getDefaultContext() { // Returns the default context return ((TObjString*)contexts->At(0))->String().Data(); } void HContainer::print() { // prints the name, title of the container together with the actual context set // or all possible contexts, when the actual context was not set cout<String().IsNull()) cout<<" \"\""; else cout<<" "< String(); if (i==0) cout<<"\t default"; cout<<"\n"; i++; } } } TString HContainer::getConcatName() { // Returns the name of the parameter container used in the constructor and the // runtime database. // When the parameter container supportes different contexts (not only an empty string) // and the actual context set is not the default context, the new name of the parameter // container is concatinated as // original container name + _ + actualcontext TString cn=fName; if (!actualContext.IsNull() && actualContext!=((TObjString*)contexts->At(0))->String()) { cn+="_"; cn+=actualContext; } return cn; } const char* HContainer::getContext() { // return the actual context, if set, or the default context if (!actualContext.IsNull()) return actualContext.Data(); else return getDefaultContext(); } //------------------------------------------------------------------ HContFact::HContFact() : TNamed() { // Constructor creates a list to store objects of type HContainer containers=new TList; } HContFact::~HContFact() { // Destructor deletes the container list and its elements containers->Delete(); delete containers; } Bool_t HContFact::addContext(const char* name) { // Set the actual context in all containers, which accept this context HContainer* c=0; Bool_t found=kFALSE; TIter next(containers); while ((c=(HContainer*)next())) { if (c->setActualContext(name)) found=kTRUE; } return found; } HParSet* HContFact::getContainer(const char* name) { // Returns the pointer to the parameter container in the runtime database // If this parameter container does not yet exit, it calls the function // createContainer(HContainer*), which is implemented in the derived classes // and calls the corresponding constructor. Then the pointer it added in the // runtime database. HContainer* c=(HContainer*)(containers->FindObject(name)); HParSet* cont=0; if (c) { TString cn=c->getConcatName(); HRuntimeDb* rtdb=gHades->getRuntimeDb(); if (!(cont=rtdb->findContainer(c->getConcatName().Data()))) { if (strlen(c->getActualContext())==0) c->setActualContext(c->getDefaultContext()); cont=createContainer(c); if (cont) rtdb->addContainer(cont); else Error("getContainer(const char* name)","Container %s not created",name); } } return cont; } void HContFact::print() { // Loops over all containers in the list and calls their print() function cout<<"---------------------------------------------------------------------------"<<"\n"; cout< print(); }
(See .../rich/hrichcontfact.h) class HRichContFact : public HContFact { private: void setAllContainers(); public: HRichContFact(); ~HRichContFact() {} HParSet* createContainer(HContainer*); ClassDef(HRichContFact,0) // Factory for parameter containers in libRich };(See .../rich/hrichcontfact.cc) ///////////////////////////////////////////////////////////// // // HRichContFact // // Factory for the parameter containers in libRich // ///////////////////////////////////////////////////////////// #include "hrichcontfact.h" #include "hruntimedb.h" #include "hrichanalysis.h" #include "hrichcalpar.h" #include "hrichcorrelatorpar.h" #include "hrichdigitisationpar.h" #include "hrichgeometrypar.h" #include "hrichmappingpar.h" #include <iostream.h> ClassImp(HRichContFact) static HRichContFact gHRichContFact; // instantiated when libRich is loaded HRichContFact::HRichContFact() { // Constructor (called when the library is loaded) fName="RichContFact"; fTitle="Factory for parameter containers in libRich"; setAllContainers(); HRuntimeDb::instance()->addContFactory(this); } //============================================================================ //---------------------------------------------------------------------------- void HRichContFact::setAllContainers() { // Creates the Container objects with all accepted contexts and adds them to // the list of containers for the Rich library. HContainer* ca=new HContainer("RichAnalysisParameters", "Rich Analysis Parameters", "RichAnaNormalBias"); ca->addContext("RichAnaMinimumBias"); ca->addContext("RichAnaHighBias"); containers->Add(ca); containers->Add( new HContainer("RichCalPar", "Rich Calibration Parameters", "")); HContainer* cc=new HContainer("RichCorrelatorParameters", "Rich Correlator Parameters", "RichCorrSharpCut"); cc->addContext("RichCorrWideCut"); cc->addContext("RichCorrSharpPhiWideThe"); containers->Add(cc); HContainer* cd=new HContainer("RichDigitisationParameters", "Rich Digitisation Parameters", "RichDigiNoiseOn"); cd->addContext("RichDigiNoiseOff"); containers->Add(cd); containers->Add( new HContainer("RichGeometryParameters", "Rich Geometry Parameters", "")); containers->Add( new HContainer("RichMappingParameters", "Rich Mapping Parameters", "")); } //============================================================================ //---------------------------------------------------------------------------- HParSet* HRichContFact::createContainer(HContainer* c) { // Calls the constructor of the corresponding parameter container. // For an actual context, which is not an empty string and not the default context // of this container, the name is concatinated with the context. const char* name=c->GetName(); if (strcmp(name,"RichAnalysisParameters")==0) return new HRichAnalysisPar(c->getConcatName().Data(),c->GetTitle(),c->getContext()); if (strcmp(name,"RichCalPar")==0) return new HRichCalPar(c->getConcatName().Data(),c->GetTitle(),c->getContext()); if (strcmp(name,"RichCorrelatorParameters")==0) return new HRichCorrelatorPar(c->getConcatName().Data(),c->GetTitle(),c->getContext()); if (strcmp(name,"RichDigitisationParameters")==0) return new HRichDigitisationPar(c->getConcatName().Data(),c->GetTitle(),c->getContext()); if (strcmp(name,"RichGeometryParameters")==0) return new HRichGeometryPar(c->getConcatName().Data(),c->GetTitle(),c->getContext()); if (strcmp(name,"RichMappingParameters")==0) return new HRichMappingPar(c->getConcatName().Data(),c->GetTitle(),c->getContext()); return 0; }
class HRuntimeDb : public TObject { private: static HRuntimeDb* gRtdb; //! protected: HRuntimeDb(void); TList* contFactories; //! list of container factories ... public: static HRuntimeDb* instance(void); ... Bool_t addParamContext(const char*); void printParamContexts(); void addContFactory(HContFact*); HParSet* getContainer(Text_t*); HParSet* findContainer(const char*); ...(See .../base/runtimedb/hruntimedb.h for complete class definition)   ... HRuntimeDb* HRuntimeDb::gRtdb=0; HRuntimeDb* HRuntimeDb::instance(void) { if (gRtdb==0) gRtdb=new HRuntimeDb; return gRtdb; } HRuntimeDb::HRuntimeDb(void) { // constructor creates an empty list for parameter containers // and an empty list of runs for the version management gRtdb=this; contFactories=new TList(); containerList=new TList(); runs=new TList(); firstInput=0; secondInput=0; output=0; versionsChanged=kFALSE; currentRun=0; isRootFileOutput=kFALSE; } HRuntimeDb::~HRuntimeDb() { // destructor // deletes the list of runs and all containers closeFirstInput(); closeSecondInput(); closeOutput(); if (containerList) { containerList->Delete(); delete containerList; } if (runs) { runs->Delete(); delete runs; } if (contFactories) { contFactories->Delete(); delete contFactories; } gRtdb=0; } void HRuntimeDb::addContFactory(HContFact* fact) { // Adds a container factory to the list of factories if (!(contFactories->FindObject(fact->GetName()))) contFactories->Add(fact); } Bool_t HRuntimeDb::addParamContext(const char* context) { // Sets via the container factories the context of all parameter containers, // which accept this context Bool_t found=kFALSE; TIter next(contFactories); HContFact* fact; while((fact=(HContFact*)next())) { if (fact->addContext(context)) found=kTRUE; } if (!found) Error("addParamContext","Unknown context"); return found; } void HRuntimeDb::printParamContexts() { // Prints the context of all parameter containers, which can be created by // the container factories TIter next(contFactories); HContFact* fact; while((fact=(HContFact*)next())) fact->print(); } HParSet* HRuntimeDb::getContainer(Text_t* name) { // The function loops over the container factories to find the corresponding container // with the give name and its context. // The name is the original name of the parameter container without the concatination // with the context. // The factory checks, if the container exists already in the runtime database. Otherwise // it will be created and added by the factory. // The function returns a pointer to the container or NULL, if not created. TIter next(contFactories); HContFact* fact; HParSet* c=0; while(!c && (fact=(HContFact*)next())) { c=fact->getContainer(name); } if (!c) Error("getContainer","Container %s not created!",name); return c; } HParSet* HRuntimeDb::findContainer(const char* name) { // Returns a pointer to the container called by name // The name is the original name of the parameter container eventually concatinated with // a non-default context. return (HParSet*)(containerList->FindObject(name)); } ...(See .../base/runtimedb/hruntimedb.cc for complete implementation)
The old default constructor without any arguments has been changed to a constructor with three arguments:
class HParSet : public TNamed { protected: ... TString paramContext; //! Context/purpose for conditions TString author; //! Author of parameters TString description ; //! Description of parameters public: HParSet(const char* name="",const char* title="",const char* context=""); ... void setParamContext(const char*); const char* getParamContext() const { return paramContext.Data(); } void setAuthor(const char* s) {author=s;} const char* getAuthor() const { return author.Data(); } void setDescription(const char* s) {description=s;} const char* getDescription() const { return description.Data(); } ClassDef(HParSet,2) // Base class for all parameter containers };(See .../base/runtimedb/hparset.cc for implementation)
name, title, default contextThe constructors of all parameter containers must be changed, but existing code still compiles as long as the corresonding container factory is not added.
The class has gotten three additional data-elements:
(See .../rich/hrichcalpar.h) class HRichCalPar : public HRichParSet { public: HRichCalPar(const char* name="RichCalPar", const char* title="Rich Calibration Parameters", const char* context=""); ...(See .../rich/hrichcalpar.cc) HRichCalPar::HRichCalPar(const char* name,const char* title, const char* context) : HRichParSet(name,title,context) { m_pReadParam = NULL; setSetup(6, 96, 96); //default setup // setSetup(6, 64, 64); //default setup old setCellClassName("HRichCalParCell"); }
HParSet* HRuntimeDb::getContainer(Text_t* name)takes care, that a non-existing parameter container is created automatically via the factory, the blue marked lines, typically found in the old code, are obsolete. They should be removed, because they create always a container with the default context, which might be wrong.
HRuntimeDb* rtdb=gHades->getRuntimeDb(); fCalPar = rtdb->getContainer("RichCalPar"); if (!fCalPar) { fCalPar= new HRichCalPar; rtdb->addContainer(fCalPar); }
{ Hades* myHades=new Hades; HRuntimeDb* rtdb=gHades->getRuntimeDb(); HSpectrometer* spec=gHades->getSetup(); HRichDetector* rich=new HRichDetector; spec->addDetector(rich); HParOraIo* inp1=new HParOraIo; inp1->open(); rtdb->setFirstInput(inp1); HParRootFileIo* output=new HParRootFileIo; output->open("tmp.root","RECREATE"); rtdb->setOutput(output); //////////////////////////////// RICH //////////////////////////////////////// rtdb->addParamContext("RichAnaHighBias"); HRichAnalysisPar* p1=(HRichAnalysisPar*)(rtdb->getContainer("RichAnalysisParameters")); // Second version with defaults: context = RichAnaNormalBias HRichAnalysisPar* p2=new HRichAnalysisPar; rtdb->addContainer(p2); if (!rtdb->initContainers(1007785790)) return; p1->print(); p2->print(); //////////////////////////////////////////////////////////////////////////////// rtdb->saveOutput(); rtdb->print(); delete myHades; }