CMS 3D CMS Logo

IgModuleCache Class Reference

Automatically cached directory of module registrations. More...

#include <Iguana/Framework/interface/IgModuleCache.h>

List of all members.

Public Types

typedef ModuleList::const_iterator Iterator
 Iterator over IgModule objects in this cache.

Public Member Functions

Iterator begin (void) const
 Return an iterator to the first Module in the cache.
lat::Filename directory (void) const
 Return the module cache directory name.
Iterator end (void) const
 Return an iterator one past the last Module in the cache.
 IgModuleCache (IgPluginManager *manager, const lat::Filename &directory)
 Initialise a module cache in directory.
IgPluginManagermanager (void) const
void refresh (void)
 Refresh the module cache.
 ~IgModuleCache (void)
 Destroy the module cache.

Protected Member Functions

void load (void)
 Load the module cache file ".cache".
void notify (void)
 Update m_modules from the current state of the cache (m_cache).
void rebuild (void)
 Rebuild the cache comparing it to the actual directory contents.
void update (void)
 Update the ".cache" file on the disk if it is writable.

Private Types

enum  CacheStatus { CACHE_MISSING = 1, CACHE_OLD = 2, CACHE_VALID = 3 }
 Different cache states. More...
typedef ModuleList::iterator ModuleIterator
 Iterator over module registations.
typedef std::list< IgModule * > ModuleList
 Module registrations (each of which maintains its list of modules).

Private Member Functions

bool parse (const lat::Filename &filename, IgModuleDescriptor *root=0)
 Parse a module cache file (".cache" or one of the "*.reg" files).
void reconstruct (IgModuleDescriptor *info)
 Validate and reconstruct descriptor proxies from info.
CacheStatus scanModules (ModuleList &cache)
 Actually scan the module directory, compare it with the current m_cache, and build a new cache that reflects the changes.
void write (std::ostream &s, IgModuleDescriptor *doc, int level=0)
 Dump the module descriptor doc and all it's children into the stream s.

Static Private Member Functions

static IgModuleDescriptormakeBad (const std::string &file, const std::string &time)
 Construct a module descriptor for a bad file with timestamp time.

Private Attributes

ModuleList m_cache
lat::Filename m_directory
IgPluginManagerm_manager
ModuleList m_modules
ParseContext m_parse
CacheContext m_state

Static Private Attributes

static const char s_cacheFile [] = ".iglets"
static const char s_cacheTag [] = "cache"
static const char s_fileTag []
static const char s_moduleTag []

Friends

struct CacheContext
class FileByName
struct ParseContext

Classes

struct  CacheContext
 Flags that describe the current cache status. More...
class  FileByName
struct  ParseContext
 Structure used as temporary storage and result by parse() and reconstruct(). More...


Detailed Description

Automatically cached directory of module registrations.

The IgPluginManager automatically instantiates a IgModuleCache for every module registration directory. The purpose of this class is to maintain an automatically updated cache about all the modules in the directory, including all the plug-ins registered in those modules. The cache object automatically refreshes the cache with respect to the on-disk registrations when it is created. Clients can also force an update by calling refresh(); note however that calling it on already-loaded modules whose library has been updated while the program is running is not a good idea.

The cache maintains information about all the registrations in the directory, including the time-stamp of each file. The cache is updated if the file time stamp is different from what it was when the data was cached. The cache also records time-stamps for bad files: files the cache does not understand or files that describe modules that fail to load for some reason. Such files are ignored until the on-disk file time stamp changes.

The IgModuleCache updates the on-disk cache automatically if it can, i.e. if it has write permissions on the directory. It never modifies the original registration files. If the cache file cannot be written, the errors are silently ignored and class proceeds with just the information in memory; the canonical data it maintains is the part that is in memory, the data on disk is merely an optimisation that avoids having to query all the modules all the time.

Note that if the cache cannot be written but needs to be updated, there is a performance penalty because the client programs will continuously refresh their caches. Thus when new modules are installed, it is important to refresh the cache before the directories are frozen.

