Commit 9a0d779c authored by Barry Warsaw's avatar Barry Warsaw

Port BerkeleyDB 4.1 support from the pybsddb project. bsddb is now at

version 4.1.1 and works with up to BerkeleyDB 4.1.25.
parent 0a26235e
...@@ -33,14 +33,7 @@ ...@@ -33,14 +33,7 @@
#---------------------------------------------------------------------- #----------------------------------------------------------------------
""" """Support for BerkeleyDB 3.1 through 4.1.
This package initialization module provides a compatibility interface
that should enable bsddb3 to be a near drop-in replacement for the original
old bsddb module. The functions and classes provided here are all
wrappers around the new functionality provided in the bsddb3.db module.
People interested in the more advanced capabilites of Berkeley DB 3.x
should use the bsddb3.db module directly.
""" """
try: try:
...@@ -55,7 +48,7 @@ except ImportError: ...@@ -55,7 +48,7 @@ except ImportError:
_db = _bsddb _db = _bsddb
__version__ = _db.__version__ __version__ = _db.__version__
error = _db.DBError # So bsddb3.error will mean something... error = _db.DBError # So bsddb.error will mean something...
#---------------------------------------------------------------------- #----------------------------------------------------------------------
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
import db import db
class DBEnv: class DBEnv:
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self._cobj = apply(db.DBEnv, args, kwargs) self._cobj = apply(db.DBEnv, args, kwargs)
...@@ -77,6 +76,14 @@ class DBEnv: ...@@ -77,6 +76,14 @@ class DBEnv:
def set_get_returns_none(self, *args, **kwargs): def set_get_returns_none(self, *args, **kwargs):
return apply(self._cobj.set_get_returns_none, args, kwargs) return apply(self._cobj.set_get_returns_none, args, kwargs)
if db.version() >= (4,1):
def dbremove(self, *args, **kwargs):
return apply(self._cobj.dbremove, args, kwargs)
def dbrename(self, *args, **kwargs):
return apply(self._cobj.dbrename, args, kwargs)
def set_encrypt(self, *args, **kwargs):
return apply(self._cobj.set_encrypt, args, kwargs)
class DB: class DB:
def __init__(self, dbenv, *args, **kwargs): def __init__(self, dbenv, *args, **kwargs):
...@@ -175,3 +182,8 @@ class DB: ...@@ -175,3 +182,8 @@ class DB:
return apply(self._cobj.verify, args, kwargs) return apply(self._cobj.verify, args, kwargs)
def set_get_returns_none(self, *args, **kwargs): def set_get_returns_none(self, *args, **kwargs):
return apply(self._cobj.set_get_returns_none, args, kwargs) return apply(self._cobj.set_get_returns_none, args, kwargs)
if db.version() >= (4,1):
def set_encrypt(self, *args, **kwargs):
return apply(self._cobj.set_encrypt, args, kwargs)
""" """
File-like objects that read from or write to a bsddb3 record. File-like objects that read from or write to a bsddb record.
This implements (nearly) all stdio methods. This implements (nearly) all stdio methods.
......
...@@ -23,8 +23,7 @@ ...@@ -23,8 +23,7 @@
# #
#------------------------------------------------------------------------ #------------------------------------------------------------------------
""" """Manage shelves of pickled objects using bsddb database files for the
Manage shelves of pickled objects using bsddb3 database files for the
storage. storage.
""" """
...@@ -43,7 +42,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH, ...@@ -43,7 +42,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
shleve.py module. It can be used like this, where key is a string shleve.py module. It can be used like this, where key is a string
and data is a pickleable object: and data is a pickleable object:
from bsddb3 import dbshelve from bsddb import dbshelve
db = dbshelve.open(filename) db = dbshelve.open(filename)
db[key] = data db[key] = data
...@@ -63,7 +62,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH, ...@@ -63,7 +62,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
elif sflag == 'n': elif sflag == 'n':
flags = db.DB_TRUNCATE | db.DB_CREATE flags = db.DB_TRUNCATE | db.DB_CREATE
else: else:
raise error, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb3.db.DB_* flags" raise error, "flags should be one of 'r', 'w', 'c' or 'n' or use the bsddb.db.DB_* flags"
d = DBShelf(dbenv) d = DBShelf(dbenv)
d.open(filename, dbname, filetype, flags, mode) d.open(filename, dbname, filetype, flags, mode)
...@@ -73,7 +72,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH, ...@@ -73,7 +72,7 @@ def open(filename, flags=db.DB_CREATE, mode=0660, filetype=db.DB_HASH,
class DBShelf: class DBShelf:
""" """
A shelf to hold pickled objects, built upon a bsddb3 DB object. It A shelf to hold pickled objects, built upon a bsddb DB object. It
automatically pickles/unpickles data objects going to/from the DB. automatically pickles/unpickles data objects going to/from the DB.
""" """
def __init__(self, dbenv=None): def __init__(self, dbenv=None):
...@@ -286,3 +285,6 @@ class DBShelfCursor: ...@@ -286,3 +285,6 @@ class DBShelfCursor:
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
This diff is collapsed.
...@@ -22,19 +22,21 @@ ...@@ -22,19 +22,21 @@
# #
# import the time.sleep function in a namespace safe way to allow # import the time.sleep function in a namespace safe way to allow
# "from bsddb3.db import *" # "from bsddb.db import *"
# #
from time import sleep from time import sleep as _sleep
_sleep = sleep
del sleep
import _bsddb from bsddb import _db
_deadlock_MinSleepTime = 1.0/64 # always sleep at least N seconds between retrys # always sleep at least N seconds between retrys
_deadlock_MaxSleepTime = 3.14159 # never sleep more than N seconds between retrys _deadlock_MinSleepTime = 1.0/64
# never sleep more than N seconds between retrys
_deadlock_MaxSleepTime = 3.14159
# Assign a file object to this for a "sleeping" message to be written to it
# each retry
_deadlock_VerboseFile = None
_deadlock_VerboseFile = None # Assign a file object to this for a "sleeping"
# message to be written to it each retry
def DeadlockWrap(function, *_args, **_kwargs): def DeadlockWrap(function, *_args, **_kwargs):
"""DeadlockWrap(function, *_args, **_kwargs) - automatically retries """DeadlockWrap(function, *_args, **_kwargs) - automatically retries
...@@ -57,16 +59,17 @@ def DeadlockWrap(function, *_args, **_kwargs): ...@@ -57,16 +59,17 @@ def DeadlockWrap(function, *_args, **_kwargs):
del _kwargs['max_retries'] del _kwargs['max_retries']
while 1: while 1:
try: try:
return apply(function, _args, _kwargs) return function(*_args, **_kwargs)
except _bsddb.DBLockDeadlockError: except _db.DBLockDeadlockError:
if _deadlock_VerboseFile: if _deadlock_VerboseFile:
_deadlock_VerboseFile.write('dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime) _deadlock_VerboseFile.write(
'dbutils.DeadlockWrap: sleeping %1.3f\n' % sleeptime)
_sleep(sleeptime) _sleep(sleeptime)
# exponential backoff in the sleep time # exponential backoff in the sleep time
sleeptime = sleeptime * 2 sleeptime *= 2
if sleeptime > _deadlock_MaxSleepTime : if sleeptime > _deadlock_MaxSleepTime:
sleeptime = _deadlock_MaxSleepTime sleeptime = _deadlock_MaxSleepTime
max_retries = max_retries - 1 max_retries -= 1
if max_retries == -1: if max_retries == -1:
raise raise
......
"""Run all test cases.
"""
import sys
import os
import unittest
verbose = 0
if 'verbose' in sys.argv:
verbose = 1
sys.argv.remove('verbose')
if 'silent' in sys.argv: # take care of old flag, just in case
verbose = 0
sys.argv.remove('silent')
def print_versions():
from bsddb import db
print
print '-=' * 38
print db.DB_VERSION_STRING
print 'bsddb.db.version(): %s' % (db.version(), )
print 'bsddb.db.__version__: %s' % db.__version__
print 'bsddb.db.cvsid: %s' % db.cvsid
print 'python version: %s' % sys.version
print 'My pid: %s' % os.getpid()
print '-=' * 38
class PrintInfoFakeTest(unittest.TestCase):
def testPrintVersions(self):
print_versions()
# This little hack is for when this module is run as main and all the
# other modules import it so they will still be able to get the right
# verbose setting. It's confusing but it works.
import test_all
test_all.verbose = verbose
def suite():
test_modules = [
'test_associate',
'test_basics',
'test_compat',
'test_dbobj',
'test_dbshelve',
'test_dbtables',
'test_env_close',
'test_get_none',
'test_join',
'test_lock',
'test_misc',
'test_queue',
'test_recno',
'test_thread',
]
alltests = unittest.TestSuite()
for name in test_modules:
module = __import__(name)
alltests.addTest(module.suite())
return alltests
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(PrintInfoFakeTest))
return suite
if __name__ == '__main__':
print_versions()
unittest.main(defaultTest='suite')
...@@ -14,7 +14,7 @@ except ImportError: ...@@ -14,7 +14,7 @@ except ImportError:
have_threads = 0 have_threads = 0
import unittest import unittest
from test.test_support import verbose from test_all import verbose
from bsddb import db, dbshelve from bsddb import db, dbshelve
...@@ -70,7 +70,8 @@ musicdata = { ...@@ -70,7 +70,8 @@ musicdata = {
45: ("Blue Man Group", "Klein Mandelbrot", "New Age"), 45: ("Blue Man Group", "Klein Mandelbrot", "New Age"),
46: ("Kenny G", "Silhouette", "Jazz"), 46: ("Kenny G", "Silhouette", "Jazz"),
47: ("Sade", "Smooth Operator", "Jazz"), 47: ("Sade", "Smooth Operator", "Jazz"),
48: ("David Arkenstone", "Papillon (On The Wings Of The Butterfly)", "New Age"), 48: ("David Arkenstone", "Papillon (On The Wings Of The Butterfly)",
"New Age"),
49: ("David Arkenstone", "Stepping Stars", "New Age"), 49: ("David Arkenstone", "Stepping Stars", "New Age"),
50: ("David Arkenstone", "Carnation Lily Lily Rose", "New Age"), 50: ("David Arkenstone", "Carnation Lily Lily Rose", "New Age"),
51: ("David Lanz", "Behind The Waterfall", "New Age"), 51: ("David Lanz", "Behind The Waterfall", "New Age"),
...@@ -109,8 +110,6 @@ class AssociateTestCase(unittest.TestCase): ...@@ -109,8 +110,6 @@ class AssociateTestCase(unittest.TestCase):
key = "%02d" % key key = "%02d" % key
d.put(key, string.join(value, '|')) d.put(key, string.join(value, '|'))
def createDB(self): def createDB(self):
self.primary = db.DB(self.env) self.primary = db.DB(self.env)
self.primary.open(self.filename, "primary", self.dbtype, self.primary.open(self.filename, "primary", self.dbtype,
...@@ -122,18 +121,18 @@ class AssociateTestCase(unittest.TestCase): ...@@ -122,18 +121,18 @@ class AssociateTestCase(unittest.TestCase):
def getDB(self): def getDB(self):
return self.primary return self.primary
def test01_associateWithDB(self): def test01_associateWithDB(self):
if verbose: if verbose:
print '\n', '-=' * 30 print '\n', '-=' * 30
print "Running %s.test01_associateWithDB..." % self.__class__.__name__ print "Running %s.test01_associateWithDB..." % \
self.__class__.__name__
self.createDB() self.createDB()
secDB = db.DB(self.env) secDB = db.DB(self.env)
secDB.set_flags(db.DB_DUP) secDB.set_flags(db.DB_DUP)
secDB.open(self.filename, "secondary", db.DB_BTREE, db.DB_CREATE | db.DB_THREAD) secDB.open(self.filename, "secondary", db.DB_BTREE,
db.DB_CREATE | db.DB_THREAD)
self.getDB().associate(secDB, self.getGenre) self.getDB().associate(secDB, self.getGenre)
self.addDataToDB(self.getDB()) self.addDataToDB(self.getDB())
...@@ -144,14 +143,16 @@ class AssociateTestCase(unittest.TestCase): ...@@ -144,14 +143,16 @@ class AssociateTestCase(unittest.TestCase):
def test02_associateAfterDB(self): def test02_associateAfterDB(self):
if verbose: if verbose:
print '\n', '-=' * 30 print '\n', '-=' * 30
print "Running %s.test02_associateAfterDB..." % self.__class__.__name__ print "Running %s.test02_associateAfterDB..." % \
self.__class__.__name__
self.createDB() self.createDB()
self.addDataToDB(self.getDB()) self.addDataToDB(self.getDB())
secDB = db.DB(self.env) secDB = db.DB(self.env)
secDB.set_flags(db.DB_DUP) secDB.set_flags(db.DB_DUP)
secDB.open(self.filename, "secondary", db.DB_BTREE, db.DB_CREATE | db.DB_THREAD) secDB.open(self.filename, "secondary", db.DB_BTREE,
db.DB_CREATE | db.DB_THREAD)
# adding the DB_CREATE flag will cause it to index existing records # adding the DB_CREATE flag will cause it to index existing records
self.getDB().associate(secDB, self.getGenre, db.DB_CREATE) self.getDB().associate(secDB, self.getGenre, db.DB_CREATE)
...@@ -159,8 +160,6 @@ class AssociateTestCase(unittest.TestCase): ...@@ -159,8 +160,6 @@ class AssociateTestCase(unittest.TestCase):
self.finish_test(secDB) self.finish_test(secDB)
def finish_test(self, secDB): def finish_test(self, secDB):
if verbose: if verbose:
print "Primary key traversal:" print "Primary key traversal:"
...@@ -190,9 +189,8 @@ class AssociateTestCase(unittest.TestCase): ...@@ -190,9 +189,8 @@ class AssociateTestCase(unittest.TestCase):
if verbose: if verbose:
print rec print rec
rec = c.next() rec = c.next()
assert count == len(musicdata)-1 # all items accounted for EXCEPT for 1 with "Blues" genre # all items accounted for EXCEPT for 1 with "Blues" genre
assert count == len(musicdata)-1
def getGenre(self, priKey, priData): def getGenre(self, priKey, priData):
assert type(priData) == type("") assert type(priData) == type("")
...@@ -299,25 +297,25 @@ class ThreadedAssociateRecnoTestCase(ShelveAssociateTestCase): ...@@ -299,25 +297,25 @@ class ThreadedAssociateRecnoTestCase(ShelveAssociateTestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
theSuite = unittest.TestSuite() suite = unittest.TestSuite()
if db.version() >= (3, 3, 11): if db.version() >= (3, 3, 11):
theSuite.addTest(unittest.makeSuite(AssociateHashTestCase)) suite.addTest(unittest.makeSuite(AssociateHashTestCase))
theSuite.addTest(unittest.makeSuite(AssociateBTreeTestCase)) suite.addTest(unittest.makeSuite(AssociateBTreeTestCase))
theSuite.addTest(unittest.makeSuite(AssociateRecnoTestCase)) suite.addTest(unittest.makeSuite(AssociateRecnoTestCase))
theSuite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase)) suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase))
theSuite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase)) suite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase))
theSuite.addTest(unittest.makeSuite(ShelveAssociateRecnoTestCase)) suite.addTest(unittest.makeSuite(ShelveAssociateRecnoTestCase))
if have_threads: if have_threads:
theSuite.addTest(unittest.makeSuite(ThreadedAssociateHashTestCase)) suite.addTest(unittest.makeSuite(ThreadedAssociateHashTestCase))
theSuite.addTest(unittest.makeSuite(ThreadedAssociateBTreeTestCase)) suite.addTest(unittest.makeSuite(ThreadedAssociateBTreeTestCase))
theSuite.addTest(unittest.makeSuite(ThreadedAssociateRecnoTestCase)) suite.addTest(unittest.makeSuite(ThreadedAssociateRecnoTestCase))
return theSuite return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
This diff is collapsed.
...@@ -9,7 +9,7 @@ import bsddb ...@@ -9,7 +9,7 @@ import bsddb
import unittest import unittest
import tempfile import tempfile
from test.test_support import verbose from test_all import verbose
...@@ -159,9 +159,9 @@ class CompatibilityTestCase(unittest.TestCase): ...@@ -159,9 +159,9 @@ class CompatibilityTestCase(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(CompatibilityTestCase) return unittest.makeSuite(CompatibilityTestCase)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -36,18 +36,20 @@ class dbobjTestCase(unittest.TestCase): ...@@ -36,18 +36,20 @@ class dbobjTestCase(unittest.TestCase):
# call our parent classes put method with an upper case key # call our parent classes put method with an upper case key
return apply(dbobj.DB.put, (self, key) + args, kwargs) return apply(dbobj.DB.put, (self, key) + args, kwargs)
self.env = TestDBEnv() self.env = TestDBEnv()
self.env.open(self.db_home, db.DB_CREATE | db.DB_INIT_MPOOL) self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL)
self.db = TestDB(self.env) self.db = TestDB(self.env)
self.db.open(self.db_name, db.DB_HASH, db.DB_CREATE) self.db.open(self.db_name, db.DB_HASH, db.DB_CREATE)
self.db.put('spam', 'eggs') self.db.put('spam', 'eggs')
assert self.db.get('spam') == None, "overridden dbobj.DB.put() method failed [1]" assert self.db.get('spam') == None, \
assert self.db.get('SPAM') == 'eggs', "overridden dbobj.DB.put() method failed [2]" "overridden dbobj.DB.put() method failed [1]"
assert self.db.get('SPAM') == 'eggs', \
"overridden dbobj.DB.put() method failed [2]"
self.db.close() self.db.close()
self.env.close() self.env.close()
def test02_dbobj_dict_interface(self): def test02_dbobj_dict_interface(self):
self.env = dbobj.DBEnv() self.env = dbobj.DBEnv()
self.env.open(self.db_home, db.DB_CREATE | db.DB_INIT_MPOOL) self.env.open(self.homeDir, db.DB_CREATE | db.DB_INIT_MPOOL)
self.db = dbobj.DB(self.env) self.db = dbobj.DB(self.env)
self.db.open(self.db_name+'02', db.DB_HASH, db.DB_CREATE) self.db.open(self.db_name+'02', db.DB_HASH, db.DB_CREATE)
# __setitem__ # __setitem__
...@@ -64,8 +66,8 @@ class dbobjTestCase(unittest.TestCase): ...@@ -64,8 +66,8 @@ class dbobjTestCase(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(dbobjTestCase) return unittest.makeSuite(dbobjTestCase)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -10,7 +10,7 @@ import unittest ...@@ -10,7 +10,7 @@ import unittest
from bsddb import dbshelve, db from bsddb import dbshelve, db
from test.test_support import verbose from test_all import verbose
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -143,6 +143,7 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -143,6 +143,7 @@ class DBShelveTestCase(unittest.TestCase):
key, value = rec key, value = rec
self.checkrec(key, value) self.checkrec(key, value)
rec = c.next() rec = c.next()
del c
assert count == len(d) assert count == len(d)
...@@ -162,9 +163,7 @@ class DBShelveTestCase(unittest.TestCase): ...@@ -162,9 +163,7 @@ class DBShelveTestCase(unittest.TestCase):
c.set('SS') c.set('SS')
key, value = c.current() key, value = c.current()
self.checkrec(key, value) self.checkrec(key, value)
del c
c.close()
...@@ -202,8 +201,6 @@ class BasicShelveTestCase(DBShelveTestCase): ...@@ -202,8 +201,6 @@ class BasicShelveTestCase(DBShelveTestCase):
self.d.close() self.d.close()
class BTreeShelveTestCase(BasicShelveTestCase): class BTreeShelveTestCase(BasicShelveTestCase):
dbtype = db.DB_BTREE dbtype = db.DB_BTREE
dbflags = db.DB_CREATE dbflags = db.DB_CREATE
...@@ -228,7 +225,8 @@ class ThreadHashShelveTestCase(BasicShelveTestCase): ...@@ -228,7 +225,8 @@ class ThreadHashShelveTestCase(BasicShelveTestCase):
class BasicEnvShelveTestCase(DBShelveTestCase): class BasicEnvShelveTestCase(DBShelveTestCase):
def do_open(self): def do_open(self):
self.homeDir = homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home') self.homeDir = homeDir = os.path.join(
os.path.dirname(sys.argv[0]), 'db_home')
try: os.mkdir(homeDir) try: os.mkdir(homeDir)
except os.error: pass except os.error: pass
self.env = db.DBEnv() self.env = db.DBEnv()
...@@ -283,21 +281,21 @@ class EnvThreadHashShelveTestCase(BasicEnvShelveTestCase): ...@@ -283,21 +281,21 @@ class EnvThreadHashShelveTestCase(BasicEnvShelveTestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
theSuite = unittest.TestSuite() suite = unittest.TestSuite()
theSuite.addTest(unittest.makeSuite(DBShelveTestCase)) suite.addTest(unittest.makeSuite(DBShelveTestCase))
theSuite.addTest(unittest.makeSuite(BTreeShelveTestCase)) suite.addTest(unittest.makeSuite(BTreeShelveTestCase))
theSuite.addTest(unittest.makeSuite(HashShelveTestCase)) suite.addTest(unittest.makeSuite(HashShelveTestCase))
theSuite.addTest(unittest.makeSuite(ThreadBTreeShelveTestCase)) suite.addTest(unittest.makeSuite(ThreadBTreeShelveTestCase))
theSuite.addTest(unittest.makeSuite(ThreadHashShelveTestCase)) suite.addTest(unittest.makeSuite(ThreadHashShelveTestCase))
theSuite.addTest(unittest.makeSuite(EnvBTreeShelveTestCase)) suite.addTest(unittest.makeSuite(EnvBTreeShelveTestCase))
theSuite.addTest(unittest.makeSuite(EnvHashShelveTestCase)) suite.addTest(unittest.makeSuite(EnvHashShelveTestCase))
theSuite.addTest(unittest.makeSuite(EnvThreadBTreeShelveTestCase)) suite.addTest(unittest.makeSuite(EnvThreadBTreeShelveTestCase))
theSuite.addTest(unittest.makeSuite(EnvThreadHashShelveTestCase)) suite.addTest(unittest.makeSuite(EnvThreadHashShelveTestCase))
return theSuite return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
This diff is collapsed.
""" """TestCases for checking that it does not segfault when a DBEnv object
TestCases for checking that it does not segfault when a DBEnv object
is closed before its DB objects. is closed before its DB objects.
""" """
import sys, os, string import os
from pprint import pprint import sys
import tempfile import tempfile
import glob import glob
import unittest import unittest
from bsddb import db from bsddb import db
from test.test_support import verbose from test_all import verbose
# We're going to get warnings in this module about trying to close the db when
# its env is already closed. Let's just ignore those.
try:
import warnings
except ImportError:
pass
else:
warnings.filterwarnings('ignore',
message='DB could not be closed in',
category=RuntimeWarning)
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -33,7 +43,9 @@ class DBEnvClosedEarlyCrash(unittest.TestCase): ...@@ -33,7 +43,9 @@ class DBEnvClosedEarlyCrash(unittest.TestCase):
def test01_close_dbenv_before_db(self): def test01_close_dbenv_before_db(self):
dbenv = db.DBEnv() dbenv = db.DBEnv()
dbenv.open(self.homeDir,db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL, 0666) dbenv.open(self.homeDir,
db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL,
0666)
d = db.DB(dbenv) d = db.DB(dbenv)
d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0666) d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0666)
...@@ -45,14 +57,18 @@ class DBEnvClosedEarlyCrash(unittest.TestCase): ...@@ -45,14 +57,18 @@ class DBEnvClosedEarlyCrash(unittest.TestCase):
d.close() d.close()
except db.DBError: except db.DBError:
return return
assert 0, "DB close did not raise an exception about its DBEnv being trashed" assert 0, \
"DB close did not raise an exception about its "\
"DBEnv being trashed"
assert 0, "dbenv did not raise an exception about its DB being open" assert 0, "dbenv did not raise an exception about its DB being open"
def test02_close_dbenv_delete_db_success(self): def test02_close_dbenv_delete_db_success(self):
dbenv = db.DBEnv() dbenv = db.DBEnv()
dbenv.open(self.homeDir,db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL, 0666) dbenv.open(self.homeDir,
db.DB_INIT_CDB| db.DB_CREATE |db.DB_THREAD|db.DB_INIT_MPOOL,
0666)
d = db.DB(dbenv) d = db.DB(dbenv)
d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0666) d.open(self.filename, db.DB_BTREE, db.DB_CREATE | db.DB_THREAD, 0666)
...@@ -62,8 +78,6 @@ class DBEnvClosedEarlyCrash(unittest.TestCase): ...@@ -62,8 +78,6 @@ class DBEnvClosedEarlyCrash(unittest.TestCase):
except db.DBError: except db.DBError:
pass # good, it should raise an exception pass # good, it should raise an exception
# this should not raise an exception, it should silently skip
# the db->close() call as it can't be done safely.
del d del d
try: try:
import gc import gc
...@@ -76,9 +90,11 @@ class DBEnvClosedEarlyCrash(unittest.TestCase): ...@@ -76,9 +90,11 @@ class DBEnvClosedEarlyCrash(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(DBEnvClosedEarlyCrash) suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(DBEnvClosedEarlyCrash))
return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -9,7 +9,7 @@ import unittest ...@@ -9,7 +9,7 @@ import unittest
from bsddb import db from bsddb import db
from test.test_support import verbose from test_all import verbose
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -88,9 +88,9 @@ class GetReturnsNoneTestCase(unittest.TestCase): ...@@ -88,9 +88,9 @@ class GetReturnsNoneTestCase(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(GetReturnsNoneTestCase) return unittest.makeSuite(GetReturnsNoneTestCase)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -16,7 +16,7 @@ except ImportError: ...@@ -16,7 +16,7 @@ except ImportError:
import unittest import unittest
from test.test_support import verbose from test_all import verbose
from bsddb import db from bsddb import db
...@@ -68,15 +68,24 @@ class LockingTestCase(unittest.TestCase): ...@@ -68,15 +68,24 @@ class LockingTestCase(unittest.TestCase):
print "Running %s.test02_threaded..." % self.__class__.__name__ print "Running %s.test02_threaded..." % self.__class__.__name__
threads = [] threads = []
threads.append(Thread(target = self.theThread, args=(5, db.DB_LOCK_WRITE))) threads.append(Thread(target = self.theThread,
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_READ))) args=(5, db.DB_LOCK_WRITE)))
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_READ))) threads.append(Thread(target = self.theThread,
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_WRITE))) args=(1, db.DB_LOCK_READ)))
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_READ))) threads.append(Thread(target = self.theThread,
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_READ))) args=(1, db.DB_LOCK_READ)))
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_WRITE))) threads.append(Thread(target = self.theThread,
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_WRITE))) args=(1, db.DB_LOCK_WRITE)))
threads.append(Thread(target = self.theThread, args=(1, db.DB_LOCK_WRITE))) threads.append(Thread(target = self.theThread,
args=(1, db.DB_LOCK_READ)))
threads.append(Thread(target = self.theThread,
args=(1, db.DB_LOCK_READ)))
threads.append(Thread(target = self.theThread,
args=(1, db.DB_LOCK_WRITE)))
threads.append(Thread(target = self.theThread,
args=(1, db.DB_LOCK_WRITE)))
threads.append(Thread(target = self.theThread,
args=(1, db.DB_LOCK_WRITE)))
for t in threads: for t in threads:
t.start() t.start()
...@@ -109,16 +118,16 @@ class LockingTestCase(unittest.TestCase): ...@@ -109,16 +118,16 @@ class LockingTestCase(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
theSuite = unittest.TestSuite() suite = unittest.TestSuite()
if have_threads: if have_threads:
theSuite.addTest(unittest.makeSuite(LockingTestCase)) suite.addTest(unittest.makeSuite(LockingTestCase))
else: else:
theSuite.addTest(unittest.makeSuite(LockingTestCase, 'test01')) suite.addTest(unittest.makeSuite(LockingTestCase, 'test01'))
return theSuite return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
""" """Miscellaneous bsddb module test cases
Misc TestCases
""" """
import sys, os, string import os
import tempfile import sys
from pprint import pprint
import unittest import unittest
from bsddb import db from bsddb import db
...@@ -19,25 +17,26 @@ class MiscTestCase(unittest.TestCase): ...@@ -19,25 +17,26 @@ class MiscTestCase(unittest.TestCase):
self.filename = self.__class__.__name__ + '.db' self.filename = self.__class__.__name__ + '.db'
homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home') homeDir = os.path.join(os.path.dirname(sys.argv[0]), 'db_home')
self.homeDir = homeDir self.homeDir = homeDir
try: os.mkdir(homeDir) try:
except os.error: pass os.mkdir(homeDir)
except OSError:
pass
def tearDown(self): def tearDown(self):
try: os.remove(self.filename) try:
except os.error: pass os.remove(self.filename)
except OSError:
pass
import glob import glob
files = glob.glob(os.path.join(self.homeDir, '*')) files = glob.glob(os.path.join(self.homeDir, '*'))
for file in files: for file in files:
os.remove(file) os.remove(file)
def test01_badpointer(self): def test01_badpointer(self):
dbs = dbshelve.open(self.filename) dbs = dbshelve.open(self.filename)
dbs.close() dbs.close()
self.assertRaises(db.DBError, dbs.get, "foo") self.assertRaises(db.DBError, dbs.get, "foo")
def test02_db_home(self): def test02_db_home(self):
env = db.DBEnv() env = db.DBEnv()
# check for crash fixed when db_home is used before open() # check for crash fixed when db_home is used before open()
...@@ -45,12 +44,13 @@ class MiscTestCase(unittest.TestCase): ...@@ -45,12 +44,13 @@ class MiscTestCase(unittest.TestCase):
env.open(self.homeDir, db.DB_CREATE) env.open(self.homeDir, db.DB_CREATE)
assert self.homeDir == env.db_home assert self.homeDir == env.db_home
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(MiscTestCase) return unittest.makeSuite(MiscTestCase)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -9,7 +9,7 @@ import unittest ...@@ -9,7 +9,7 @@ import unittest
from bsddb import db from bsddb import db
from test.test_support import verbose from test_all import verbose
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -84,8 +84,8 @@ class SimpleQueueTestCase(unittest.TestCase): ...@@ -84,8 +84,8 @@ class SimpleQueueTestCase(unittest.TestCase):
pprint(d.stat()) pprint(d.stat())
assert len(d) == 0, \ assert len(d) == 0, \
"if you see this message then you need to rebuild BerkeleyDB 3.1.17 "\ "if you see this message then you need to rebuild " \
"with the patch in patches/qam_stat.diff" "BerkeleyDB 3.1.17 with the patch in patches/qam_stat.diff"
d.close() d.close()
...@@ -160,9 +160,9 @@ class SimpleQueueTestCase(unittest.TestCase): ...@@ -160,9 +160,9 @@ class SimpleQueueTestCase(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(SimpleQueueTestCase) return unittest.makeSuite(SimpleQueueTestCase)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -2,14 +2,16 @@ ...@@ -2,14 +2,16 @@
TestCases for exercising a Recno DB. TestCases for exercising a Recno DB.
""" """
import sys, os, string import os
import sys
import string
import tempfile import tempfile
from pprint import pprint from pprint import pprint
import unittest import unittest
from bsddb import db from bsddb import db
from test.test_support import verbose from test_all import verbose
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -165,21 +167,24 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -165,21 +167,24 @@ class SimpleRecnoTestCase(unittest.TestCase):
def test02_WithSource(self): def test02_WithSource(self):
""" """
A Recno file that is given a "backing source file" is essentially a simple ASCII A Recno file that is given a "backing source file" is essentially a
file. Normally each record is delimited by \n and so is just a line in the file, simple ASCII file. Normally each record is delimited by \n and so is
but you can set a different record delimiter if needed. just a line in the file, but you can set a different record delimiter
if needed.
""" """
source = os.path.join(os.path.dirname(sys.argv[0]), 'db_home/test_recno.txt') source = os.path.join(os.path.dirname(sys.argv[0]),
'db_home/test_recno.txt')
f = open(source, 'w') # create the file f = open(source, 'w') # create the file
f.close() f.close()
d = db.DB() d = db.DB()
d.set_re_delim(0x0A) # This is the default value, just checking if both int # This is the default value, just checking if both int
d.set_re_delim(0x0A)
d.set_re_delim('\n') # and char can be used... d.set_re_delim('\n') # and char can be used...
d.set_re_source(source) d.set_re_source(source)
d.open(self.filename, db.DB_RECNO, db.DB_CREATE) d.open(self.filename, db.DB_RECNO, db.DB_CREATE)
data = string.split("The quick brown fox jumped over the lazy dog") data = "The quick brown fox jumped over the lazy dog".split()
for datum in data: for datum in data:
d.append(datum) d.append(datum)
d.sync() d.sync()
...@@ -187,13 +192,13 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -187,13 +192,13 @@ class SimpleRecnoTestCase(unittest.TestCase):
# get the text from the backing source # get the text from the backing source
text = open(source, 'r').read() text = open(source, 'r').read()
text = string.strip(text) text = text.strip()
if verbose: if verbose:
print text print text
print data print data
print string.split(text, '\n') print text.split('\n')
assert string.split(text, '\n') == data assert text.split('\n') == data
# open as a DB again # open as a DB again
d = db.DB() d = db.DB()
...@@ -207,12 +212,13 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -207,12 +212,13 @@ class SimpleRecnoTestCase(unittest.TestCase):
d.close() d.close()
text = open(source, 'r').read() text = open(source, 'r').read()
text = string.strip(text) text = text.strip()
if verbose: if verbose:
print text print text
print string.split(text, '\n') print text.split('\n')
assert string.split(text, '\n') == string.split("The quick reddish-brown fox jumped over the comatose dog") assert text.split('\n') == \
"The quick reddish-brown fox jumped over the comatose dog".split()
def test03_FixedLength(self): def test03_FixedLength(self):
...@@ -248,9 +254,9 @@ class SimpleRecnoTestCase(unittest.TestCase): ...@@ -248,9 +254,9 @@ class SimpleRecnoTestCase(unittest.TestCase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
return unittest.makeSuite(SimpleRecnoTestCase) return unittest.makeSuite(SimpleRecnoTestCase)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
...@@ -16,11 +16,10 @@ except ImportError: ...@@ -16,11 +16,10 @@ except ImportError:
import unittest import unittest
from test.test_support import verbose from test_all import verbose
from bsddb import db, dbutils from bsddb import db, dbutils
#---------------------------------------------------------------------- #----------------------------------------------------------------------
class BaseThreadedTestCase(unittest.TestCase): class BaseThreadedTestCase(unittest.TestCase):
...@@ -80,7 +79,8 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase): ...@@ -80,7 +79,8 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
def test01_1WriterMultiReaders(self): def test01_1WriterMultiReaders(self):
if verbose: if verbose:
print '\n', '-=' * 30 print '\n', '-=' * 30
print "Running %s.test01_1WriterMultiReaders..." % self.__class__.__name__ print "Running %s.test01_1WriterMultiReaders..." % \
self.__class__.__name__
threads = [] threads = []
for x in range(self.writers): for x in range(self.writers):
...@@ -112,7 +112,8 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase): ...@@ -112,7 +112,8 @@ class ConcurrentDataStoreBase(BaseThreadedTestCase):
for x in range(start, stop): for x in range(start, stop):
key = '%04d' % x key = '%04d' % x
dbutils.DeadlockWrap(d.put, key, self.makeData(key), max_retries=12) dbutils.DeadlockWrap(d.put, key, self.makeData(key),
max_retries=12)
if verbose and x % 100 == 0: if verbose and x % 100 == 0:
print "%s: records %d - %d finished" % (name, start, x) print "%s: records %d - %d finished" % (name, start, x)
...@@ -215,7 +216,8 @@ class SimpleThreadedBase(BaseThreadedTestCase): ...@@ -215,7 +216,8 @@ class SimpleThreadedBase(BaseThreadedTestCase):
# create a bunch of records # create a bunch of records
for x in xrange(start, stop): for x in xrange(start, stop):
key = '%04d' % x key = '%04d' % x
dbutils.DeadlockWrap(d.put, key, self.makeData(key), max_retries=12) dbutils.DeadlockWrap(d.put, key, self.makeData(key),
max_retries=12)
if verbose and x % 100 == 0: if verbose and x % 100 == 0:
print "%s: records %d - %d finished" % (name, start, x) print "%s: records %d - %d finished" % (name, start, x)
...@@ -284,7 +286,7 @@ class HashSimpleThreaded(SimpleThreadedBase): ...@@ -284,7 +286,7 @@ class HashSimpleThreaded(SimpleThreadedBase):
class ThreadedTransactionsBase(BaseThreadedTestCase): class ThreadedTransactionsBase(BaseThreadedTestCase):
dbopenflags = db.DB_THREAD dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT
envflags = (db.DB_THREAD | envflags = (db.DB_THREAD |
db.DB_INIT_MPOOL | db.DB_INIT_MPOOL |
db.DB_INIT_LOCK | db.DB_INIT_LOCK |
...@@ -306,7 +308,8 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -306,7 +308,8 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
def test03_ThreadedTransactions(self): def test03_ThreadedTransactions(self):
if verbose: if verbose:
print '\n', '-=' * 30 print '\n', '-=' * 30
print "Running %s.test03_ThreadedTransactions..." % self.__class__.__name__ print "Running %s.test03_ThreadedTransactions..." % \
self.__class__.__name__
threads = [] threads = []
for x in range(self.writers): for x in range(self.writers):
...@@ -430,9 +433,11 @@ class ThreadedTransactionsBase(BaseThreadedTestCase): ...@@ -430,9 +433,11 @@ class ThreadedTransactionsBase(BaseThreadedTestCase):
while self.doLockDetect: while self.doLockDetect:
time.sleep(0.5) time.sleep(0.5)
try: try:
aborted = self.env.lock_detect(db.DB_LOCK_RANDOM, db.DB_LOCK_CONFLICT) aborted = self.env.lock_detect(
db.DB_LOCK_RANDOM, db.DB_LOCK_CONFLICT)
if verbose and aborted: if verbose and aborted:
print "deadlock: Aborted %d deadlocked transaction(s)" % aborted print "deadlock: Aborted %d deadlocked transaction(s)" \
% aborted
except db.DBError: except db.DBError:
pass pass
...@@ -467,24 +472,24 @@ class HashThreadedNoWaitTransactions(ThreadedTransactionsBase): ...@@ -467,24 +472,24 @@ class HashThreadedNoWaitTransactions(ThreadedTransactionsBase):
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def suite(): def test_suite():
theSuite = unittest.TestSuite() suite = unittest.TestSuite()
if have_threads: if have_threads:
theSuite.addTest(unittest.makeSuite(BTreeConcurrentDataStore)) suite.addTest(unittest.makeSuite(BTreeConcurrentDataStore))
theSuite.addTest(unittest.makeSuite(HashConcurrentDataStore)) suite.addTest(unittest.makeSuite(HashConcurrentDataStore))
theSuite.addTest(unittest.makeSuite(BTreeSimpleThreaded)) suite.addTest(unittest.makeSuite(BTreeSimpleThreaded))
theSuite.addTest(unittest.makeSuite(HashSimpleThreaded)) suite.addTest(unittest.makeSuite(HashSimpleThreaded))
theSuite.addTest(unittest.makeSuite(BTreeThreadedTransactions)) suite.addTest(unittest.makeSuite(BTreeThreadedTransactions))
theSuite.addTest(unittest.makeSuite(HashThreadedTransactions)) suite.addTest(unittest.makeSuite(HashThreadedTransactions))
theSuite.addTest(unittest.makeSuite(BTreeThreadedNoWaitTransactions)) suite.addTest(unittest.makeSuite(BTreeThreadedNoWaitTransactions))
theSuite.addTest(unittest.makeSuite(HashThreadedNoWaitTransactions)) suite.addTest(unittest.makeSuite(HashThreadedNoWaitTransactions))
else: else:
print "Threads not available, skipping thread tests." print "Threads not available, skipping thread tests."
return theSuite return suite
if __name__ == '__main__': if __name__ == '__main__':
unittest.main( defaultTest='suite' ) unittest.main(defaultTest='test_suite')
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment