Gaudi Framework, version v21r8

Home   Generated: 17 Mar 2010

configGenerator Class Reference

Collaboration diagram for configGenerator:

Collaboration graph
[legend]

List of all members.

Public Member Functions

 configGenerator (const string &pkgName, const string &outputDirName)
int genConfig (const Strings_t &modules)
 main entry point of this class:
  • iterate over all the modules (ie: library names)
  • for each module extract component informations
  • eventually generate the header/body/trailer python file and "Db" file

void setConfigurableModule (const std::string &moduleName)
 customize the Module name where configurable base classes are defined
void setConfigurableDefaultName (const std::string &defaultName)
 customize the default name for configurable instances
void setConfigurableAlgorithm (const std::string &cfgAlgorithm)
 customize the configurable base class for Algorithm component
void setConfigurableAlgTool (const std::string &cfgAlgTool)
 customize the configurable base class for AlgTool component
void setConfigurableAuditor (const std::string &cfgAuditor)
 customize the configurable base class for AlgTool component
void setConfigurableService (const std::string &cfgService)
 customize the configurable base class for Service component

Private Member Functions

void genComponent (const std::string &libName, const std::string &componentName, const std::string &componentType, const vector< Property * > &properties)
void genImport (std::ostream &s, const boost::format &frmt, std::string indent)
void genHeader (std::ostream &pyOut, std::ostream &dbOut)
void genBody (std::ostream &pyOut, std::ostream &dbOut)
void genTrailer (std::ostream &pyOut, std::ostream &dbOut)
void pythonizeValue (const Property *prop, string &pvalue, string &ptype)
 handle the "marshalling" of Properties
void pythonizeName (string &name)
 Translates a valid C++ typename into a valid python one.

Private Attributes

string m_pkgName
 name of the package we are processing
string m_outputDirName
 absolute path to the directory where genconf will store auto-generated files (Configurables and ConfigurableDb)
stringstream m_pyBuf
 buffer of auto-generated configurables
bool m_importGaudiHandles
 switch to decide if the generated configurables need to import GaudiHandles (ie: if one of the components has a XyzHandle<T>)
stringstream m_dbBuf
 buffer of generated configurables informations for the "Db" file The "Db" file is holding informations about the generated configurables This file is later one used by the PropertyProxy.py to locate Configurables and know their default values, host module,.
GaudiUtils::HashMap
< std::string, std::string
m_configurable
 Configurable customization.


Detailed Description

Definition at line 78 of file genconf.cpp.


Constructor & Destructor Documentation

configGenerator::configGenerator ( const string &  pkgName,
const string &  outputDirName 
) [inline]

Definition at line 108 of file genconf.cpp.

00109                                                  :
00110     m_pkgName           ( pkgName ),
00111     m_outputDirName     ( outputDirName ),
00112     m_pyBuf             ( ),
00113     m_importGaudiHandles( false ),
00114     m_dbBuf             ( ),
00115     m_configurable      ( )
00116   {}


Member Function Documentation

int configGenerator::genConfig ( const Strings_t modules  ) 

main entry point of this class:

  • iterate over all the modules (ie: library names)
  • for each module extract component informations
  • eventually generate the header/body/trailer python file and "Db" file

not enough information... skip it

no Properties, so don't bother create Configurables...

: no Configurable for this component. yet... continue;

write-out files for this library

Definition at line 430 of file genconf.cpp.