The cache data is maintained in string form as IgModuleDescriptor objects. The IgModuleCache automatically creates IgModule objects as needed. When restoring a cache the information is passed as IgModuleDescriptor to the IgModule objects, which passes it to the IgPluginManager, which passes it to the IgPluginFactory categories as necessary. When writing the the IgModule objects are queried for their caches of the IgPluginInfo items registered with them, to produce IgModuleDescriptors for output.

Definition at line 68 of file IgModuleCache.h.


Member Typedef Documentation

typedef ModuleList::const_iterator IgModuleCache::Iterator

Iterator over IgModule objects in this cache.

Definition at line 77 of file IgModuleCache.h.

typedef ModuleList::iterator IgModuleCache::ModuleIterator [private]

Iterator over module registations.

Definition at line 73 of file IgModuleCache.h.

typedef std::list<IgModule *> IgModuleCache::ModuleList [private]

Module registrations (each of which maintains its list of modules).

Definition at line 71 of file IgModuleCache.h.


Member Enumeration Documentation

enum IgModuleCache::CacheStatus [private]

Different cache states.

The progression goes from first to last.

Enumerator:
CACHE_MISSING 
CACHE_OLD 
CACHE_VALID 

Definition at line 109 of file IgModuleCache.h.

00109                      {
00110         CACHE_MISSING   = 1,            //< No cache
00111         CACHE_OLD       = 2,            //< Cache exists but is outdated
00112         CACHE_VALID     = 3             //< Cache exists and is up-to-date
00113     };


Constructor & Destructor Documentation

IgModuleCache::IgModuleCache ( IgPluginManager manager,
const lat::Filename directory 
)

Initialise a module cache in directory.

Initialises the cache to clear state and then invokes refresh() to rebuild; this causes for instance Module objects to be created.

Definition at line 103 of file IgModuleCache.cc.

References IgModuleCache::CacheContext::added, ASSERT, CACHE_MISSING, IgModuleCache::CacheContext::changed, lat::Filename::empty(), m_directory, m_parse, m_state, IgModuleCache::ParseContext::module, refresh(), IgModuleCache::CacheContext::removed, IgModuleCache::CacheContext::skipped, and IgModuleCache::CacheContext::status.

00104     : m_manager (manager),
00105       m_directory (directory.asDirectory ())
00106 {
00107     ASSERT (! m_directory.empty ());
00108 
00109     m_state.status = CACHE_MISSING;
00110     m_state.added  = m_state.removed
00111                    = m_state.changed
00112                    = m_state.skipped
00113                    = false;
00114 
00115     m_parse.module = 0;
00116     refresh ();
00117 }

IgModuleCache::~IgModuleCache ( void   ) 

Destroy the module cache.

Destroys all modules owned by the cache.

Definition at line 120 of file IgModuleCache.cc.

References ASSERT, lat::Filename::empty(), lat::indent(), LFplugin_manager, LOG, m, m_cache, m_directory, GsfMatrixTools::trace(), and lat::undent().

00121 {
00122     LOG (0, trace, LFplugin_manager,
00123          "destroying module cache for `" << m_directory << "'\n" << lat::indent);
00124     ASSERT (! m_directory.empty ());
00125     for (ModuleIterator m = m_cache.begin (); m != m_cache.end (); ++m)
00126         delete *m;
00127 
00128     LOG (0, trace, LFplugin_manager, lat::undent);
00129 }


Member Function Documentation

IgModuleCache::Iterator IgModuleCache::begin ( void   )  const

Return an iterator to the first Module in the cache.

Definition at line 138 of file IgModuleCache.cc.

References m_modules.

00139 { return m_modules.begin (); }

lat::Filename IgModuleCache::directory ( void   )  const

Return the module cache directory name.

Definition at line 133 of file IgModuleCache.cc.

References m_directory.

Referenced by IgDirectoryByName::operator()().

00134 { return m_directory; }

IgModuleCache::Iterator IgModuleCache::end ( void   )  const

Return an iterator one past the last Module in the cache.

Definition at line 143 of file IgModuleCache.cc.

References m_modules.

Referenced by scanModules().

00144 { return m_modules.end (); }

void IgModuleCache::load ( void   )  [protected]

Load the module cache file ".cache".

Attempts to load and rebuild the cache from the file. The cache is first set to CACHE_MISSING status and all m_state flags are cleared. If the file exists and can be parsed and reconstructed successfully, m_cache is set to the IgModule list and the cache status is set to CACHE_OLD. Otherwise m_cache is left untouched.

