[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[minion-cvs] Recover from crashes better when using berkeley db and ...



Update of /home/minion/cvsroot/src/minion/lib/mixminion
In directory moria.mit.edu:/tmp/cvs-serv29700/lib/mixminion

Modified Files:
	Filestore.py 
Log Message:
Recover from crashes better when using berkeley db and recent pythons

Index: Filestore.py
===================================================================
RCS file: /home/minion/cvsroot/src/minion/lib/mixminion/Filestore.py,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- Filestore.py	27 Jul 2004 03:07:06 -0000	1.21
+++ Filestore.py	9 Aug 2004 19:29:55 -0000	1.22
@@ -528,12 +528,45 @@
 # ======================================================================
 # Database wrappers
 
+def _openDBHash(filename,flag,mode=0666):
+    """Open a Berkeley DB hash database.  Equivalent to dbhash.open, but when
+       possible, reaches into bsddb.db and uses the DB_RECOVER* flag(s) to
+       handle possible corruption from crashing without closing the database.
+    """
+    try:
+        import bsddb
+    except ImportError:
+        # Fallback to anydbm, which delegates to dbhash
+        return anydbm.open(filename, flag, mode)
+    # Adapted from bsddb.hashopen
+    flags = bsddb._checkFlag(flag)
+    flags |= getattr(bsddb.db, "DB_RECOVER", 0)
+    flags |= getattr(bsddb.db, "DB_RECOVER_FATAL", 0)
+    d = bsddb.db.DB()
+    d.set_flags(flags)
+    d.open(filename, bsddb.db.DB_HASH, flags, mode)
+    return bsddb._DBWithCursor(d)
+
 def openDB(filename, purpose):
-    """DOCDOC"""
+    """Replacement for anydbm.open.  Open a database stored in 'filename',
+       using the best available database implementation.  The string 'purpose'
+       is used to indicate which database has succeeded or failed in any
+       messages.
+
+       Changes from anydbm.open:
+         - Create parent directory if it doesn't exist.
+         - Bail with sane error messages if file is non-readable.
+         - Handle the error case where the database file is created but never
+           filled.
+         - Always create the database if it doesn't exist.
+         - Warn if using a dumbdbm database.
+         - Return a 2-tuple of the database object and a no-arguments callable
+           that flushes the database's contents to disk.
+    """
     parent = os.path.split(filename)[0]
     createPrivateDir(parent)
 
-    # If the file can't be read, bail.
+    # If the file exists, but can't be read, bail.
     try:
         st = os.stat(filename)
     except OSError, e:
@@ -545,13 +578,16 @@
         LOG.warn("Half-created database %s found; cleaning up.", filename)
         tryUnlink(filename)
 
+    dbtype = whichdb.whichdb(filename)
     LOG.debug("Opening %s database at %s", purpose, filename)
     try:
-        db = anydbm.open(filename, 'c')
+        if dbtype != 'dbhash':
+            db = _openDBHash(filename, 'c', 0600)
+        else:
+            db = anydbm.open(filename, 'c', 0600)
     except anydbm.error, e:
         raise MixFatalError("Can't open %s database: %s"%(purpose,e))
     except ImportError:
-        dbtype = whichdb.whichdb(filename)
         raise MixFatalError("Unsupported type for %s database: %s"
                             %(purpose, dbtype))