00432 {
00433   //--- Disable checking StatusCode -------------------------------------------
00434   StatusCode::disableChecking();
00435 
00436   const Strings_t::const_iterator endLib = libs.end();
00437 
00438   const std::string gaudiSvc = "GaudiSvc";
00439   const bool isGaudiSvc = ( std::find( libs.begin(), endLib, gaudiSvc ) != endLib );
00440 
00441   //--- Instantiate ApplicationMgr --------------------------------------------
00442   if ( !isGaudiSvc && createAppMgr() ) {
00443     cout << "ERROR: ApplicationMgr can not be created. Check environment" << endl;
00444     return EXIT_FAILURE;
00445   }
00446 
00447   //--- Iterate over component factories --------------------------------------
00448   Scope factories = Scope::ByName(PLUGINSVC_FACTORY_NS);
00449   if ( !factories ) {
00450     cout << "ERROR: No PluginSvc factory namespace could be found" << endl;
00451     return EXIT_FAILURE;
00452   }
00453 
00454   ISvcLocator* svcLoc = Gaudi::svcLocator();
00455   IInterface*  dummySvc = new Service( "DummySvc", svcLoc );
00456   dummySvc->addRef();
00457 
00458   bool allGood = true;
00459 
00460   // iterate over all the requested libraries
00461   for ( Strings_t::const_iterator iLib=libs.begin(); iLib != endLib; ++iLib ) {
00462 
00463     std::cout << ":::: processing library: " << *iLib << "..." << std::endl;
00464 
00465     // reset state
00466     m_importGaudiHandles = false;
00467     m_pyBuf.str("");
00468     m_dbBuf.str("");
00469 
00470     // Scan the pluginSvc namespace and store the "background" of already
00471     // alive components, so we can extract our signal later on
00472     set<string> bkgNames;
00473     if ( !isGaudiSvc ) {
00474       for ( Member_Iterator it = factories.FunctionMember_Begin();
00475             it != factories.FunctionMember_End(); ++it ) {
00476         string ident = getId(*it);
00477         if ( PluginService::Debug() > 0 ) {
00478           cout << "::: " << ident << endl;
00479         }
00480         bkgNames.insert( ident );
00481       }
00482     }
00483     const set<string>::const_iterator bkgNamesEnd = bkgNames.end();
00484 
00485     //--- Load component library ----------------------------------------------
00486     System::ImageHandle handle;
00487     unsigned long err = System::loadDynamicLib( *iLib, &handle );
00488     if ( err != 1 ) {
00489       cout << "ERROR: " << System::getLastErrorString() << endl;
00490       allGood = false;
00491       continue;
00492     }
00493 
00494     for ( Member_Iterator it = factories.FunctionMember_Begin();
00495           it != factories.FunctionMember_End();
00496           ++it ) {
00497       const string ident = getId(*it);
00498       if ( bkgNames.find(ident) != bkgNamesEnd ) {
00499         if ( PluginService::Debug() > 0 ) {
00500           cout << "\t==> skipping [" << ident << "]..." << endl;
00501         }
00502         continue;
00503       }
00504 
00505       // Atlas contributed code (patch #1247)
00506       // Skip the generation of configurables if the component does not come
00507       // from the same library we are processing (i.e. we found a symbol that
00508       // is coming from a library loaded by the linker).
00509       // Windows implementation is empty.
00510       if ( !DsoUtils::inDso( *it, DsoUtils::libNativeName(*iLib) ) ) {
00511         cout << "WARNING: library [" << *iLib << "] requested factory "
00512         << "from another library ["
00513         << DsoUtils::dsoName(*it) << "]"
00514         << " ==> [" << ident << "] !!"
00515         << endl;
00516         continue;
00517       }
00518 
00519       const string rtype = it->TypeOf().ReturnType().Name();
00520       string type;
00521       bool known = true;
00522       if      ( ident == "ApplicationMgr" ) type = "ApplicationMgr";
00523       else if ( rtype == "IInterface*" )    type = "IInterface";
00524       else if ( rtype == "IAlgorithm*" )    type = "Algorithm";
00525       else if ( rtype == "IService*" )      type = "Service";
00526       else if ( rtype == "IAlgTool*" )      type = "AlgTool";
00527       else if ( rtype == "IAuditor*" )      type = "Auditor";
00528       else if ( rtype == "IConverter*" )    type = "Converter";
00529       else if ( rtype == "DataObject*" )    type = "DataObject";
00530       else                                  type = "Unknown", known = false;
00531       string name = ident;
00532       // handle possible problems with templated components
00533       boost::trim(name);
00534 
00535       cout << " - component: " << name << endl;
00536 
00537       if ( type == "IInterface" ) {
00540         continue;
00541       }
00542 
00543       if ( type == "Converter" || type == "DataObject" ) {
00545         continue;
00546       }
00547 
00548       //if ( type == "ApplicationMgr" ) {
00551       //}
00552 
00553       if ( !known ) {
00554         cout << "WARNING: Unknown (return) type [" << rtype << "] !!\n"
00555              << "WARNING: component [" << ident << "] is skipped !"
00556              << endl;
00557         allGood = false;
00558         continue;
00559       }
00560 
00561       string cname = "DefaultName";
00562       vector<void*>  args;
00563       args.reserve( 3 );
00564       if ( type == "AlgTool" ) {
00565         args.resize( 3 );
00566         args[0] = &cname;
00567         args[1] = &type;
00568         args[2] = dummySvc;
00569       }
00570       else {
00571         args.resize( 2 );
00572         args[0] = &cname;
00573         args[1] = svcLoc;
00574       }
00575       IProperty* prop = 0;
00576       try {
00577         if ( type == "Algorithm" ) {
00578           prop = makeInstance<IAlgorithm>(*it,args);
00579         }
00580         else if ( type == "Service") {
00581           prop = makeInstance<IService>(*it,args);
00582         }
00583         else if ( type == "AlgTool") {
00584           prop = makeInstance<IAlgTool>(*it,args);
00585         }
00586         else if ( type == "Auditor") {
00587           prop = makeInstance<IAuditor>(*it,args);
00588         }
00589         else if ( type == "ApplicationMgr") {
00590           //svcLoc->queryInterface(IProperty::interfaceID(), pp_cast<void>(&prop));
00591           svcLoc->queryInterface(IProperty::interfaceID(), (void**)(&prop));
00592         }
00593         else {
00594           prop = makeInstance<IInterface>(*it,args);
00595         }
00596       }
00597       catch ( exception& e ) {
00598         cout << "ERROR: Error instantiating " << name
00599              << " from " << *iLib << endl;
00600         cout << "ERROR: Got exception: " << e.what() << endl;
00601         allGood = false;
00602         continue;
00603       }
00604       catch ( ... ) {
00605         cout << "ERROR: Error instantiating " << name
00606              << " from " << *iLib << endl;
00607         allGood = false;
00608         continue;
00609       }
00610       if( prop ) {
00611         genComponent( *iLib, name, type, prop->getProperties() );
00612         prop->release();
00613       } else {
00614         cout << "ERROR: could not cast IInterface* object to an IProperty* !\n"
00615              << "ERROR: return type from PluginSvc is [" << rtype << "]...\n"
00616              << "ERROR: NO Configurable will be generated for ["
00617              << name << "] !"
00618              << endl;
00619         allGood = false;
00620       }
00621     } //> end loop over factories
00622 
00626     const std::string pyName = ( fs::path(m_outputDirName) /
00627                   fs::path(*iLib+"Conf.py") ).string();
00628     const std::string dbName = ( fs::path(m_outputDirName) /
00629                   fs::path(*iLib+"_confDb.py") ).string();
00630 
00631     std::fstream py( pyName.c_str(),
00632               std::ios_base::out|std::ios_base::trunc );
00633     std::fstream db( dbName.c_str(),
00634               std::ios_base::out|std::ios_base::trunc );
00635 
00636     genHeader ( py, db );
00637     genBody   ( py, db );
00638     genTrailer( py, db );
00639 
00640   } //> end loop over libraries
00641 
00642   dummySvc->release();
00643   dummySvc = 0;
00644 
00645   return allGood ? EXIT_SUCCESS : EXIT_FAILURE;
00646 }