Definition at line 303 of file IgModuleCache.cc.

References IgModuleCache::CacheContext::added, CACHE_MISSING, CACHE_OLD, IgModuleCache::CacheContext::changed, lat::indent(), LFplugin_manager, LOG, m, m_cache, m_directory, m_parse, m_state, parse(), IgModuleCache::CacheContext::removed, IgModuleCache::ParseContext::result, s_cacheFile, IgModuleCache::CacheContext::skipped, IgModuleCache::CacheContext::status, GsfMatrixTools::trace(), and lat::undent().

Referenced by refresh().

00304 {
00305     LOG (0, trace, LFplugin_manager, "loading cache "
00306          << lat::Filename (m_directory, s_cacheFile) << '\n' << lat::indent);
00307 
00308     m_state.status = CACHE_MISSING;
00309     m_state.added  = m_state.removed
00310                    = m_state.changed
00311                    = m_state.skipped
00312                    = false;
00313 
00314     if (parse (s_cacheFile))
00315     {
00316         m_state.status = CACHE_OLD;
00317 
00318         // Clear the cache before adding to it (in case we already
00319         // have something, i.e. refresh() was already invoked).
00320         for (ModuleIterator m = m_cache.begin (); m != m_cache.end (); ++m)
00321             delete *m;
00322 
00323         m_cache.clear ();
00324         m_cache.splice (m_cache.end (), m_parse.result);
00325     }
00326 
00327     LOG (0, trace, LFplugin_manager, lat::undent << "done\n");
00328 }

IgModuleDescriptor * IgModuleCache::makeBad ( const std::string &  file,
const std::string &  time 
) [static, private]

Construct a module descriptor for a bad file with timestamp time.

Definition at line 332 of file IgModuleCache.cc.

References IgPluginManager::ErrorBadCacheFile, IgPluginManager::feedback(), IgPluginManager::get(), s_cacheTag, and IgModule::tag().

00333 {
00334     IgPluginManager::get ()->feedback (IgPluginManager::ErrorBadCacheFile, file);
00335     IgModuleDescriptor *top = new IgModuleDescriptor (0, s_cacheTag);
00336     new IgModuleDescriptor (top, IgModule::tag (), file, time, "bad");
00337     return top;
00338 }

IgPluginManager* IgModuleCache::manager ( void   )  const

void IgModuleCache::notify ( void   )  [protected]

Update m_modules from the current state of the cache (m_cache).

Definition at line 509 of file IgModuleCache.cc.

References lat::indent(), LFplugin_manager, LOG, m, m_cache, m_modules, GsfMatrixTools::trace(), and lat::undent().

Referenced by refresh().

00510 {
00511     LOG (0, trace, LFplugin_manager, "collecting modules\n" << lat::indent);
00512     for (ModuleIterator m = m_cache.begin (); m != m_cache.end (); ++m)
00513         if (! (*m)->bad ()) m_modules.push_back (*m);
00514     LOG (0, trace, LFplugin_manager, lat::undent);
00515 }

bool IgModuleCache::parse ( const lat::Filename file,
IgModuleDescriptor root = 0 
) [private]

Parse a module cache file (".cache" or one of the "*.reg" files).

This both reads the file and reconstructs its contents as children of root; the descriptor tree is destroyed before the method returns. If reading in ".cache", root should be null, if reading in a single registration it should be contain the initial cache structure, otherwise reconstruct will fail. The reconstructed cache will be put into m_parse.result. Returns true if the cache was successfully read and reconstructed, false otherwise.

Definition at line 167 of file IgModuleCache.cc.

References IgModuleDescriptor::addToken(), ASSERT, IgModuleDescriptor::child(), IgModuleDescriptor::children(), decode(), doc, e, error, IgPluginManager::ErrorBadCacheFile, HLT_VtxMuL3::errors, lat::Error::explain(), f, IgPluginManager::feedback(), EgammaValidation_cff::filename, level, LFplugin_manager, LOG, m, m_directory, m_manager, m_parse, IgModuleCache::ParseContext::module, offset, IgPluginManager::Other, reconstruct(), IgModuleCache::ParseContext::result, IgModuleDescriptor::tokens(), and GsfMatrixTools::trace().

