CMS 3D CMS Logo

IgModule.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
00002 
00003 #include "Iguana/Framework/interface/IgModule.h"
00004 #include "Iguana/Framework/interface/IgModuleDef.h"
00005 #include "Iguana/Framework/interface/IgModuleDescriptor.h"
00006 #include "Iguana/Framework/interface/IgPluginCapabilities.h"
00007 #include "Iguana/Framework/interface/IgPluginManager.h"
00008 #include "Iguana/Framework/interface/IgPluginInfo.h"
00009 #include "Iguana/Framework/interface/IgPluginError.h"
00010 #include "debug.h"
00011 #include "classlib/utils/SharedLibrary.h"
00012 #include "classlib/utils/SharedLibraryError.h"
00013 #include "classlib/utils/ShellEnvironment.h"
00014 #include "classlib/iobase/Filename.h"
00015 #include "classlib/utils/DebugAids.h"
00016 #include "classlib/utils/Log.h"
00017 #include <algorithm>
00018 
00019 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00020 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00021 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00022 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00023 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00024 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00025 
00026 const char IgModule::s_modEntryPoint [] = "IGUANA_MODULE";
00027 const char IgModule::s_capEntryPoint [] = "IGUANA_CAPABILITIES";
00028 const char IgModule::s_tag [] = "module";
00029 
00030 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00031 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00032 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00033 
00034 IgModule *
00035 IgModule::builtin (void)
00036 {
00037     static IgModule *myself = new IgModule (IgPluginManager::get (),
00038                                             "" /* magic library name */,
00039                                             "0", "good");
00040     return myself;
00041 }
00042 
00043 IgModule::IgModule (IgPluginManager *manager,
00044                     const lat::Filename &libraryName,
00045                     const std::string &time,
00046                     const std::string &flag)
00047     : m_manager (manager),
00048       m_libraryName (libraryName),
00049       m_library (0),
00050       m_cache (0),
00051       m_time (strtoul (time.c_str (), 0, 10)),
00052       m_bad (flag != "good"),
00053       m_attached (libraryName.empty ()),
00054       m_definition (0)
00055 {
00056     ASSERT (flag == "good" || flag == "bad");
00057     ASSERT (! time.empty ());
00058     LOG (0, trace, LFplugin_manager,
00059          "constructing module for library `" << m_libraryName << "'\n");
00060     makeCache ();
00061 }
00062 
00063 IgModule::~IgModule (void)
00064 {
00065     LOG (0, trace, LFplugin_manager,
00066          "destroying module for library `" << m_libraryName << "'\n");
00067 
00068     unload ();
00069     ASSERT (! m_library);
00070 
00071     while (! m_infos.empty ())
00072         delete *m_infos.begin ();
00073 
00074     delete m_cache;
00075 }
00076 
00078 IgPluginManager *
00079 IgModule::manager (void) const
00080 { return m_manager; }
00081 
00082 const lat::Filename &
00083 IgModule::libraryName (void) const
00084 { return m_libraryName; }
00085 
00087 bool
00088 IgModule::bad (void) const
00089 { return m_bad; }
00090 
00093 void
00094 IgModule::bad (bool value)
00095 { if ((m_bad = value)) clearCache (); }
00096 
00097 lat::SharedLibrary *
00098 IgModule::library (void) const
00099 {
00100     // FIXME: return SharedLibrary::self if m_libraryName is empty?
00101     if (m_libraryName.empty ())
00102         return 0;
00103 
00104     if (! m_library)
00105     {
00106         LOG (0, trace, LFplugin_manager,
00107              "loading shared library `" << m_libraryName << "'\n");
00108 
00109         try
00110         {
00111             m_manager->feedback (IgPluginManager::StatusLoading, m_libraryName);
00112             // FIXME: remove cast when filename is in the same namespace/gcc bug fixed
00113             m_library = lat::SharedLibrary::load ((const std::string &) m_libraryName);
00114         }
00115         catch (lat::Error &e)
00116         {
00117             m_manager->feedback (IgPluginManager::ErrorLoadFailure, m_libraryName, &e);
00118             throw IgPluginError (e.clone ());
00119         }
00120     }
00121 
00122     ASSERT (m_library);
00123     return m_library;
00124 }
00125 
00126 bool
00127 IgModule::loaded (void) const
00128 { return m_libraryName.empty () || m_library;}
00129 
00130 void
00131 IgModule::load (void)
00132 {
00133     if (m_libraryName.empty ())
00134         return;
00135 
00136     LOG (0, trace, LFplugin_manager, "loading `" << m_libraryName << "'\n");
00137 
00138     VERIFY (library ());
00139     VERIFY (checkEntryPoints ());
00140 }
00141 
00142 void
00143 IgModule::unload (void)
00144 {
00145     if (m_libraryName.empty ())
00146         return;
00147 
00148     detach ();
00149 
00150     // Do not unload libraries on platforms with broken handling of
00151     // global destructors in shared libraries (e.g. KCC 4.0f on
00152     // Linux).  The problem is that global destructors are not
00153     // deregistered on library unload, causing instability with
00154     // subsequent dynamic loading operations, program exit etc.
00155     if (m_library)
00156     {
00157         LOG (0, trace, LFplugin_manager, "unloading `" << m_libraryName << "'\n");
00158 
00159         if (lat::ShellEnvironment ().has ("IGUANA_RELEASE_MODULES"))
00160         {
00161             m_manager->feedback (IgPluginManager::StatusUnloading, m_libraryName);
00162             m_library->release ();
00163         }
00164         else
00165             m_library->abandon ();
00166 
00167         m_library = 0;
00168     }
00169 }
00170 
00172 void
00173 IgModule::makeCache (void)
00174 {
00175     char time [40]; // 128+ bits
00176     const char *bad = m_bad ? "bad" : "good";
00177     sprintf (time, "%lu", (unsigned long) m_time);
00178 
00179     // Ask each module to dump itself under myself.
00180     m_cache = new IgModuleDescriptor (0, s_tag,
00181                                       m_libraryName.nondirectory ().name (),
00182                                       time, bad);
00183 }
00184 
00185 void
00186 IgModule::clearCache (void)
00187 { delete m_cache; makeCache (); }
00188 
00189 IgModuleDescriptor *
00190 IgModule::cacheRoot (void) const
00191 { return m_cache; }
00192 
00194 IgModule::InfoIterator
00195 IgModule::beginInfos (void) const
00196 { return m_infos.begin (); }
00197 
00198 IgModule::InfoIterator
00199 IgModule::endInfos (void) const
00200 { return m_infos.end (); }
00201 
00202 void
00203 IgModule::addInfo (IgPluginInfo *info, bool needCache)
00204 {
00205     if (needCache)
00206         // This info isn't cached yet -- add it.
00207         info->cache (cacheRoot ());
00208 
00209     m_infos.push_back (info);
00210     m_manager->addInfo (info);
00211 }
00212 
00213 void
00214 IgModule::detachInfo (IgPluginInfo *info)
00215 {
00216     // Remove from the list but keep the details in the cache.  Also
00217     // notify the plug-in database so that this gets removed from the
00218     // factories.
00219     InfoList::iterator pos = std::find (m_infos.begin (), m_infos.end (), info);
00220     ASSERT (pos != m_infos.end ());
00221     m_infos.erase (pos);
00222     m_manager->removeInfo (info);
00223 }
00224 
00226 void
00227 IgModule::restore (IgModuleDescriptor *from)
00228 {
00229     // FIXME: If factory is active, this will result in creation of a new
00230     // info, which we'll want to add to our cache.  Make sure we don't
00231     // make duplicates...
00232     from->dup (m_cache);
00233     m_manager->restore (this, from);
00234 }
00235 
00237 void
00238 IgModule::cache (IgModuleDescriptor *to) const
00239 {
00240     // Internal cache is already in sync (we update it every time a
00241     // new info item is created), so let base class do all the work.
00242     m_cache->dup (to);
00243 }
00244 
00246 bool
00247 IgModule::checkEntryPoints (void) const
00248 {
00249     // Check for module entry points.  It's legal to have just one or both
00250     // of the normal and capability entry points, but not to have neither.
00251     // First check for the capability entry point, then for the standard one.
00252     // If either succeeds, we declare success.  If both fail, we record the
00253     // error from the standard entry point for more meaningful errors.
00254     m_manager->feedback (IgPluginManager::StatusEntries, m_libraryName);
00255 
00256     try
00257     {
00258         if (library ()->function (s_capEntryPoint))
00259             return true;
00260     }
00261     catch (lat::Error &)
00262     {
00263     }
00264 
00265     try
00266     {
00267         return library ()->function (s_modEntryPoint);
00268     }
00269     catch (lat::Error &e)
00270     {
00271         m_manager->feedback (IgPluginManager::ErrorEntryFailure, m_libraryName, &e);
00272         throw IgPluginError (e.clone ());
00273     }
00274 }
00275 
00276 IgModuleEntry
00277 IgModule::moduleEntryPoint (void)
00278 {
00279     lat::SharedLibrary::Function entry = 0;
00280 
00281     if (! libraryName ().empty ()) 
00282     {
00283         // Swallow errors, just return null if it fails
00284         try { entry = library ()->function (s_modEntryPoint); }
00285         catch (lat::Error &) {}
00286 
00287         LOG (0, trace, LFplugin_manager, "module entry point ("
00288              << s_modEntryPoint << ") = " << (void *) entry << '\n');
00289     }
00290 
00291     return reinterpret_cast<IgModuleEntry> (entry);
00292 }
00293 
00294 IgModuleCapEntry
00295 IgModule::capabilityEntryPoint (void)
00296 {
00297     lat::SharedLibrary::Function entry = 0;
00298 
00299     if (! libraryName ().empty ()) 
00300     {
00301         // Swallow errors, just return null if it fails
00302         try { entry = library ()->function (s_capEntryPoint); }
00303         catch (lat::Error &) {}
00304 
00305         LOG (0, trace, LFplugin_manager, "capability entry point ("
00306              << s_capEntryPoint << ") = " << (void *) entry << '\n');
00307     }
00308 
00309     return reinterpret_cast<IgModuleCapEntry> (entry);
00310 }
00311 
00312 void
00313 IgModule::attach (void)
00314 {
00315     if (! m_attached && ! libraryName ().empty ())
00316     {
00317         ASSERT (! m_definition);
00318 
00319         LOG (0, trace, LFplugin_manager,
00320              "attaching module " << libraryName () << '\n' << lat::indent);
00321 
00322         // Capability-only modules don't have a normal entry; we
00323         // don't need a definition for them either.
00324         if (IgModuleEntry entry = moduleEntryPoint ())
00325         {
00326             m_definition = (*entry) ();
00327             ASSERT (m_definition);
00328 
00329             m_manager->feedback (IgPluginManager::StatusAttaching, m_libraryName);
00330             m_definition->bind (this);
00331             m_definition->attach ();
00332         }
00333 
00334         m_attached = true;
00335         LOG (0, trace, LFplugin_manager, lat::undent);
00336     }
00337 }
00338 
00339 void
00340 IgModule::detach (void)
00341 {
00342     if (loaded () && m_attached && ! libraryName ().empty ())
00343     {
00344         LOG (0, trace, LFplugin_manager,
00345              "detaching module " << libraryName () << '\n' << lat::indent);
00346 
00347         m_manager->feedback (IgPluginManager::StatusDetaching, m_libraryName);
00348         for (InfoIterator i = m_infos.begin (); i != m_infos.end (); ++i)
00349             (*i)->detach ();
00350 
00351         // Capability-only modules don't have a definition.
00352         if (m_definition)
00353         {
00354             m_definition->detach ();
00355             m_definition->release ();
00356             m_definition = 0;
00357         }
00358         LOG (0, trace, LFplugin_manager, lat::undent);
00359     }
00360 }
00361 
00362 void
00363 IgModule::query (void)
00364 {
00365     if (! libraryName ().empty ()) 
00366     {
00367         ASSERT (! m_definition);
00368 
00369         LOG (0, trace, LFplugin_manager,
00370              "querying module " << libraryName () << '\n' << lat::indent);
00371 
00372         // Blast away existing infos and the cache in order to rebuild
00373         // a clean state from the newly created infos.
00374         clearCache ();
00375         while (! m_infos.empty ())
00376             delete *m_infos.begin ();
00377 
00378         // Now invoke the standard entry point.
00379         if (IgModuleEntry entry = moduleEntryPoint ())
00380         {
00381             m_definition = (*entry) ();
00382             ASSERT (m_definition);
00383 
00384             m_manager->feedback (IgPluginManager::StatusQuerying, m_libraryName);
00385             m_definition->bind (this);
00386             m_definition->query ();
00387             m_definition->release ();
00388             m_definition = 0;
00389         }
00390 
00391         // Repeat with capabilities entry, processing it manually as
00392         // if the code was in the entry point in the module library.
00393         // This allows libraries to define "caability" modules with
00394         // pure string labels without linking against us -- but not
00395         // anything that needs a factory.  These would normally be
00396         // used for side-effects or libraries that self-register to
00397         // some other factory.  NB: The code below creates a module
00398         // definition even if the module has a standard entry point
00399         // and thus an existing definition.  Since this is a query,
00400         // different defs don't matter, and attach will never use
00401         // the def anyway.
00402         if (IgModuleCapEntry capEntry = capabilityEntryPoint ())
00403         {
00404             IgModuleDef *def = new IgModuleDef;
00405             const char  **names = 0;
00406             int         n = -1;
00407 
00408             (*capEntry) (names, n);
00409 
00410             def->bind (this);
00411             for (int i = 0; names && names [i] && (n < 0 || i < n); ++i)
00412                 IgPluginCapabilities::get ()->declare (def, names [i]);
00413             def->release ();
00414             delete def;
00415         }
00416 
00417         LOG (0, trace, LFplugin_manager, lat::undent);
00418     }
00419 }
00420 
00421 bool
00422 IgModule::attached (void)
00423 { return m_attached; }

Generated on Tue Jun 9 17:38:28 2009 for CMSSW by  doxygen 1.5.4