void configGenerator::setConfigurableModule ( const std::string moduleName  )  [inline]

customize the Module name where configurable base classes are defined

Definition at line 125 of file genconf.cpp.

00126   {
00127     m_configurable[ "Module" ] = moduleName;
00128   }

void configGenerator::setConfigurableDefaultName ( const std::string defaultName  )  [inline]

customize the default name for configurable instances

Definition at line 131 of file genconf.cpp.

00132   {
00133     m_configurable[ "DefaultName" ] = defaultName;
00134   }

void configGenerator::setConfigurableAlgorithm ( const std::string cfgAlgorithm  )  [inline]

customize the configurable base class for Algorithm component

Definition at line 137 of file genconf.cpp.

00138   {
00139     m_configurable[ "Algorithm" ] = cfgAlgorithm;
00140   }

void configGenerator::setConfigurableAlgTool ( const std::string cfgAlgTool  )  [inline]

customize the configurable base class for AlgTool component

Definition at line 143 of file genconf.cpp.

00144   {
00145     m_configurable[ "AlgTool" ] = cfgAlgTool;
00146   }

void configGenerator::setConfigurableAuditor ( const std::string cfgAuditor  )  [inline]

customize the configurable base class for AlgTool component

Definition at line 149 of file genconf.cpp.

00150   {
00151     m_configurable[ "Auditor" ] = cfgAuditor;
00152   }