Referenced by load().

00168 {
00169     // FIXME: Use platform independent facilities for all file stuff (actually, registry)
00170     struct stat         statbuf;
00171     lat::Filename       filename (m_directory, file);
00172     bool                errors = false;
00173     IgModuleDescriptor  *regdata = root;
00174 
00175     if (::stat (filename, &statbuf) == -1)
00176     {
00177         delete regdata;
00178         return true;
00179     }
00180 
00181     LOG (0, trace, LFplugin_manager, "parsing file: " << file << "\n");
00182 
00183     ASSERT (m_parse.result.empty ());
00184     ASSERT (! m_parse.module);
00185 
00186     // Parse the registry file
00187     try {
00188         // FIXME: use an object so we don't need to fclose() it.
00189         FILE *f = fopen (filename, "r");
00190         if (! f)
00191             throw IgPluginError (new IgPluginParserError ("can't read the file"));
00192 
00193         typedef std::vector<IgModuleDescriptor *> ContextStack;
00194         ContextStack    stack;
00195         int             offset = 0;
00196         int             ch;
00197 
00198         // Bias the stack in case we were give a root preamble.  In
00199         // that case we simply descend as far as we can into the first
00200         // children of the preamble, and insert parse results there.
00201         // `regdata' is assinged
00202         while (root)
00203         {
00204             ++offset;
00205             stack.push_back (root);
00206             root = root->children () ? root->child (0) : 0;
00207         }
00208 
00209         // Process the file
00210         do {
00211             std::string token;
00212             int         level = offset;
00213 
00214             while ((ch = fgetc (f)) != EOF && ch == ' ')
00215                 ++level;
00216 
00217             if (ch == EOF)
00218                 break;
00219 
00220             if (level == 0 && regdata)
00221             {
00222                 fclose (f);
00223                 throw IgPluginError (new IgPluginParserError ("duplicate top level line"));
00224             }
00225 
00226             stack.resize (level+1);
00227             IgModuleDescriptor *doc
00228                 = new IgModuleDescriptor (level ? stack [level-1] : 0);
00229             stack [level] = doc;
00230             if (level == 0)
00231                 regdata = doc;
00232 
00233             for ( ; ch != EOF; ch = fgetc (f))
00234                 if (ch == '\n')
00235                 {
00236                     if (! token.empty ())
00237                         doc->addToken (decode (token));
00238 
00239                     if (doc->tokens () == 0)
00240                     {
00241                         fclose (f);
00242                         throw IgPluginError (new IgPluginParserError ("empty line"));
00243                     }
00244 
00245                     break;
00246                 }
00247                 else if (ch == ' ')
00248                 {
00249                     if (! token.empty ())
00250                         doc->addToken (decode (token));
00251                     token = "";
00252                 }
00253                 else
00254                     token += ch;
00255         } while (ch != EOF);
00256 
00257         fclose (f);
00258         reconstruct (regdata);
00259 
00260         ASSERT (! m_parse.module);
00261     } catch (lat::Error &e) {
00262         m_manager->feedback (IgPluginManager::ErrorBadCacheFile, file, &e);
00263 
00264         // FIXME: Notify owner
00265         LOG (0, error, LFplugin_manager,
00266              file << ": error, file ignored (" << e.explain() << ")\n");
00267 
00268         errors = true;
00269     } catch (...) {
00270         m_manager->feedback (IgPluginManager::Other, file);
00271 
00272         // FIXME: Notify owner
00273         LOG (0, error, LFplugin_manager,
00274              file << ": unknown error, file ignored\n");
00275 
00276         errors = true;
00277     }
00278 
00279     delete regdata;
00280 
00281     if (errors)
00282     {
00283         delete m_parse.module;
00284         m_parse.module = 0;
00285 
00286         for (ModuleIterator m = m_parse.result.begin ();
00287              m != m_parse.result.end (); ++m)
00288             delete *m;
00289 
00290         m_parse.result.clear ();
00291     }
00292 
00293     return !errors;
00294 }

void IgModuleCache::rebuild ( void   )  [protected]

