/*************************************************************************** * Copyright (C) 200_ by Olivier Stezowski * * stezow(AT)ipnl.in2p3.fr * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * aLong_t with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ /** \file ConfAgent.cpp compiled in libGWADF.so */ #ifndef ADF_ConfAgent #include "ConfAgent.h" #endif #ifndef ADF_KeyFactory #include "KeyFactory.h" #endif #ifndef ADF_ConfigurationFrame #include "ConfigurationFrame.h" #endif #include #include #include ADF::ConfAgent *ADF::ConfAgent::gTheGlobalAgent = 0x0; using namespace ADF; using namespace std; namespace { UInt_t gAllocated = 0u; } ConfAgent::ConfAgent() : fLog("ConfAgent"), fModel(kStrict), fLastModif(""), fComment("Default"), fEndian(BaseBuffer::kLittle), fPrimaryKey("Default","FS",Version(0,1)) , fAutoConf(), fListOfFrames(), fListOfFactories() { // the three main factories are added to the main factory in case it has not yet been done // key factory if ( !KeyFactory::IsKnown("Agata") ) KeyFactory::Register("Agata"); if ( !KeyFactory::IsKnown("Default") ) KeyFactory::Register("Default"); // Frame factory if ( !FrameFactory::IsKnown("Agata") ) FrameFactory::Register("Agata"); // prepare factories for the current endian KeyFactory::SetEndian(fEndian,std::string("all")); // frame for automatic reconfiguration fAutoConf.first = FactoryItem("NONE","NONE",Version(0,0)); fAutoConf.second = FactoryItem("NONE","NONE",Version(0,0)); // configuration from the input file of the distribution // if not found in the install path (make install not done properly) // try in the current directory std::string tmp; Bool_t is_one = false; // first the one in the distribution tmp = GetPathToConfFile(); if ( tmp.size() > 0 && !(tmp.at(tmp.size()-1) == '/') ) tmp += '/'; tmp += "ADF.conf"; if ( Configure(tmp.data(),"in") ) is_one = true; // second the one in the ADF_CONF_PATH path if ( ::getenv("ADF_CONF_PATH") ) { tmp = ::getenv("ADF_CONF_PATH"); if ( tmp.size() > 0 && !(tmp.at(tmp.size()-1) == '/') ) tmp += '/'; tmp += "ADF.conf"; if ( Configure(tmp.data(),"in") ) { is_one = true; } if ( !is_one ) { Configure("./ADF.conf","in"); } } SetLastModif(); } ConfAgent::ConfAgent(const char *comment) : fLog("ConfAgent"), fModel(kStrict), fLastModif(""), fComment(comment), fEndian(BaseBuffer::kLittle), fPrimaryKey("Default","FS",Version(0,1)) , fAutoConf(), fListOfFrames(), fListOfFactories() { // prepare factories for the current endian KeyFactory::SetEndian(fEndian,std::string("all")); // to remove end of line character if (fComment.size() > 0) if ( fComment.at(fComment.length()-1) == '\n' ) fComment.erase(fComment.size()-1); SetLastModif(); } ConfAgent::~ConfAgent() { fListOfFrames.clear(); fListOfFactories.clear(); gAllocated--; if ( gAllocated == 0 ) { #ifdef DEBUGSTATIC std::clog << "[[static]] ConfAgent::~ConfAgent() ]\n[...\n" ; #endif KilltheGlobalAgent(); #ifdef DEBUGSTATIC std::clog << " done\n...]\n"; #endif } } ConfAgent::EModel ConfAgent::GetModel(std::string model) { ConfAgent::EModel m = ConfAgent::kSafe; if ( model == "kStrict" ) m = ConfAgent::kStrict; if ( model == "kSafe" ) m = ConfAgent::kSafe; if ( model == "kGrowing" ) m = ConfAgent::kGrowing; return m; } const char *ConfAgent::GetStringModel(EModel m) const { const char *model = NULL; switch (m) { case kStrict: model = "kStrict"; break; case kSafe: model = "kSafe"; break; case kGrowing: model = "kGrowing"; break; } return model; } ConfAgent *ConfAgent::theGlobalAgent() { if ( gTheGlobalAgent == NULL ) { #ifdef DEBUGSTATIC std::clog << "[[static]] Creating the global ConfAgent ]\n[...\n"; #endif gTheGlobalAgent = new ConfAgent(); #ifdef DEBUGSTATIC if ( gTheGlobalAgent ) std::clog << " done\n...]\n"; else { std::clog << " *** ERROR *** \n"; std::clog << "...]\n"; } #endif } return gTheGlobalAgent; } void ConfAgent::KilltheGlobalAgent() { if ( gTheGlobalAgent && gAllocated == 0 ) { #ifdef DEBUGSTATIC std::clog << "[[static]] KilltheGlobalAgent() ]\n[...\n" ; std::clog << " Destroying the global agent ... " << std::endl; #endif delete gTheGlobalAgent; #ifdef DEBUGSTATIC std::clog << " done\n...]\n"; #endif gTheGlobalAgent = NULL; } } const FactoryItem &ConfAgent::GetPrimaryKey() const { return fPrimaryKey; } void ConfAgent::SetPrimaryKey(const FactoryItem &item) { fPrimaryKey = item; } void ConfAgent::AddKnownFrame(const FactoryItem &item_key, const FactoryItem &item_frame, const Char_t opt) { if ( opt == 'r' ) fListOfFrames.clear(); pair p; p.first = item_key; p.second = item_frame; fListOfFrames.push_back(p); } void ConfAgent::AddKnownFrame(const Frame *frame, const Char_t opt) { if ( frame ) AddKnownFrame(frame->GetKey()->GetSignatureImplementation(),frame->GetSignatureImplementation(),opt); } void ConfAgent::SetLastModif() { time_t thetime; ::time(&thetime); fLastModif = ::ctime(&thetime); // to remove end of line character if (fLastModif.size() > 0) if ( fLastModif.at(fLastModif.length()-1) == '\n' ) fLastModif.erase(fLastModif.size()-1); } void ConfAgent::Reset(const Char_t *opt) { std::string option = opt; /*fComment = "Reset"; */ SetLastModif(); fEndian = BaseBuffer::kLittle; fPrimaryKey = FactoryItem("Default","FS",Version(0,1)); fAutoConf.first = FactoryItem("NONE","NONE",Version(0,0)); fAutoConf.second = FactoryItem("NONE","NONE",Version(0,0)); fListOfFrames.clear(); fListOfFactories.clear(); } ConfAgent *ConfAgent::Clone(const char *comment) { // check the global agent exists ConfAgent::theGlobalAgent(); // first creats a new agent ConfAgent *aconf = new ConfAgent(comment); if ( aconf == NULL ) return NULL; // add one more allocated Agent gAllocated++; // now copy the content of the global agent to it using Configure std::ostringstream o; ConfAgent::theGlobalAgent()->DoConfigure(o); std::string tmp; tmp = o.str(); std::istringstream i(tmp); aconf->DoConfigure(i); return aconf; } /* UShort_t ConfAgent::IsAKnownFrame (const Frame *f,PF_FactoryItemChange kch = ChangeOfVersion, PF_FactoryItemChange fch = ChangeOfVersion) const { return IsAKnownFrame( f->GetKey()->GetSignatureImplementation(), f->GetSignatureImplementation(), kch,fch); } */ UShort_t ConfAgent::IsAKnownFrame (const FactoryItem &to_key, const FactoryItem &to_frame, PF_FactoryItemChange pfk, PF_FactoryItemChange pff) const { UShort_t ok; Bool_t ok_key, ok_frame; ok = 0u; std::list< std::pair >::iterator listed_item; for ( listed_item = fListOfFrames.begin() ; listed_item != fListOfFrames.end() ; listed_item++ ) { ok_key = pfk ( (*listed_item).first , to_key ); ok_frame = pff ( (*listed_item).second , to_frame ); if ( ok_key && ok_frame ) { ok++; } } return ok; } FactoryItem ConfAgent::WhichKnownFrame (const FactoryItem &to_key, const FactoryItem &to_frame, PF_FactoryItemChange pfk, PF_FactoryItemChange pff) const { FactoryItem ok; Bool_t ok_key, ok_frame; std::list< pair >::iterator listed_item; for ( listed_item = fListOfFrames.begin() ; listed_item != fListOfFrames.end() ; listed_item++ ) { ok_key = pfk ( (*listed_item).first , to_key ); ok_frame = pff ( (*listed_item).second , to_frame ); if ( ok_key && ok_frame ) { ok = (*listed_item).second; break; } } return ok; } /* UShort_t ConfAgent::WhichKnownFrame (const Frame *f,PF_FactoryItemChange kch = ChangeOfVersion, PF_FactoryItemChange fch = ChangeOfVersion) const { FactoryItem itk = f->GetKey()->GetSignatureImplementation(); FactoryItem itf = f->GetSignatureImplementation(); return WhichKnownFrame(itk,itf,kch,fch); } */ FactoryItem ConfAgent::WhichKnownKey (const FactoryItem &to_key, const FactoryItem &to_frame, PF_FactoryItemChange pfk, PF_FactoryItemChange pff) const { FactoryItem ok; Bool_t ok_key, ok_frame; std::list< pair >::iterator listed_item; for ( listed_item = fListOfFrames.begin() ; listed_item != fListOfFrames.end() ; listed_item++ ) { ok_key = pfk ( (*listed_item).first , to_key ); ok_frame = pff ( (*listed_item).second , to_frame ); if ( ok_key && ok_frame ) { ok = (*listed_item).first; break; } } return ok; } void ConfAgent::ProcessLine(const string &aline) { string tmp1, tmp2, tmp3; UInt_t ui1, ui2; if ( aline.find("Endian:") == 0 ) { istringstream decode(aline); // just to be sure ... decode.clear(); decode >> tmp1 >> tmp2; if ( decode.good() ) { // expected format if ( tmp2 == "kLittle" ) { fEndian = BaseBuffer::kLittle; } if ( tmp2 == "kBig" ) { fEndian = BaseBuffer::kBig; } } } // check needed Key factories exist if ( aline.find("KeyFactory:") == 0 ) { istringstream decode(aline); // just to be sure ... decode.clear(); decode >> tmp1 >> tmp2 ; if ( decode.good() ) { // expected format if ( KeyFactory::GetFactory(tmp2.data()) == NULL ) { fLog << error << "The KeyFactory " << tmp2.data() << " is not registered \n"; } else { std::pair p; p.first = tmp1; p.second = tmp2; fListOfFactories.push_back(p); } } }// tmp.find("KeyFactory:") == 0 check needed factories exist // check needed Frame factories exist if ( aline.find("FrameFactory:") == 0 ) { istringstream decode(aline); // just to be sure ... decode.clear(); decode >> tmp1 >> tmp2 ; if ( decode.good() ) { // expected format if ( FrameFactory::GetFactory(tmp2.data()) == NULL ){ fLog << error << "The FrameFactory " << tmp2.data() << " is not registered \n"; } else { std::pair p; p.first = tmp1; p.second = tmp2; fListOfFactories.push_back(p); } } }// tmp.find("FrameFactory:") == 0 check needed factories exist if ( aline.find("PrimaryKey:") == 0 ) { // this is the primary key (input) istringstream decode(aline); // just to be sure ... decode.clear(); decode >> tmp1 >> tmp2 >> tmp3 >> ui1 >> ui2; if ( decode.good() ) { // expected format Key *tmpkey = NULL; tmpkey = KeyFactory::theMainFactory().New(tmp2.data(),tmp3.data(),Version(ui1,ui2)); // valid key, otherwise does not change defaults if ( tmpkey ) { fPrimaryKey.SetItem(tmp2.data(),tmp3.data(),Version(ui1,ui2)); delete tmpkey; } else { fLog << error << "PrimaryKey " << tmp2.data() << " is not known \n"; } } } // this is the primary key (input) if ( aline.find("AutoConf:") == 0 ) { // this is the primary key (output) istringstream decode(aline); // just to be sure ... decode.clear(); // decode >> tmp1 >> tmp2 >> tmp3 >> ui1 >> ui2; FactoryItem itemkey, itemframe; decode >> tmp1 >> itemkey >> itemframe; if ( decode.good() ) { // expected format Key *tmpkey = NULL; tmpkey = KeyFactory::theMainFactory().New(itemkey); // valid key, otherwise does not change defaults if ( tmpkey ) { fAutoConf.first = itemkey; fAutoConf.second = itemframe; delete tmpkey; } else { fLog << error << "AutoConf " << itemkey << itemframe << " is not known \n"; } } }// this is the primary key (for output) if ( aline.find("Frame:") == 0 ) { // list of frames going through the data flow std::istringstream decode(aline); // just to be sure ... decode.clear(); FactoryItem itemkey, itemframe; // decode >> tmp1 >> tmp2 >> tmp3 >> ui1 >> ui2; decode >> tmp1 >> itemkey ; decode >> itemframe; if ( decode.good() ) { // expected format std::pair < FactoryItem, FactoryItem > p; p.first = itemkey; p.second = itemframe; fListOfFrames.push_back(p); // try to allocated a frame to check if it is known by factories /* Frame *frame = FrameFactory::theMainFactory().New(item); if ( frame ) { // a valid frame Bool_t isin = false; std::list::iterator listed_item; for (listed_item = fListOfFrames.begin(); listed_item != fListOfFrames.end() ; listed_item++ ) if ( (*listed_item) == item ) { isin = true; break; } if ( !isin ) { fListOfFrames.push_back(item); } delete frame; } */ } else { ;} } // if ( tmp.find("Frame:") == 0 ) /* if ( aline.find("LogCollector:") == 0 ) { // Log server to be used istringstream decode(aline); // just to be sure ... decode.clear(); decode >> tmp1 >> tmp2 ; if ( decode.good() ) { // expected format G::LogServer = tmp2; } } // tmp.find("LogCollector:") == 0 if ( aline.find("FrameIO:") == 0 ) { // Default FrameIO istringstream decode(aline); // just to be sure ... decode.clear(); decode >> tmp1 >> tmp2 ; } //tmp.find("FrameIO:") == 0 */ } Bool_t ConfAgent::DoConfigure (istream &in) { fLog.GetProcessMethod() = "Configure(istream)"; // local required string tmp, bor = BeginOfRecord("ADF::ConfAgent"), eor = EndOfRecord("ADF::ConfAgent") , option; Bool_t is_a_record = false, do_process = false; // look for a configuation record for this class getline(in,tmp); tmp += " "; while ( in.good() && !in.eof() ) { // read input stream line by line if ( tmp[0] == '#' ) { // this is a start of record statement for that class if ( tmp.find(bor) == 0 ) { // get option option = tmp.substr(bor.length()+1); // now all line are processed by ProcessLine if ( option.find("Init") != string::npos ) Reset(); do_process = is_a_record = true; } // this is a end of record statement for that class if ( tmp.find(eor) == 0 ) { option = ""; do_process = false; } getline(in,tmp); tmp += " "; continue; } // this line is a comment if (do_process) ProcessLine(tmp); // add null character at the end since getline // does not store \n and it may give troubles when decoding getline(in,tmp); tmp += " "; } // the LogCollector may have been changed ... so wait util the end to apply collection if ( ! is_a_record ) { fLog << " Agent coming from " << fComment ; fLog << warning << " expecting a configuration record but not found \n"; } // now call it for all the registred factories Bool_t is_a_factory_record = KeyFactory::theMainFactory().DoConfigure(in); if ( is_a_factory_record ) is_a_record = true; return is_a_record; } Bool_t ConfAgent::DoConfigure (ostream &out) { // set reference to this method for log system fLog.GetProcessMethod() = "Configure(ostream)"; out.clear(); // local required string tmp, bor = BeginOfRecord("ADF::ConfAgent"), eor = EndOfRecord("ADF::ConfAgent") , option; // The global conf should be read correctly whatever the key length (for frame) // so fill with blank the beginning to avoid loosing the real beginning of the record (bor) out << ends << ends << ends << ends << ends << ends << ends << ends << ends << ends << ends << ends; out << ends << ends << ends << ends << ends << ends << ends << ends << endl; out << "# \n"; out << "#////ADF::ConfAgent_beg//// Agata 1 Init \n" ; // version number in case of futur developments. out << "# \n"; out << "# Last modified by : "<< fLastModif << " \n"; out << "# Modified by : " << fComment << " \n"; out << "VersionADF: " << GetVersion() << " \n"; out << "# \n"; out << "# Endian type \n"; out << "Endian: "; if ( fEndian == BaseBuffer::kLittle ) out << "kLittle \n"; else out << "kBig \n"; out << "# Factories for Frames & Keys \n" ; out << "# \n"; // loop on required factories std::list< pair >::iterator listed_item; for (listed_item = fListOfFactories.begin(); listed_item != fListOfFactories.end() ; listed_item++ ){ out << (*listed_item).first << " " << (*listed_item).second << " \n"; } out << "# \n"; out << "# Version of the primary keys that structure the data flow \n"; out << "# \n"; out << "PrimaryKey: " << fPrimaryKey << " \n"; out << "# \n"; out << "AutoConf:" << fAutoConf.first << fAutoConf.second << " \n"; out << "# \n"; out << "# Current Frames going through the data flow \n"; out << "# \n"; // loop on frames defining the data flow std::list< pair >::iterator listed_fitem; for (listed_fitem = fListOfFrames.begin(); listed_fitem != fListOfFrames.end() ; listed_fitem++ ){ out << "Frame: " << (*listed_fitem).first << (*listed_fitem).second << " " << std::endl; } // loop on frames defining the data flow out << "#////ADF::ConfAgent_end//// \n"; /* out << "" << std::endl; out << "" << std::endl; out << "" << std::endl; out << "" << std::endl; out << "" << std::endl; */ // now call it for all the registred factories KeyFactory::theMainFactory().DoConfigure(out); out << "# \n"; return out.good(); } Bool_t ConfAgent::Configure(const char *name, const char *option) { // set reference to this method for log system fLog.ClearMessage(); fLog.GetProcessMethod() = "Configure(const char *name)"; Bool_t ok; std::string opt = option; if ( opt == "in" ) { std::ifstream filein(name); if ( filein.is_open() == true ) { ok = DoConfigure(filein); } else ok = false; filein.close(); } else { std::ofstream fileout(name); if ( fileout.is_open() == true ) { ok = DoConfigure(fileout); } else ok = false; fileout.close(); } fLog << dolog; return ok; } Bool_t ConfAgent::Configure(ConfigurationFrame *frame, const char *option) { // set reference to this method for log system fLog.GetProcessMethod() = "Configure(ConfigurationFrame *name)"; Bool_t ok; std::string opt = option; if ( opt == "in" ) { // load the content of the frame in the string frame->Read(); // use stream facility std::istringstream in; in.clear(); in.str((frame->String())); ok = DoConfigure(in); } else { // use stream facility std::ostringstream out; ok = DoConfigure(out); frame->String() = out.str(); frame->Write(); } fLog << dolog; return ok; }