void configGenerator::setConfigurableService ( const std::string cfgService  )  [inline]

customize the configurable base class for Service component

Definition at line 155 of file genconf.cpp.

00156   {
00157     m_configurable[ "Service" ] = cfgService;
00158     m_configurable[ "ApplicationMgr" ] = cfgService;
00159   }

void configGenerator::genComponent ( const std::string libName,
const std::string componentName,
const std::string componentType,
const vector< Property * > &  properties 
) [private]

Definition at line 738 of file genconf.cpp.

00743 {
00744   string cname = componentName;
00745   pythonizeName(cname);
00746 
00747   typedef GaudiUtils::HashMap<std::string, std::string> PropertyDoc_t;
00748   PropertyDoc_t propDoc;
00749 
00750   m_pyBuf << "\n";
00751   m_pyBuf << "class " << cname
00752           << "( " << m_configurable[componentType] << " ) :"
00753           << "\n";
00754   m_pyBuf << "  __slots__ = { \n";
00755   for ( vector<Property*>::const_iterator it = properties.begin() ;
00756         it != properties.end(); ++it ) {
00757     const string pname  = (*it)->name();
00758     string pvalue, ptype;
00759     pythonizeValue( (*it), pvalue, ptype );
00760     m_pyBuf << "    '" << pname << "' : " << pvalue <<", # " << ptype << "\n";
00761 
00762     if ( (*it)->documentation() != "none" ) {
00763       propDoc[pname] = (*it)->documentation();
00764     }
00765 
00766   }
00767   m_pyBuf << "  }\n";
00768   m_pyBuf << "  _propertyDocDct = { \n";
00769   for ( PropertyDoc_t::const_iterator iProp = propDoc.begin();
00770         iProp != propDoc.end();
00771         ++iProp ) {
00772     m_pyBuf << std::setw(5)
00773             << "'"       << iProp->first  << "' : "
00774             << "\"\"\" "  << iProp->second << " \"\"\",\n";
00775   }
00776   m_pyBuf << "  }\n";
00777 
00778   m_pyBuf
00779     << "  def __init__(self, name = " << m_configurable["DefaultName"]
00780                                       << ", **kwargs):\n"
00781     << "      super(" << cname << ", self).__init__(name)\n"
00782     << "      for n,v in kwargs.items():\n"
00783     << "         setattr(self, n, v)\n"
00784     << "  def getDlls( self ):\n"
00785     << "      return '" << libName << "'\n"
00786     << "  def getType( self ):\n"
00787     << "      return '" << componentName  << "'\n"
00788     << "  pass # class " << cname << "\n"
00789     << flush;
00790 
00791   // name of the auto-generated module
00792   const string pyName = ( fs::path(m_outputDirName) /
00793                           fs::path(libName+"Conf.py") ).string();
00794   const string modName = fs::basename( fs::path( pyName ).leaf() );
00795 
00796   // now the db part
00797   m_dbBuf
00798     << py_tab << "cfgDb.add( configurable = '" << cname << "',\n"
00799     << py_tab << "           package = '" << m_pkgName << "',\n"
00800     << py_tab << "           module  = '" << m_pkgName << "." << modName << "',\n"
00801     << py_tab << "           lib     = '" << libName << "' )\n"
00802     << flush;
00803 
00804 }

void configGenerator::genImport ( std::ostream s,
const boost::format &  frmt,
std::string  indent = "" 
) [private]

Definition at line 648 of file genconf.cpp.