Rebuild the cache comparing it to the actual directory contents.

Assumes any existing cache is already loaded. Scans the directory contents and compares with the cache, updating it to the new state of things. Updates m_state to reflect what happened.

Definition at line 483 of file IgModuleCache.cc.

References IgModuleCache::CacheContext::added, IgModuleCache::CacheContext::changed, lat::indent(), LFplugin_manager, LOG, m, m_cache, m_directory, m_state, IgModuleCache::CacheContext::removed, scanModules(), IgModuleCache::CacheContext::skipped, IgModuleCache::CacheContext::status, GsfMatrixTools::trace(), and lat::undent().

Referenced by refresh().

00484 {
00485     LOG (0, trace, LFplugin_manager,
00486          "rebuilding cache in `" << m_directory << "'\n" << lat::indent);
00487 
00488     // Build a new cache and stealing bits from the old one as the new
00489     // one is rebuilt.  Then replace the cache with the new one and
00490     // delete whatever was left over from the old cache (creating the
00491     // new one may steal bits of the old).
00492     ModuleList cache;
00493     m_state.status = scanModules (cache);
00494     m_cache.swap (cache);
00495     for (ModuleIterator m = cache.begin (); m != cache.end (); ++m)
00496         delete *m;
00497 
00498     LOG (0, trace, LFplugin_manager,
00499          lat::undent << "done (" << (int) m_state.status
00500          << ", added = " << m_state.added
00501          << ", removed = " << m_state.removed
00502          << ", changed = " << m_state.changed
00503          << ", skipped = " << m_state.skipped
00504          << ")\n");
00505 }

void IgModuleCache::reconstruct ( IgModuleDescriptor info  )  [private]

Validate and reconstruct descriptor proxies from info.

Definition at line 589 of file IgModuleCache.cc.

References ASSERT, IgModuleDescriptor::child(), IgModuleDescriptor::children(), i, LFplugin_manager, LOG, m_directory, m_manager, m_parse, IgModuleCache::ParseContext::module, IgModuleDescriptor::parent(), IgModule::restore(), IgModuleCache::ParseContext::result, s_cacheTag, IgModule::tag(), IgModuleDescriptor::token(), IgModuleDescriptor::tokens(), and GsfMatrixTools::trace().

Referenced by parse(), and scanModules().

00590 {
00591     // Protect against random junk, e.g. empty files
00592     if (! info || ! info->tokens ())
00593         throw IgPluginError (new IgPluginParserError ("empty descriptor"));
00594 
00595     // Make sure the root is either a cache...
00596     if (info->token (0) == s_cacheTag)
00597     {
00598         if (info->tokens () != 1)
00599             throw IgPluginError (new IgPluginParserError
00600                                  ("`cache' does not take arguments"));
00601         else if (info->parent ())
00602             throw IgPluginError (new IgPluginParserError
00603                                  ("`cache' must be at the root"));
00604 
00605         for (unsigned i = 0; i < info->children (); ++i)
00606             reconstruct (info->child (i));
00607 
00608         ASSERT (! m_parse.module);
00609     }
00610     // ... or a module itself
00611     else if (info->token (0) == IgModule::tag ())
00612     {
00613         if (info->tokens () != 4)
00614             throw IgPluginError (new IgPluginParserError
00615                                  ("`module' must have three arguments"));
00616         if (! info->parent () || info->parent ()->token (0) != s_cacheTag)
00617             throw IgPluginError (new IgPluginParserError
00618                                  ("`module' must be under `cache'"));
00619         if (info->token (3) != "good" && info->token (3) != "bad")
00620             throw IgPluginError (new IgPluginParserError
00621                                  ("`module' last argument must be"
00622                                   " 'good' or 'bad'"));
00623 
00624         ASSERT (! m_parse.module);
00625         m_parse.module = new IgModule (m_manager,
00626                                        lat::Filename (m_directory, info->token (1)),
00627                                        info->token (2),
00628                                        info->token (3));
00629 
00630         for (unsigned i = 0; i < info->children (); ++i)
00631             reconstruct (info->child (i));
00632 
00633         ASSERT (m_parse.module);
00634         m_parse.result.push_back (m_parse.module);
00635         m_parse.module = 0;
00636     }
00637     // ... or junk we don't understand
00638     else
00639     {
00640         if (! m_parse.module)
00641             throw IgPluginError (new IgPluginParserError
00642                                  (info->token (0) + " unexpected"));
00643 
00644         if (info->tokens () >= 2)
00645             LOG (0, trace, LFplugin_manager, "processing "
00646                  << info->token(0) << ' ' << info->token(1) << '\n');
00647 
00648         m_parse.module->restore (info);
00649     }
00650 }

