def isDbUpToDate ( databaseFile ):
     """ Check if index database is up to date """
     upToDate      = False
     for dbFile in ( databaseFile + os.path.extsep + 'db', databaseFile ):
         try:
             if not os.path.exists(dbFile):
                 # Database doesn't exist, try next one
                 continue;
             if not whichdb(dbFile):
                 # Not in a readable format
                 logger.debug ( 'Database not in a readable format: %s', dbFile );
                 break;
             # From here, database exists and is readable
             db = dbm.open(dbFile)
             sourceFile  = db["__source_path__"]
             if not os.path.exists(sourceFile):
                 # Source file doesn't exist any more
                 break;
             textFileSum = md5sum(sourceFile)
             if textFileSum != db["__source_md5__"]:
                 logger.debug ( 'Source file checksum differs from the one used to build the database: %s', sourceFile );
                 db.close()
                 break;
             if not db["__version__"] == Database.version:
                 logger.debug ( 'Database version "%s" doesn\'t match this version "%s"', db["__version__"], Database.version );
                 db.close()
                 break;
             db.close()
             # Everything is ok with the existing database
             upToDate = True
             break;
         except Exception:
             pass
     return upToDate
 def parse_confs(self,conf_dir):
     try:
         agents = {}
         for conf in searchFiles(conf_dir, lambda _,ext: ext=='agent'):
             conf = os.path.abspath(conf)
             # Records this new agent placeholder
             agents[conf] = Any( **{"sum":0, "current_sum":md5sum(conf), "handle":None} );
     except Exception:
         logger.error ( 'Exception parsing conf %s', sys.exc_info()[1] );
         logger.debug ( "", exc_info=True );
         return;
     return agents
    def refresh (self):
        """ Rebuild the index from source file """

        # The cache directory must exist
        self.check_cache(confdir.cache)

        # these might speed-up indexing
        db_oids = []
        open_flags = 'nfu' 
        while open_flags:
            try:
                # Issue #4: work on a temporary file to limit collisions
                db = dbm.open(self.__dbFileTmp, open_flags)
                db["__version__"]     = Database.version
                db["__source_path__"] = os.path.abspath(self.sourceFile)
                db["__source_md5__"]  = md5sum(self.sourceFile)
            except Exception:
                open_flags = open_flags[:-1]
                if not open_flags:
                    raise
            else:
                break

        text = open(self.sourceFile, 'rb')

        logger.debug ( 'Building index %s for data file %s (open flags \"%s\")', self.__dbFileTmp, self.sourceFile, open_flags );

        # Build the "direct" indexes to have direct access to values
        nb_direct = nb_next = 0
        lineNo = 0
        while 1:

            try:
                oid = line = None
                while not oid:
                    line = text.readline()
                    lineNo += 1
                    if not line: break
                    oid, tag, val = self.textParser.grammar.parse(line)
                if not oid: break
            except Exception:
                db.close()
                exc = sys.exc_info()[1]
                try:
                    os.remove(self.__dbFileTmp)
                except OSError:
                    pass
                raise Exception('Data error at %s:%d: %s' % ( self.sourceFile, lineNo, exc ) )

            try:
                _oid     = self.textParser.evaluateOid(oid)
            except Exception:
                db.close()
                exc = sys.exc_info()[1]
                try:
                    os.remove(self.__dbFileTmp)
                except OSError:
                    pass
                raise Exception( 'OID error at %s:%d: %s' % ( self.sourceFile, lineNo, exc ) )

            try:
                _tag = self.textParser.evaluateTag(tag)
            except Exception:
                logger.warn ( 'Validation error at line %s, tag %r: %s', lineNo, tag, sys.exc_info()[1] );

            try:
                _val = self.textParser.evaluateValue( oid, tag, val, dataValidation=True)
            except Exception:
                logger.warn ( 'Validation error at line %s, value %r: %s', lineNo, val, sys.exc_info()[1] );

            # for lines serving subtrees, type is empty in tag field
            db[oid] = '%s,%d,%s,%s' % (oid2str(_oid), tag[0] == ':', _tag, _val)
            db_oids.append ( _oid );
            nb_direct = nb_direct+1

        # Build the "next" indexes to have direct access to next values

        # First we need oids splitted into nodes. We cannot sort them by string
        #   comparison: "1"<"10"<"2" and we want 1<2<10
        db_oids.sort()
        for i in range(len(db_oids)-1):
            oid         = db_oids[i]
            oid_txt     = oid2str(oid)
            # The easy one
            key      = "next."+oid_txt
            db[key]  = oid2str(db_oids[i+1])
            nb_next  = nb_next+1
            # Now the parents: their next is current oid unless they already have one next
            nodes = oid[:-1]
            for n in range(len(nodes)):
                key     = "next." + oid2str(nodes[:n+1])
                if not db.has_key(key):
                    db[key] = oid_txt
                    nb_next = nb_next+1
        # The last one have no next
        key = "next." + oid2str(db_oids[ len(db_oids)-1 ])
        db[key] = ""
        nb_next = nb_next+1

        text.close()
        db.close()
        logger.debug ( 'Index ok: %d direct entries, %d next entries' % (nb_direct,nb_next) );

        # Issue #4: Synchronizes access to the database
        self.__lock.acquire(True);
        try:
            self.close()
            if os.access(self.__dbFile, os.R_OK):
                os.remove(self.__dbFile);
            os.rename(self.__dbFileTmp, self.__dbFile);
            self.__dbType = whichdb(self.__dbFile)
        finally:
            self.__lock.release();