00650                                                        {
00651 
00652   std::string::size_type pos = 0, nxtpos = 0;
00653   std::string mod;
00654 
00655   while ( std::string::npos != pos ){
00656     // find end of module name
00657     nxtpos = m_configurable["Module"].find_first_of(',',pos);
00658 
00659     // Prepare import string
00660     mod = m_configurable["Module"].substr(pos,nxtpos-pos);
00661     std::ostringstream import;
00662     import << boost::format(frmt) % mod;
00663 
00664     // append a normal import or a try/except enclosed one depending
00665     // on availability of a fall-back module (next in the list)
00666     if ( std::string::npos == nxtpos ) {
00667       // last possible module
00668       s << indent << import.str() << "\n" << flush;
00669       pos = std::string::npos;
00670     } else {
00671       // we have a fallback for this
00672       s << indent << "try:\n"
00673         << indent << py_tab << import.str() << "\n"
00674         << indent << "except ImportError:\n"
00675         << flush;
00676       pos = nxtpos+1;
00677     }
00678     // increase indentation level for next iteration
00679     indent += py_tab;
00680   }
00681 }

void configGenerator::genHeader ( std::ostream pyOut,
std::ostream dbOut 
) [private]

Definition at line 684 of file genconf.cpp.

00687 {
00688   // python file part
00689   time_t rawtime;
00690   time( &rawtime );
00691   py << "#" << ctime(&rawtime) //<< "\n"
00692      << "\"\"\"Automatically generated. DO NOT EDIT please\"\"\"\n";
00693   if ( m_importGaudiHandles ) {
00694     py << "from GaudiKernel.GaudiHandles import *\n";
00695   }
00696 
00697   genImport(py,boost::format("from %1%.Configurable import *"));
00698 
00699   // db file part
00700   db << "##  -*- python -*-  \n"
00701      << "# db file automatically generated by genconf on: "
00702      << ctime(&rawtime); // << "\n";
00703   db << "## insulates outside world against anything bad that could happen\n"
00704      << "## also prevents global scope pollution\n"
00705      << "def _fillCfgDb():\n";
00706   genImport(db,boost::format("from %1%.ConfigurableDb import CfgDb"),py_tab);
00707 
00708   db << "\n"
00709      << py_tab << "# get a handle on the repository of Configurables\n"
00710      << py_tab << "cfgDb = CfgDb()\n"
00711      << "\n"
00712      << py_tab << "# populate the repository with informations on Configurables \n"
00713      << "\n"
00714      << flush;
00715 }

void configGenerator::genBody ( std::ostream pyOut,
std::ostream dbOut 
) [inline, private]

Definition at line 168 of file genconf.cpp.

00169                                     {
00170     pyOut << m_pyBuf.str() << flush;
00171     dbOut << m_dbBuf.str() << flush;
00172   }

void configGenerator::genTrailer ( std::ostream pyOut,
std::ostream dbOut 
) [private]

Definition at line 717 of file genconf.cpp.

00720 {
00721   // db file part
00722   db << py_tab << "return #_fillCfgDb\n"
00723      << "# fill cfgDb at module import...\n"
00724      << "try:\n"
00725      << py_tab << "_fillCfgDb()\n"
00726      << py_tab << "#house cleaning...\n"
00727      << py_tab << "del _fillCfgDb\n"
00728      << "except Exception,err:\n"
00729      << py_tab << "print \"Py:ConfigurableDb   ERROR Problem with [%s] content!"
00730                << "\" % __name__\n"
00731      << py_tab << "print \"Py:ConfigurableDb   ERROR\",err\n"
00732      << py_tab << "print \"Py:ConfigurableDb   ERROR   ==> culprit is package ["
00733                << m_pkgName << "] !\"\n"
00734      << std::flush;
00735 }

void configGenerator::pythonizeValue ( const Property prop,
string &  pvalue,
string &  ptype 
) [private]

handle the "marshalling" of Properties

Definition at line 817 of file genconf.cpp.