void IgModuleCache::refresh ( void   ) 

Refresh the module cache.

This causes the old ".cache" file to be loaded and to be compared with the current state of the directory. If there are any differences, a new cache will be written out.

Definition at line 150 of file IgModuleCache.cc.

References load(), notify(), rebuild(), and update().

Referenced by IgModuleCache().

00151 {
00152     load ();
00153     rebuild ();
00154     notify ();
00155     update ();
00156 }

IgModuleCache::CacheStatus IgModuleCache::scanModules ( ModuleList cache  )  [private]

Actually scan the module directory, compare it with the current m_cache, and build a new cache that reflects the changes.

Returns a cache status code to reflect the new state.

Definition at line 344 of file IgModuleCache.cc.

References IgModuleCache::CacheContext::added, ASSERT, CACHE_MISSING, CACHE_OLD, CACHE_VALID, IgModuleCache::CacheContext::changed, e, end(), error, IgPluginManager::ErrorBadModule, lat::Error::explain(), IgPluginManager::feedback(), file, FileByName, EgammaValidation_cff::filename, lat::indent(), LFplugin_manager, LOG, m, m_cache, m_directory, m_manager, m_parse, m_state, edm::match(), IgModuleCache::ParseContext::module, reconstruct(), IgModuleCache::CacheContext::removed, HLT_VtxMuL3::result, IgModuleCache::ParseContext::result, s_cacheFile, s_cacheTag, IgModuleCache::CacheContext::skipped, StDecayID::status, IgModule::tag(), GsfMatrixTools::trace(), and lat::undent().

Referenced by rebuild().