00820 {
00821   const std::string cvalue = p->toString();
00822   const type_info& ti = *p->type_info();
00823   if ( ti == typeid(bool) ) {
00824     pvalue = ( cvalue == "0" || cvalue == "False" || cvalue == "false" )
00825            ? "False"
00826            : "True";
00827     ptype  = "bool";
00828   }
00829   else if ( ti == typeid(char)  || ti == typeid(signed char)
00830             || ti == typeid(unsigned char)  ||
00831             ti == typeid(short) || ti == typeid(unsigned short) ||
00832             ti == typeid(int)   || ti == typeid(unsigned int)   ||
00833             ti == typeid(long)  || ti == typeid(unsigned long) ) {
00834     pvalue = cvalue;
00835     ptype  = "int";
00836   }
00837   else if ( ti == typeid(long long) || ti == typeid(unsigned long long) ) {
00838     pvalue = cvalue + "L";
00839     ptype  = "long";
00840   }
00841   else if ( ti == typeid(float) || ti == typeid(double) ) {
00842     // forces python to handle this as a float: put a dot in there...
00843     pvalue = boost::to_lower_copy(cvalue);
00844     if ( pvalue == "nan" ) {
00845       pvalue = "float('nan')";
00846       std::cout << "WARNING: default value for ["
00847                 << p->name() << "] is NaN !!"
00848                 << std::endl;
00849     } else if ( std::string::npos == pvalue.find(".") &&
00850                 std::string::npos == pvalue.find("e")  ) {
00851       pvalue = cvalue + ".0";
00852     }
00853     ptype  = "float";
00854   }
00855   else if ( ti == typeid(string) ) {
00856 
00857     pvalue = "'"+cvalue+"'";
00858     ptype  = "str";
00859   }
00860   else if ( ti == typeid(GaudiHandleBase) ) {
00861     m_importGaudiHandles = true;
00862     const GaudiHandleProperty& hdl
00863       = dynamic_cast<const GaudiHandleProperty&>(*p);
00864     const GaudiHandleBase&     base = hdl.value();
00865 
00866     pvalue = base.pythonRepr();
00867     ptype  = "GaudiHandle";
00868   }
00869   else if ( ti == typeid(GaudiHandleArrayBase) ) {
00870     m_importGaudiHandles = true;
00871     const GaudiHandleArrayProperty& hdl
00872       = dynamic_cast<const GaudiHandleArrayProperty&>(*p);
00873     const GaudiHandleArrayBase&     base = hdl.value();
00874 
00875     pvalue = base.pythonRepr();
00876     ptype  = "GaudiHandleArray";
00877   }
00878   else {
00879     pvalue = cvalue;
00880     ptype  = "list";
00881   }
00882 }

void configGenerator::pythonizeName ( string &  name  )  [private]

Translates a valid C++ typename into a valid python one.

Definition at line 806 of file genconf.cpp.

00808 {
00809   static string  in("<>&*,: ().");
00810   static string out("__rp__s___");
00811   for ( string::iterator i = name.begin(); i != name.end(); ++i ) {
00812     if ( in.find(*i) != string::npos ) *i = out[in.find(*i)];
00813   }
00814 }


Member Data Documentation

string configGenerator::m_pkgName [private]

name of the package we are processing

Definition at line 81 of file genconf.cpp.

absolute path to the directory where genconf will store auto-generated files (Configurables and ConfigurableDb)

Definition at line 85 of file genconf.cpp.

buffer of auto-generated configurables

Definition at line 88 of file genconf.cpp.

switch to decide if the generated configurables need to import GaudiHandles (ie: if one of the components has a XyzHandle<T>)

Definition at line 92 of file genconf.cpp.

buffer of generated configurables informations for the "Db" file The "Db" file is holding informations about the generated configurables This file is later one used by the PropertyProxy.py to locate Configurables and know their default values, host module,.

..

Definition at line 98 of file genconf.cpp.

Configurable customization.

Contains customization for:

  • Name of the module where configurable base classes are defined
  • Name of the configurable base class for the Algorithm component
  • Name of the configurable base class for the AlgTool component
  • Name of the configurable base class for the Service component

Definition at line 105 of file genconf.cpp.


The documentation for this class was generated from the following file:

Generated at Wed Mar 17 18:16:41 2010 for Gaudi Framework, version v21r8 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004