00345 {
00346     LOG (0, trace, LFplugin_manager,
00347          "scanning `" << m_directory << "'\n" << lat::indent);
00348 
00349     CacheStatus         result = CACHE_MISSING;
00350     lat::DirIterator    file (m_directory);
00351     lat::DirIterator    end;
00352 
00353     ASSERT (cache.empty ());
00354     for (; file != end; ++file)
00355     {
00356         // Ignore the cache file.
00357         if (*file == s_cacheFile)
00358             continue;
00359 
00360         // Check, read and validate the module definition file.
00361         // FIXME: Use platform-independent facilities!
00362         struct stat     statbuf;
00363         lat::Filename   filename (m_directory, *file);
00364         if (filename.extension () != "iglet")
00365             continue;
00366 
00367         // Ignore files we cannot stat
00368         int status = stat (filename, &statbuf);
00369         if (status == -1)
00370         {
00371             LOG (0, error, LFplugin_manager,
00372                  "stat() failed with error " << errno << ", ignoring `"
00373                  << *file << "'\n");
00374             m_state.skipped = true;
00375             continue;
00376         }
00377 
00378         // Check whether the module reg fragment has changed by
00379         // comparing the file and cached timestamps.
00380         ModuleIterator match
00381             = std::find_if (m_cache.begin(), m_cache.end(),
00382                             FileByName (*file));
00383 
00384         if (match == m_cache.end ())
00385         {
00386             LOG (0, trace, LFplugin_manager,
00387                  "==> new module definition `" << *file << "'\n");
00388             m_state.added = true;
00389         }
00390         else if ((*match)->time () != (unsigned long) statbuf.st_mtime)
00391         {
00392             LOG (0, trace, LFplugin_manager,
00393                  "==> modified module definition `" << *file << "' (file is "
00394                  << statbuf.st_mtime << ", cached was " << (*match)->time ()
00395                  << ")\n");
00396             m_state.changed = true;
00397         }
00398         else
00399         {
00400             // Copy the old cache to the new cache.  This relies on
00401             // the knowledge that the old cache will be thrown away
00402             // and so it is ok to steal the entry from the old one to
00403             // the new one.
00404             LOG (0, trace, LFplugin_manager,
00405                  "==> unchanged definition `" << *file << "'\n");
00406             cache.splice (cache.end (), m_cache, match);
00407             continue;
00408         }
00409 
00410         // Construct a fake registry document root for this file
00411         std::string time = lat::StringFormat ("%1").arg (statbuf.st_mtime);
00412         IgModuleDescriptor *top = new IgModuleDescriptor (0, s_cacheTag);
00413         new IgModuleDescriptor (top, IgModule::tag (), *file, time, "good");
00414         ASSERT (m_parse.result.empty ());
00415         ASSERT (! m_parse.module);
00416         reconstruct (top);
00417         ASSERT (! m_parse.module);
00418 
00419         // Try loading the modules to check that they are well-formed:
00420         // ensure that each module loads and resolves the required
00421         // entry points.  If this fails, mark the whole registration
00422         // file bad so that it will be ignored until the time-stamp
00423         // changes.  This leaves the cache always in valid state,
00424         // remembering anything bad.
00425         ASSERT (m_parse.result.size () == 1);
00426         for (ModuleIterator m = m_parse.result.begin () ; m != m_parse.result.end (); ++m)
00427             try
00428             {
00429                 (*m)->load (); // checks for entry points
00430                 (*m)->query ();
00431                 (*m)->unload ();
00432             }
00433             catch (lat::Error &e)
00434             {
00435                 m_manager->feedback (IgPluginManager::ErrorBadModule,
00436                                      (*m)->libraryName (), &e);
00437 
00438                 // FIXME: Notify to owner
00439                 LOG (0, error, LFplugin_manager,
00440                      *file << ": bad module library `"
00441                      << (*m)->libraryName ()
00442                      << "', module ignored\n (error was: "
00443                      << e.explain () << ")\n");
00444                 m_state.skipped = true;
00445                 (*m)->bad (true);
00446                 break;
00447             }
00448 
00449         // Transfer into cache.
00450         cache.splice (cache.end (), m_parse.result);
00451     }
00452 
00453     // See if cache contains info on removed modules.
00454     for (ModuleIterator m = m_cache.begin (); m != m_cache.end (); ++m)
00455         if (std::find_if (cache.begin (), cache.end (),
00456                           FileByName ((*m)->libraryName ().nondirectory ()))
00457             == cache.end ())
00458         {
00459             LOG (0, trace, LFplugin_manager,
00460                  "==> removed module `" << (*m)->libraryName () << "'\n");
00461             m_state.removed = true;
00462         }
00463 
00464     // Update status codes.  Note that CACHE_VALID means .cache is
00465     // valid, CACHE_OLD means it needs updating.  If directory was
00466     // empty, mark the cache valid so we don't try to create one.
00467     result = (m_state.added
00468               || m_state.removed
00469               || m_state.changed
00470               || m_state.skipped)
00471               ? CACHE_OLD : CACHE_VALID;
00472 
00473     LOG (0, trace, LFplugin_manager,
00474          lat::undent << "done (" << (int) result << ")\n");
00475     return result;
00476 }

void IgModuleCache::update ( void   )  [protected]

Update the ".cache" file on the disk if it is writable.

Definition at line 538 of file IgModuleCache.cc.

References python::cmstools::all(), CACHE_VALID, data, error, file, EgammaValidation_cff::filename, lat::indent(), LFplugin_manager, LOG, m, m_cache, m_directory, m_state, s_cacheFile, s_cacheTag, IgModuleCache::CacheContext::status, GsfMatrixTools::trace(), lat::undent(), and write().

Referenced by refresh().

00539 {
00540     if (m_state.status == CACHE_VALID)
00541         return;
00542 
00543     // Regenerate cache file from information we have in memory
00544     LOG (0, trace, LFplugin_manager,
00545          "updating cache in `" << m_directory << "'\n" << lat::indent);
00546 
00547     // Build a descriptor tree and dump it out
00548     IgModuleDescriptor *all = new IgModuleDescriptor (0, s_cacheTag);
00549     for (ModuleIterator m = m_cache.begin (); m != m_cache.end (); ++m)
00550         (*m)->cache (all);
00551 
00552     std::ostringstream buf;
00553     write (buf, all);
00554     delete all;
00555 
00556     lat::Filename filename (m_directory, s_cacheFile);
00557     FILE          *file = STDC::fopen (filename, "wb");
00558 
00559     if (! file)
00560     {
00561         LOG (0, error, LFplugin_manager,
00562              filename << ": error " << errno << ", unable to open the cache"
00563              " for writing -- cache not updated\n" << lat::undent);
00564         return;
00565     }
00566 
00567     std::string data (buf.str ());
00568     if (STDC::fwrite (data.c_str (), 1, data.size (), file) != data.size ())
00569     {
00570         LOG (0, error, LFplugin_manager,
00571              filename << ": error " << errno << " while writing cache out"
00572              " -- forcing file truncation\n");
00573 
00574         file = STDC::freopen (filename, "wb", file);
00575     }
00576     else
00577         m_state.status = CACHE_VALID;
00578 
00579     STDC::fclose (file);
00580 
00581     LOG (0, trace, LFplugin_manager, lat::undent << "done\n");
00582 }

void IgModuleCache::write ( std::ostream &  s,
IgModuleDescriptor doc,
int  level = 0 
) [private]

Dump the module descriptor doc and all it's children into the stream s.

Output should happen at nesting level; omit this argument on the first call, it is meant to be used only in the internal implementation.

Definition at line 525 of file IgModuleCache.cc.

References IgModuleDescriptor::child(), IgModuleDescriptor::children(), encode(), lat::endl(), i, IgModuleDescriptor::token(), and IgModuleDescriptor::tokens().

Referenced by update().

00526 {
00527     s << std::string (level, ' ') << encode (doc->token (0));
00528     for (unsigned i = 1; i < doc->tokens (); ++i)
00529         s << ' ' << encode (doc->token (i));
00530     s << std::endl;
00531 
00532     for (unsigned i = 0; i < doc->children (); ++i)
00533         write (s, doc->child (i), level+1);
00534 }


Friends And Related Function Documentation

friend struct CacheContext [friend]

Definition at line 102 of file IgModuleCache.h.

friend class FileByName [friend]

Definition at line 106 of file IgModuleCache.h.

Referenced by scanModules().

friend struct ParseContext [friend]

Definition at line 105 of file IgModuleCache.h.


Member Data Documentation

ModuleList IgModuleCache::m_cache [private]

Definition at line 144 of file IgModuleCache.h.

Referenced by load(), notify(), rebuild(), scanModules(), update(), and ~IgModuleCache().

lat::Filename IgModuleCache::m_directory [private]

Definition at line 143 of file IgModuleCache.h.

Referenced by directory(), IgModuleCache(), load(), parse(), rebuild(), reconstruct(), scanModules(), update(), and ~IgModuleCache().

IgPluginManager* IgModuleCache::m_manager [private]

Definition at line 142 of file IgModuleCache.h.

Referenced by parse(), reconstruct(), and scanModules().

ModuleList IgModuleCache::m_modules [private]

Definition at line 147 of file IgModuleCache.h.

Referenced by begin(), end(), and notify().

ParseContext IgModuleCache::m_parse [private]

Definition at line 146 of file IgModuleCache.h.

Referenced by IgModuleCache(), load(), parse(), reconstruct(), and scanModules().

CacheContext IgModuleCache::m_state [private]

Definition at line 145 of file IgModuleCache.h.

Referenced by IgModuleCache(), load(), rebuild(), scanModules(), and update().

const char IgModuleCache::s_cacheFile = ".iglets" [static, private]

Definition at line 149 of file IgModuleCache.h.

Referenced by load(), scanModules(), and update().

const char IgModuleCache::s_cacheTag = "cache" [static, private]

Definition at line 150 of file IgModuleCache.h.

Referenced by makeBad(), reconstruct(), scanModules(), and update().

const char IgModuleCache::s_fileTag[] [static, private]

Definition at line 151 of file IgModuleCache.h.

const char IgModuleCache::s_moduleTag[] [static, private]

Definition at line 152 of file IgModuleCache.h.


The documentation for this class was generated from the following files:
Generated on Tue Jun 9 18:25:13 2009 for CMSSW by  doxygen 1.5.4