[Python-checkins] r79285 - in python/trunk: Lib/bsddb/__init__.py Lib/bsddb/dbobj.py Lib/bsddb/dbshelve.py Lib/bsddb/dbtables.py Lib/bsddb/test/test_all.py Lib/bsddb/test/test_associate.py Lib/bsddb/test/test_basics.py Lib/bsddb/test/test_compare.py Lib/bsddb/test/test_dbshelve.py Lib/bsddb/test/test_dbtables.py Lib/bsddb/test/test_distributed_transactions.py Lib/bsddb/test/test_early_close.py Lib/bsddb/test/test_lock.py Lib/bsddb/test/test_misc.py Lib/bsddb/test/test_pickle.py Lib/bsddb/test/test_recno.py Lib/bsddb/test/test_replication.py Lib/bsddb/test/test_sequence.py Lib/bsddb/test/test_thread.py Misc/NEWS Modules/_bsddb.c Modules/bsddb.h setup.py

jesus.cea python-checkins at python.org
Mon Mar 22 15:22:27 CET 2010


Author: jesus.cea
Date: Mon Mar 22 15:22:26 2010
New Revision: 79285
Log:
pybsddb 4.8.4 integration. Please, comment in issue #8156
Modified:
 python/trunk/Lib/bsddb/__init__.py
 python/trunk/Lib/bsddb/dbobj.py
 python/trunk/Lib/bsddb/dbshelve.py
 python/trunk/Lib/bsddb/dbtables.py
 python/trunk/Lib/bsddb/test/test_all.py
 python/trunk/Lib/bsddb/test/test_associate.py
 python/trunk/Lib/bsddb/test/test_basics.py
 python/trunk/Lib/bsddb/test/test_compare.py
 python/trunk/Lib/bsddb/test/test_dbshelve.py
 python/trunk/Lib/bsddb/test/test_dbtables.py
 python/trunk/Lib/bsddb/test/test_distributed_transactions.py
 python/trunk/Lib/bsddb/test/test_early_close.py
 python/trunk/Lib/bsddb/test/test_lock.py
 python/trunk/Lib/bsddb/test/test_misc.py
 python/trunk/Lib/bsddb/test/test_pickle.py
 python/trunk/Lib/bsddb/test/test_recno.py
 python/trunk/Lib/bsddb/test/test_replication.py
 python/trunk/Lib/bsddb/test/test_sequence.py
 python/trunk/Lib/bsddb/test/test_thread.py
 python/trunk/Misc/NEWS
 python/trunk/Modules/_bsddb.c
 python/trunk/Modules/bsddb.h
 python/trunk/setup.py
Modified: python/trunk/Lib/bsddb/__init__.py
==============================================================================
--- python/trunk/Lib/bsddb/__init__.py	(original)
+++ python/trunk/Lib/bsddb/__init__.py	Mon Mar 22 15:22:26 2010
@@ -33,7 +33,7 @@
 #----------------------------------------------------------------------
 
 
-"""Support for Berkeley DB 4.0 through 4.7 with a simple interface.
+"""Support for Berkeley DB 4.1 through 4.8 with a simple interface.
 
 For the full featured object oriented interface use the bsddb.db module
 instead. It mirrors the Oracle Berkeley DB C API.
@@ -42,11 +42,12 @@
 import sys
 absolute_import = (sys.version_info[0] >= 3)
 
-if sys.py3kwarning:
- import warnings
- warnings.warnpy3k("in 3.x, the bsddb module has been removed; "
- "please use the pybsddb project instead",
- DeprecationWarning, 2)
+if (sys.version_info >= (2, 6)) and (sys.version_info < (3, 0)) :
+ if sys.py3kwarning and (__name__ != 'bsddb3') :
+ import warnings
+ warnings.warnpy3k("in 3.x, the bsddb module has been removed; "
+ "please use the pybsddb project instead",
+ DeprecationWarning, 2)
 
 try:
 if __name__ == 'bsddb3':
@@ -81,7 +82,7 @@
 
 from weakref import ref
 
-if sys.version_info[0:2] <= (2, 5) :
+if sys.version_info < (2, 6) :
 import UserDict
 MutableMapping = UserDict.DictMixin
 else :
@@ -256,7 +257,7 @@
 self._checkOpen()
 return _DeadlockWrap(lambda: len(self.db)) # len(self.db)
 
- if sys.version_info[0:2] >= (2, 6) :
+ if sys.version_info >= (2, 6) :
 def __repr__(self) :
 if self.isOpen() :
 return repr(dict(_DeadlockWrap(self.db.items)))
@@ -442,8 +443,10 @@
 # Berkeley DB was too.
 
 try:
- import thread
- del thread
+ # 2to3 automatically changes "import thread" to "import _thread"
+ import thread as T
+ del T
+
 except ImportError:
 db.DB_THREAD = 0
 
Modified: python/trunk/Lib/bsddb/dbobj.py
==============================================================================
--- python/trunk/Lib/bsddb/dbobj.py	(original)
+++ python/trunk/Lib/bsddb/dbobj.py	Mon Mar 22 15:22:26 2010
@@ -29,7 +29,7 @@
 else :
 import db
 
-if sys.version_info[0:2] <= (2, 5) :
+if sys.version_info < (2, 6) :
 try:
 from UserDict import DictMixin
 except ImportError:
@@ -110,15 +110,17 @@
 def log_stat(self, *args, **kwargs):
 return self._cobj.log_stat(*args, **kwargs)
 
- if db.version() >= (4,1):
- def dbremove(self, *args, **kwargs):
- return self._cobj.dbremove(*args, **kwargs)
- def dbrename(self, *args, **kwargs):
- return self._cobj.dbrename(*args, **kwargs)
- def set_encrypt(self, *args, **kwargs):
- return self._cobj.set_encrypt(*args, **kwargs)
+ def dbremove(self, *args, **kwargs):
+ return self._cobj.dbremove(*args, **kwargs)
+ def dbrename(self, *args, **kwargs):
+ return self._cobj.dbrename(*args, **kwargs)
+ def set_encrypt(self, *args, **kwargs):
+ return self._cobj.set_encrypt(*args, **kwargs)
 
 if db.version() >= (4,4):
+ def fileid_reset(self, *args, **kwargs):
+ return self._cobj.fileid_reset(*args, **kwargs)
+
 def lsn_reset(self, *args, **kwargs):
 return self._cobj.lsn_reset(*args, **kwargs)
 
@@ -138,7 +140,7 @@
 def __delitem__(self, arg):
 del self._cobj[arg]
 
- if sys.version_info[0:2] >= (2, 6) :
+ if sys.version_info >= (2, 6) :
 def __iter__(self) :
 return self._cobj.__iter__()
 
@@ -229,9 +231,8 @@
 def set_get_returns_none(self, *args, **kwargs):
 return self._cobj.set_get_returns_none(*args, **kwargs)
 
- if db.version() >= (4,1):
- def set_encrypt(self, *args, **kwargs):
- return self._cobj.set_encrypt(*args, **kwargs)
+ def set_encrypt(self, *args, **kwargs):
+ return self._cobj.set_encrypt(*args, **kwargs)
 
 
 class DBSequence:
Modified: python/trunk/Lib/bsddb/dbshelve.py
==============================================================================
--- python/trunk/Lib/bsddb/dbshelve.py	(original)
+++ python/trunk/Lib/bsddb/dbshelve.py	Mon Mar 22 15:22:26 2010
@@ -29,9 +29,6 @@
 
 #------------------------------------------------------------------------
 
-import cPickle
-import sys
-
 import sys
 absolute_import = (sys.version_info[0] >= 3)
 if absolute_import :
@@ -40,13 +37,41 @@
 else :
 import db
 
+if sys.version_info[0] >= 3 :
+ import cPickle # Will be converted to "pickle" by "2to3"
+else :
+ if sys.version_info < (2, 6) :
+ import cPickle
+ else :
+ # When we drop support for python 2.3 and 2.4
+ # we could use: (in 2.5 we need a __future__ statement)
+ #
+ # with warnings.catch_warnings():
+ # warnings.filterwarnings(...)
+ # ...
+ #
+ # We can not use "with" as is, because it would be invalid syntax
+ # in python 2.3, 2.4 and (with no __future__) 2.5.
+ # Here we simulate "with" following PEP 343 :
+ import warnings
+ w = warnings.catch_warnings()
+ w.__enter__()
+ try :
+ warnings.filterwarnings('ignore',
+ message='the cPickle module has been removed in Python 3.0',
+ category=DeprecationWarning)
+ import cPickle
+ finally :
+ w.__exit__()
+ del w
+
 #At version 2.3 cPickle switched to using protocol instead of bin
-if sys.version_info[:3] >= (2, 3, 0):
+if sys.version_info >= (2, 3):
 HIGHEST_PROTOCOL = cPickle.HIGHEST_PROTOCOL
 # In python 2.3.*, "cPickle.dumps" accepts no
 # named parameters. "pickle.dumps" accepts them,
 # so this seems a bug.
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4):
 def _dumps(object, protocol):
 return cPickle.dumps(object, protocol)
 else :
@@ -59,11 +84,16 @@
 return cPickle.dumps(object, bin=protocol)
 
 
-try:
- from UserDict import DictMixin
-except ImportError:
- # DictMixin is new in Python 2.3
- class DictMixin: pass
+if sys.version_info < (2, 6) :
+ try:
+ from UserDict import DictMixin
+ except ImportError:
+ # DictMixin is new in Python 2.3
+ class DictMixin: pass
+ MutableMapping = DictMixin
+else :
+ import collections
+ MutableMapping = collections.MutableMapping
 
 #------------------------------------------------------------------------
 
@@ -106,7 +136,7 @@
 class DBShelveError(db.DBError): pass
 
 
-class DBShelf(DictMixin):
+class DBShelf(MutableMapping):
 """A shelf to hold pickled objects, built upon a bsddb DB object. It
 automatically pickles/unpickles data objects going to/from the DB.
 """
@@ -157,6 +187,17 @@
 else:
 return self.db.keys()
 
+ if sys.version_info >= (2, 6) :
+ def __iter__(self) : # XXX: Load all keys in memory :-(
+ for k in self.db.keys() :
+ yield k
+
+ # Do this when "DB" support iteration
+ # Or is it enough to pass thru "getattr"?
+ #
+ # def __iter__(self) :
+ # return self.db.__iter__()
+
 
 def open(self, *args, **kwargs):
 self.db.open(*args, **kwargs)
Modified: python/trunk/Lib/bsddb/dbtables.py
==============================================================================
--- python/trunk/Lib/bsddb/dbtables.py	(original)
+++ python/trunk/Lib/bsddb/dbtables.py	Mon Mar 22 15:22:26 2010
@@ -22,7 +22,35 @@
 import copy
 import random
 import struct
-import cPickle as pickle
+
+
+if sys.version_info[0] >= 3 :
+ import pickle
+else :
+ if sys.version_info < (2, 6) :
+ import cPickle as pickle
+ else :
+ # When we drop support for python 2.3 and 2.4
+ # we could use: (in 2.5 we need a __future__ statement)
+ #
+ # with warnings.catch_warnings():
+ # warnings.filterwarnings(...)
+ # ...
+ #
+ # We can not use "with" as is, because it would be invalid syntax
+ # in python 2.3, 2.4 and (with no __future__) 2.5.
+ # Here we simulate "with" following PEP 343 :
+ import warnings
+ w = warnings.catch_warnings()
+ w.__enter__()
+ try :
+ warnings.filterwarnings('ignore',
+ message='the cPickle module has been removed in Python 3.0',
+ category=DeprecationWarning)
+ import cPickle as pickle
+ finally :
+ w.__exit__()
+ del w
 
 try:
 # For Pythons w/distutils pybsddb
@@ -31,12 +59,6 @@
 # For Python 2.3
 from bsddb import db
 
-# XXX(nnorwitz): is this correct? DBIncompleteError is conditional in _bsddb.c
-if not hasattr(db,"DBIncompleteError") :
- class DBIncompleteError(Exception):
- pass
- db.DBIncompleteError = DBIncompleteError
-
 class TableDBError(StandardError):
 pass
 class TableAlreadyExists(TableDBError):
@@ -261,16 +283,10 @@
 self.env = None
 
 def checkpoint(self, mins=0):
- try:
- self.env.txn_checkpoint(mins)
- except db.DBIncompleteError:
- pass
+ self.env.txn_checkpoint(mins)
 
 def sync(self):
- try:
- self.db.sync()
- except db.DBIncompleteError:
- pass
+ self.db.sync()
 
 def _db_print(self) :
 """Print the database to stdout for debugging"""
@@ -659,6 +675,13 @@
 a = atuple[1]
 b = btuple[1]
 if type(a) is type(b):
+
+ # Needed for python 3. "cmp" vanished in 3.0.1
+ def cmp(a, b) :
+ if a==b : return 0
+ if a<b : return -1
+ return 1
+
 if isinstance(a, PrefixCond) and isinstance(b, PrefixCond):
 # longest prefix first
 return cmp(len(b.prefix), len(a.prefix))
Modified: python/trunk/Lib/bsddb/test/test_all.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_all.py	(original)
+++ python/trunk/Lib/bsddb/test/test_all.py	Mon Mar 22 15:22:26 2010
@@ -15,6 +15,51 @@
 if sys.version_info[0] >= 3 :
 charset = "iso8859-1" # Full 8 bit
 
+ class logcursor_py3k(object) :
+ def __init__(self, env) :
+ self._logcursor = env.log_cursor()
+
+ def __getattr__(self, v) :
+ return getattr(self._logcursor, v)
+
+ def __next__(self) :
+ v = getattr(self._logcursor, "next")()
+ if v is not None :
+ v = (v[0], v[1].decode(charset))
+ return v
+
+ next = __next__
+
+ def first(self) :
+ v = self._logcursor.first()
+ if v is not None :
+ v = (v[0], v[1].decode(charset))
+ return v
+
+ def last(self) :
+ v = self._logcursor.last()
+ if v is not None :
+ v = (v[0], v[1].decode(charset))
+ return v
+
+ def prev(self) :
+ v = self._logcursor.prev()
+ if v is not None :
+ v = (v[0], v[1].decode(charset))
+ return v
+
+ def current(self) :
+ v = self._logcursor.current()
+ if v is not None :
+ v = (v[0], v[1].decode(charset))
+ return v
+
+ def set(self, lsn) :
+ v = self._logcursor.set(lsn)
+ if v is not None :
+ v = (v[0], v[1].decode(charset))
+ return v
+
 class cursor_py3k(object) :
 def __init__(self, db, *args, **kwargs) :
 self._dbcursor = db.cursor(*args, **kwargs)
@@ -71,12 +116,12 @@
 v = self._dbcursor.next_nodup()
 return self._fix(v)
 
- def put(self, key, value, flags=0, dlen=-1, doff=-1) :
+ def put(self, key, data, flags=0, dlen=-1, doff=-1) :
 if isinstance(key, str) :
 key = bytes(key, charset)
- if isinstance(value, str) :
- value = bytes(value, charset)
- return self._dbcursor.put(key, value, flags=flags, dlen=dlen,
+ if isinstance(data, str) :
+ value = bytes(data, charset)
+ return self._dbcursor.put(key, data, flags=flags, dlen=dlen,
 doff=doff)
 
 def current(self, flags=0, dlen=-1, doff=-1) :
@@ -203,12 +248,26 @@
 k = bytes(k, charset)
 return self._db.has_key(k, txn=txn)
 
- def put(self, key, value, txn=None, flags=0, dlen=-1, doff=-1) :
+ def set_re_delim(self, c) :
+ if isinstance(c, str) : # We can use a numeric value byte too
+ c = bytes(c, charset)
+ return self._db.set_re_delim(c)
+
+ def set_re_pad(self, c) :
+ if isinstance(c, str) : # We can use a numeric value byte too
+ c = bytes(c, charset)
+ return self._db.set_re_pad(c)
+
+ def get_re_source(self) :
+ source = self._db.get_re_source()
+ return source.decode(charset)
+
+ def put(self, key, data, txn=None, flags=0, dlen=-1, doff=-1) :
 if isinstance(key, str) :
 key = bytes(key, charset)
- if isinstance(value, str) :
- value = bytes(value, charset)
- return self._db.put(key, value, flags=flags, txn=txn, dlen=dlen,
+ if isinstance(data, str) :
+ value = bytes(data, charset)
+ return self._db.put(key, data, flags=flags, txn=txn, dlen=dlen,
 doff=doff)
 
 def append(self, value, txn=None) :
@@ -221,6 +280,11 @@
 key = bytes(key, charset)
 return self._db.get_size(key)
 
+ def exists(self, key, *args, **kwargs) :
+ if isinstance(key, str) :
+ key = bytes(key, charset)
+ return self._db.exists(key, *args, **kwargs)
+
 def get(self, key, default="MagicCookie", txn=None, flags=0, dlen=-1, doff=-1) :
 if isinstance(key, str) :
 key = bytes(key, charset)
@@ -288,13 +352,21 @@
 key = key.decode(charset)
 data = data.decode(charset)
 key = self._callback(key, data)
- if (key != bsddb._db.DB_DONOTINDEX) and isinstance(key,
- str) :
- key = bytes(key, charset)
+ if (key != bsddb._db.DB_DONOTINDEX) :
+ if isinstance(key, str) :
+ key = bytes(key, charset)
+ elif isinstance(key, list) :
+ key2 = []
+ for i in key :
+ if isinstance(i, str) :
+ i = bytes(i, charset)
+ key2.append(i)
+ key = key2
 return key
 
 return self._db.associate(secondarydb._db,
- associate_callback(callback).callback, flags=flags, txn=txn)
+ associate_callback(callback).callback, flags=flags,
+ txn=txn)
 
 def cursor(self, txn=None, flags=0) :
 return cursor_py3k(self._db, txn=txn, flags=flags)
@@ -310,6 +382,21 @@
 def __getattr__(self, v) :
 return getattr(self._dbenv, v)
 
+ def log_cursor(self, flags=0) :
+ return logcursor_py3k(self._dbenv)
+
+ def get_lg_dir(self) :
+ return self._dbenv.get_lg_dir().decode(charset)
+
+ def get_tmp_dir(self) :
+ return self._dbenv.get_tmp_dir().decode(charset)
+
+ def get_data_dirs(self) :
+ # Have to use a list comprehension and not
+ # generators, because we are supporting Python 2.3.
+ return tuple(
+ [i.decode(charset) for i in self._dbenv.get_data_dirs()])
+
 class DBSequence_py3k(object) :
 def __init__(self, db, *args, **kwargs) :
 self._db=db
@@ -332,7 +419,10 @@
 
 bsddb._db.DBEnv_orig = bsddb._db.DBEnv
 bsddb._db.DB_orig = bsddb._db.DB
- bsddb._db.DBSequence_orig = bsddb._db.DBSequence
+ if bsddb.db.version() <= (4, 3) :
+ bsddb._db.DBSequence_orig = None
+ else :
+ bsddb._db.DBSequence_orig = bsddb._db.DBSequence
 
 def do_proxy_db_py3k(flag) :
 flag2 = do_proxy_db_py3k.flag
@@ -396,8 +486,12 @@
 print 'bsddb.db.version(): %s' % (db.version(), )
 print 'bsddb.db.__version__: %s' % db.__version__
 print 'bsddb.db.cvsid: %s' % db.cvsid
- print 'py module: %s' % bsddb.__file__
- print 'extension module: %s' % bsddb._bsddb.__file__
+
+ # Workaround for allowing generating an EGGs as a ZIP files.
+ suffix="__"
+ print 'py module: %s' % getattr(bsddb, "__file"+suffix)
+ print 'extension module: %s' % getattr(bsddb, "__file"+suffix)
+
 print 'python version: %s' % sys.version
 print 'My pid: %s' % os.getpid()
 print '-=' * 38
@@ -481,6 +575,8 @@
 test_modules = [
 'test_associate',
 'test_basics',
+ 'test_dbenv',
+ 'test_db',
 'test_compare',
 'test_compat',
 'test_cursor_pget_bug',
@@ -489,6 +585,7 @@
 'test_dbtables',
 'test_distributed_transactions',
 'test_early_close',
+ 'test_fileid',
 'test_get_none',
 'test_join',
 'test_lock',
Modified: python/trunk/Lib/bsddb/test/test_associate.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_associate.py	(original)
+++ python/trunk/Lib/bsddb/test/test_associate.py	Mon Mar 22 15:22:26 2010
@@ -148,12 +148,8 @@
 self.secDB = None
 self.primary = db.DB(self.env)
 self.primary.set_get_returns_none(2)
- if db.version() >= (4, 1):
- self.primary.open(self.filename, "primary", self.dbtype,
- db.DB_CREATE | db.DB_THREAD | self.dbFlags, txn=txn)
- else:
- self.primary.open(self.filename, "primary", self.dbtype,
- db.DB_CREATE | db.DB_THREAD | self.dbFlags)
+ self.primary.open(self.filename, "primary", self.dbtype,
+ db.DB_CREATE | db.DB_THREAD | self.dbFlags, txn=txn)
 
 def closeDB(self):
 if self.cur:
@@ -169,12 +165,7 @@
 return self.primary
 
 
- def test01_associateWithDB(self):
- if verbose:
- print '\n', '-=' * 30
- print "Running %s.test01_associateWithDB..." % \
- self.__class__.__name__
-
+ def _associateWithDB(self, getGenre):
 self.createDB()
 
 self.secDB = db.DB(self.env)
@@ -182,19 +173,21 @@
 self.secDB.set_get_returns_none(2)
 self.secDB.open(self.filename, "secondary", db.DB_BTREE,
 db.DB_CREATE | db.DB_THREAD | self.dbFlags)
- self.getDB().associate(self.secDB, self.getGenre)
+ self.getDB().associate(self.secDB, getGenre)
 
 self.addDataToDB(self.getDB())
 
 self.finish_test(self.secDB)
 
-
- def test02_associateAfterDB(self):
+ def test01_associateWithDB(self):
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test02_associateAfterDB..." % \
+ print "Running %s.test01_associateWithDB..." % \
 self.__class__.__name__
 
+ return self._associateWithDB(self.getGenre)
+
+ def _associateAfterDB(self, getGenre) :
 self.createDB()
 self.addDataToDB(self.getDB())
 
@@ -204,10 +197,35 @@
 db.DB_CREATE | db.DB_THREAD | self.dbFlags)
 
 # adding the DB_CREATE flag will cause it to index existing records
- self.getDB().associate(self.secDB, self.getGenre, db.DB_CREATE)
+ self.getDB().associate(self.secDB, getGenre, db.DB_CREATE)
 
 self.finish_test(self.secDB)
 
+ def test02_associateAfterDB(self):
+ if verbose:
+ print '\n', '-=' * 30
+ print "Running %s.test02_associateAfterDB..." % \
+ self.__class__.__name__
+
+ return self._associateAfterDB(self.getGenre)
+
+ if db.version() >= (4, 6):
+ def test03_associateWithDB(self):
+ if verbose:
+ print '\n', '-=' * 30
+ print "Running %s.test03_associateWithDB..." % \
+ self.__class__.__name__
+
+ return self._associateWithDB(self.getGenreList)
+
+ def test04_associateAfterDB(self):
+ if verbose:
+ print '\n', '-=' * 30
+ print "Running %s.test04_associateAfterDB..." % \
+ self.__class__.__name__
+
+ return self._associateAfterDB(self.getGenreList)
+
 
 def finish_test(self, secDB, txn=None):
 # 'Blues' should not be in the secondary database
@@ -277,6 +295,12 @@
 else:
 return genre
 
+ def getGenreList(self, priKey, PriData) :
+ v = self.getGenre(priKey, PriData)
+ if type(v) == type("") :
+ v = [v]
+ return v
+
 
 #----------------------------------------------------------------------
 
@@ -322,10 +346,7 @@
 self.secDB.set_get_returns_none(2)
 self.secDB.open(self.filename, "secondary", db.DB_BTREE,
 db.DB_CREATE | db.DB_THREAD, txn=txn)
- if db.version() >= (4,1):
- self.getDB().associate(self.secDB, self.getGenre, txn=txn)
- else:
- self.getDB().associate(self.secDB, self.getGenre)
+ self.getDB().associate(self.secDB, self.getGenre, txn=txn)
 
 self.addDataToDB(self.getDB(), txn=txn)
 except:
@@ -426,8 +447,7 @@
 suite.addTest(unittest.makeSuite(AssociateBTreeTestCase))
 suite.addTest(unittest.makeSuite(AssociateRecnoTestCase))
 
- if db.version() >= (4, 1):
- suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase))
+ suite.addTest(unittest.makeSuite(AssociateBTreeTxnTestCase))
 
 suite.addTest(unittest.makeSuite(ShelveAssociateHashTestCase))
 suite.addTest(unittest.makeSuite(ShelveAssociateBTreeTestCase))
Modified: python/trunk/Lib/bsddb/test/test_basics.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_basics.py	(original)
+++ python/trunk/Lib/bsddb/test/test_basics.py	Mon Mar 22 15:22:26 2010
@@ -33,6 +33,7 @@
 
 class BasicTestCase(unittest.TestCase):
 dbtype = db.DB_UNKNOWN # must be set in derived class
+ cachesize = (0, 1024*1024, 1)
 dbopenflags = 0
 dbsetflags = 0
 dbmode = 0660
@@ -43,6 +44,13 @@
 
 _numKeys = 1002 # PRIVATE. NOTE: must be an even value
 
+ import sys
+ if sys.version_info < (2, 4):
+ def assertTrue(self, expr, msg=None):
+ self.failUnless(expr,msg=msg)
+ def assertFalse(self, expr, msg=None):
+ self.failIf(expr,msg=msg)
+
 def setUp(self):
 if self.useEnv:
 self.homeDir=get_new_environment_path()
@@ -50,7 +58,8 @@
 self.env = db.DBEnv()
 self.env.set_lg_max(1024*1024)
 self.env.set_tx_max(30)
- self.env.set_tx_timestamp(int(time.time()))
+ self._t = int(time.time())
+ self.env.set_tx_timestamp(self._t)
 self.env.set_flags(self.envsetflags, 1)
 self.env.open(self.homeDir, self.envflags | db.DB_CREATE)
 self.filename = "test"
@@ -64,6 +73,15 @@
 
 # create and open the DB
 self.d = db.DB(self.env)
+ if not self.useEnv :
+ if db.version() >= (4, 2) :
+ self.d.set_cachesize(*self.cachesize)
+ cachesize = self.d.get_cachesize()
+ self.assertEqual(cachesize[0], self.cachesize[0])
+ self.assertEqual(cachesize[2], self.cachesize[2])
+ # Berkeley DB expands the cache 25% accounting overhead,
+ # if the cache is small.
+ self.assertEqual(125, int(100.0*cachesize[1]/self.cachesize[1]))
 self.d.set_flags(self.dbsetflags)
 if self.dbname:
 self.d.open(self.filename, self.dbname, self.dbtype,
@@ -74,6 +92,10 @@
 dbtype = self.dbtype,
 flags = self.dbopenflags|db.DB_CREATE)
 
+ if not self.useEnv:
+ self.assertRaises(db.DBInvalidArgError,
+ self.d.set_cachesize, *self.cachesize)
+
 self.populateDB()
 
 
@@ -139,7 +161,11 @@
 try:
 d.delete('abcd')
 except db.DBNotFoundError, val:
- self.assertEqual(val.args[0], db.DB_NOTFOUND)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_NOTFOUND)
+ else :
+ self.assertEqual(val.args[0], db.DB_NOTFOUND)
 if verbose: print val
 else:
 self.fail("expected exception")
@@ -158,7 +184,11 @@
 try:
 d.put('abcd', 'this should fail', flags=db.DB_NOOVERWRITE)
 except db.DBKeyExistError, val:
- self.assertEqual(val.args[0], db.DB_KEYEXIST)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_KEYEXIST)
+ else :
+ self.assertEqual(val.args[0], db.DB_KEYEXIST)
 if verbose: print val
 else:
 self.fail("expected exception")
@@ -268,6 +298,21 @@
 pprint(values[:10])
 
 
+ #----------------------------------------
+
+ def test02b_SequenceMethods(self):
+ d = self.d
+
+ for key in ['0002', '0101', '0401', '0701', '0998']:
+ data = d[key]
+ self.assertEqual(data, self.makeData(key))
+ if verbose:
+ print data
+
+ self.assertTrue(hasattr(d, "__contains__"))
+ self.assertTrue("0401" in d)
+ self.assertFalse("1234" in d)
+
 
 #----------------------------------------
 
@@ -293,7 +338,11 @@
 rec = c.next()
 except db.DBNotFoundError, val:
 if get_raises_error:
- self.assertEqual(val.args[0], db.DB_NOTFOUND)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_NOTFOUND)
+ else :
+ self.assertEqual(val.args[0], db.DB_NOTFOUND)
 if verbose: print val
 rec = None
 else:
@@ -314,7 +363,11 @@
 rec = c.prev()
 except db.DBNotFoundError, val:
 if get_raises_error:
- self.assertEqual(val.args[0], db.DB_NOTFOUND)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_NOTFOUND)
+ else :
+ self.assertEqual(val.args[0], db.DB_NOTFOUND)
 if verbose: print val
 rec = None
 else:
@@ -337,7 +390,11 @@
 try:
 n = c.set('bad key')
 except db.DBNotFoundError, val:
- self.assertEqual(val.args[0], db.DB_NOTFOUND)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_NOTFOUND)
+ else :
+ self.assertEqual(val.args[0], db.DB_NOTFOUND)
 if verbose: print val
 else:
 if set_raises_error:
@@ -351,7 +408,11 @@
 try:
 n = c.get_both('0404', 'bad data')
 except db.DBNotFoundError, val:
- self.assertEqual(val.args[0], db.DB_NOTFOUND)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_NOTFOUND)
+ else :
+ self.assertEqual(val.args[0], db.DB_NOTFOUND)
 if verbose: print val
 else:
 if get_raises_error:
@@ -380,7 +441,11 @@
 rec = c.current()
 except db.DBKeyEmptyError, val:
 if get_raises_error:
- self.assertEqual(val.args[0], db.DB_KEYEMPTY)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_KEYEMPTY)
+ else :
+ self.assertEqual(val.args[0], db.DB_KEYEMPTY)
 if verbose: print val
 else:
 self.fail("unexpected DBKeyEmptyError")
@@ -425,7 +490,11 @@
 # a bug may cause a NULL pointer dereference...
 getattr(c, method)(*args)
 except db.DBError, val:
- self.assertEqual(val.args[0], 0)
+ import sys
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], 0)
+ else :
+ self.assertEqual(val.args[0], 0)
 if verbose: print val
 else:
 self.fail("no exception raised when using a buggy cursor's"
@@ -477,6 +546,15 @@
 self.assertEqual(old, 1)
 self.test03_SimpleCursorStuff(get_raises_error=0, set_raises_error=0)
 
+ if db.version() >= (4, 6):
+ def test03d_SimpleCursorPriority(self) :
+ c = self.d.cursor()
+ c.set_priority(db.DB_PRIORITY_VERY_LOW) # Positional
+ self.assertEqual(db.DB_PRIORITY_VERY_LOW, c.get_priority())
+ c.set_priority(priority=db.DB_PRIORITY_HIGH) # Keyword
+ self.assertEqual(db.DB_PRIORITY_HIGH, c.get_priority())
+ c.close()
+
 #----------------------------------------
 
 def test04_PartialGetAndPut(self):
@@ -530,7 +608,7 @@
 d = self.d
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test99_Truncate..." % self.__class__.__name__
+ print "Running %s.test06_Truncate..." % self.__class__.__name__
 
 d.put("abcde", "ABCDE");
 num = d.truncate()
@@ -550,6 +628,33 @@
 
 #----------------------------------------
 
+ if db.version() >= (4, 6):
+ def test08_exists(self) :
+ self.d.put("abcde", "ABCDE")
+ self.assert_(self.d.exists("abcde") == True,
+ "DB->exists() returns wrong value")
+ self.assert_(self.d.exists("x") == False,
+ "DB->exists() returns wrong value")
+
+ #----------------------------------------
+
+ if db.version() >= (4, 7):
+ def test_compact(self) :
+ d = self.d
+ self.assertEqual(0, d.compact(flags=db.DB_FREELIST_ONLY))
+ self.assertEqual(0, d.compact(flags=db.DB_FREELIST_ONLY))
+ d.put("abcde", "ABCDE");
+ d.put("bcde", "BCDE");
+ d.put("abc", "ABC");
+ d.put("monty", "python");
+ d.delete("abc")
+ d.delete("bcde")
+ d.compact(start='abcde', stop='monty', txn=None,
+ compact_fillpercent=42, compact_pages=1,
+ compact_timeout=50000000,
+ flags=db.DB_FREELIST_ONLY|db.DB_FREE_SPACE)
+
+ #----------------------------------------
 
 #----------------------------------------------------------------------
 
@@ -579,13 +684,13 @@
 
 #----------------------------------------
 
- def test08_EnvRemoveAndRename(self):
+ def test09_EnvRemoveAndRename(self):
 if not self.env:
 return
 
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test08_EnvRemoveAndRename..." % self.__class__.__name__
+ print "Running %s.test09_EnvRemoveAndRename..." % self.__class__.__name__
 
 # can't rename or remove an open DB
 self.d.close()
@@ -594,10 +699,6 @@
 self.env.dbrename(self.filename, None, newname)
 self.env.dbremove(newname)
 
- # dbremove and dbrename are in 4.1 and later
- if db.version() < (4,1):
- del test08_EnvRemoveAndRename
-
 #----------------------------------------
 
 class BasicBTreeWithEnvTestCase(BasicWithEnvTestCase):
@@ -612,9 +713,14 @@
 
 class BasicTransactionTestCase(BasicTestCase):
 import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4):
 def assertTrue(self, expr, msg=None):
- self.failUnless(expr,msg=msg)
+ return self.failUnless(expr,msg=msg)
+
+ if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and
+ (sys.version_info < (3, 2))) :
+ def assertIn(self, a, b, msg=None) :
+ return self.assertTrue(a in b, msg=msg)
 
 dbopenflags = db.DB_THREAD | db.DB_AUTO_COMMIT
 useEnv = 1
@@ -672,10 +778,7 @@
 self.txn.commit()
 
 # flush pending updates
- try:
- self.env.txn_checkpoint (0, 0, 0)
- except db.DBIncompleteError:
- pass
+ self.env.txn_checkpoint (0, 0, 0)
 
 statDict = self.env.log_stat(0);
 self.assertIn('magic', statDict)
@@ -697,11 +800,25 @@
 
 #----------------------------------------
 
- def test08_TxnTruncate(self):
+ if db.version() >= (4, 6):
+ def test08_exists(self) :
+ txn = self.env.txn_begin()
+ self.d.put("abcde", "ABCDE", txn=txn)
+ txn.commit()
+ txn = self.env.txn_begin()
+ self.assert_(self.d.exists("abcde", txn=txn) == True,
+ "DB->exists() returns wrong value")
+ self.assert_(self.d.exists("x", txn=txn) == False,
+ "DB->exists() returns wrong value")
+ txn.abort()
+
+ #----------------------------------------
+
+ def test09_TxnTruncate(self):
 d = self.d
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test08_TxnTruncate..." % self.__class__.__name__
+ print "Running %s.test09_TxnTruncate..." % self.__class__.__name__
 
 d.put("abcde", "ABCDE");
 txn = self.env.txn_begin()
@@ -714,7 +831,7 @@
 
 #----------------------------------------
 
- def test09_TxnLateUse(self):
+ def test10_TxnLateUse(self):
 txn = self.env.txn_begin()
 txn.abort()
 try:
@@ -734,6 +851,39 @@
 raise RuntimeError, "DBTxn.commit() called after DB_TXN no longer valid w/o an exception"
 
 
+ #----------------------------------------
+
+
+ if db.version() >= (4, 4):
+ def test_txn_name(self) :
+ txn=self.env.txn_begin()
+ self.assertEqual(txn.get_name(), "")
+ txn.set_name("XXYY")
+ self.assertEqual(txn.get_name(), "XXYY")
+ txn.set_name("")
+ self.assertEqual(txn.get_name(), "")
+ txn.abort()
+
+ #----------------------------------------
+
+
+ def test_txn_set_timeout(self) :
+ txn=self.env.txn_begin()
+ txn.set_timeout(1234567, db.DB_SET_LOCK_TIMEOUT)
+ txn.set_timeout(2345678, flags=db.DB_SET_TXN_TIMEOUT)
+ txn.abort()
+
+ #----------------------------------------
+
+ if db.version() >= (4, 2) :
+ def test_get_tx_max(self) :
+ self.assertEqual(self.env.get_tx_max(), 30)
+
+ def test_get_tx_timestamp(self) :
+ self.assertEqual(self.env.get_tx_timestamp(), self._t)
+
+
+
 class BTreeTransactionTestCase(BasicTransactionTestCase):
 dbtype = db.DB_BTREE
 
@@ -748,11 +898,11 @@
 dbtype = db.DB_BTREE
 dbsetflags = db.DB_RECNUM
 
- def test08_RecnoInBTree(self):
+ def test09_RecnoInBTree(self):
 d = self.d
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test08_RecnoInBTree..." % self.__class__.__name__
+ print "Running %s.test09_RecnoInBTree..." % self.__class__.__name__
 
 rec = d.get(200)
 self.assertEqual(type(rec), type(()))
@@ -782,11 +932,11 @@
 class BasicDUPTestCase(BasicTestCase):
 dbsetflags = db.DB_DUP
 
- def test09_DuplicateKeys(self):
+ def test10_DuplicateKeys(self):
 d = self.d
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test09_DuplicateKeys..." % \
+ print "Running %s.test10_DuplicateKeys..." % \
 self.__class__.__name__
 
 d.put("dup0", "before")
@@ -855,11 +1005,11 @@
 else:
 return db.DB_BTREE
 
- def test10_MultiDB(self):
+ def test11_MultiDB(self):
 d1 = self.d
 if verbose:
 print '\n', '-=' * 30
- print "Running %s.test10_MultiDB..." % self.__class__.__name__
+ print "Running %s.test11_MultiDB..." % self.__class__.__name__
 
 d2 = db.DB(self.env)
 d2.open(self.filename, "second", self.dbtype,
@@ -949,7 +1099,7 @@
 
 class PrivateObject(unittest.TestCase) :
 import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4):
 def assertTrue(self, expr, msg=None):
 self.failUnless(expr,msg=msg)
 
@@ -992,7 +1142,7 @@
 
 class CrashAndBurn(unittest.TestCase) :
 import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4):
 def assertTrue(self, expr, msg=None):
 self.failUnless(expr,msg=msg)
 
Modified: python/trunk/Lib/bsddb/test/test_compare.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_compare.py	(original)
+++ python/trunk/Lib/bsddb/test/test_compare.py	Mon Mar 22 15:22:26 2010
@@ -12,6 +12,12 @@
 get_new_environment_path, get_new_database_path
 
 
+# Needed for python 3. "cmp" vanished in 3.0.1
+def cmp(a, b) :
+ if a==b : return 0
+ if a<b : return -1
+ return 1
+
 lexical_cmp = cmp
 
 def lowercase_cmp(left, right):
@@ -26,12 +32,16 @@
 _expected_lowercase_test_data = ['', 'a', 'aaa', 'b', 'c', 'CC', 'cccce', 'ccccf', 'CCCP']
 
 class ComparatorTests (unittest.TestCase):
+ if sys.version_info < (2, 4) :
+ def assertTrue(self, expr, msg=None) :
+ return self.failUnless(expr,msg=msg)
+
 def comparator_test_helper (self, comparator, expected_data):
 data = expected_data[:]
 
 import sys
- if sys.version_info[:3] < (2, 6, 0):
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 6) :
+ if sys.version_info < (2, 4) :
 data.sort(comparator)
 else :
 data.sort(cmp=comparator)
@@ -47,7 +57,7 @@
 data2.append(i)
 data = data2
 
- self.assertEqual (data, expected_data,
+ self.assertEqual(data, expected_data,
 "comparator `%s' is not right: %s vs. %s"
 % (comparator, expected_data, data))
 def test_lexical_comparator (self):
@@ -65,6 +75,15 @@
 env = None
 db = None
 
+ if sys.version_info < (2, 4) :
+ def assertTrue(self, expr, msg=None):
+ self.failUnless(expr,msg=msg)
+
+ if (sys.version_info < (2, 7)) or ((sys.version_info >= (3,0)) and
+ (sys.version_info < (3, 2))) :
+ def assertLess(self, a, b, msg=None) :
+ return self.assertTrue(a<b, msg=msg)
+
 def setUp (self):
 self.filename = self.__class__.__name__ + '.db'
 self.homeDir = get_new_environment_path()
@@ -115,14 +134,14 @@
 rec = curs.first ()
 while rec:
 key, ignore = rec
- self.assertLess (index, len (expected),
+ self.assertLess(index, len (expected),
 "to many values returned from cursor")
- self.assertEqual (expected[index], key,
+ self.assertEqual(expected[index], key,
 "expected value `%s' at %d but got `%s'"
 % (expected[index], index, key))
 index = index + 1
 rec = curs.next ()
- self.assertEqual (index, len (expected),
+ self.assertEqual(index, len (expected),
 "not enough values returned from cursor")
 finally:
 curs.close ()
@@ -193,7 +212,8 @@
 errorOut = temp.getvalue()
 if not successRe.search(errorOut):
 self.fail("unexpected stderr output:\n"+errorOut)
- sys.exc_traceback = sys.last_traceback = None
+ if sys.version_info < (3, 0) : # XXX: How to do this in Py3k ???
+ sys.exc_traceback = sys.last_traceback = None
 
 def _test_compare_function_exception (self):
 self.startTest ()
@@ -237,8 +257,8 @@
 def my_compare (a, b):
 return 0
 
- self.startTest ()
- self.createDB (my_compare)
+ self.startTest()
+ self.createDB(my_compare)
 self.assertRaises (RuntimeError, self.db.set_bt_compare, my_compare)
 
 def test_suite ():
Modified: python/trunk/Lib/bsddb/test/test_dbshelve.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_dbshelve.py	(original)
+++ python/trunk/Lib/bsddb/test/test_dbshelve.py	Mon Mar 22 15:22:26 2010
@@ -2,10 +2,9 @@
 TestCases for checking dbShelve objects.
 """
 
-import os, string
+import os, string, sys
 import random
 import unittest
-import warnings
 
 
 from test_all import db, dbshelve, test_support, verbose, \
@@ -13,6 +12,11 @@
 
 
 
+if sys.version_info < (2, 4) :
+ from sets import Set as set
+
+
+
 #----------------------------------------------------------------------
 
 # We want the objects to be comparable so we can test dbshelve.values
@@ -29,8 +33,17 @@
 
 
 class DBShelveTestCase(unittest.TestCase):
+ if sys.version_info < (2, 4):
+ def assertTrue(self, expr, msg=None):
+ return self.failUnless(expr,msg=msg)
+
+ if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and
+ (sys.version_info < (3, 2))) :
+ def assertIn(self, a, b, msg=None) :
+ return self.assertTrue(a in b, msg=msg)
+
+
 def setUp(self):
- import sys
 if sys.version_info[0] >= 3 :
 from test_all import do_proxy_db_py3k
 self._flag_proxy_db_py3k = do_proxy_db_py3k(False)
@@ -38,7 +51,6 @@
 self.do_open()
 
 def tearDown(self):
- import sys
 if sys.version_info[0] >= 3 :
 from test_all import do_proxy_db_py3k
 do_proxy_db_py3k(self._flag_proxy_db_py3k)
@@ -48,7 +60,6 @@
 def mk(self, key):
 """Turn key into an appropriate key type for this db"""
 # override in child class for RECNO
- import sys
 if sys.version_info[0] < 3 :
 return key
 else :
@@ -118,11 +129,14 @@
 
 dbvalues = d.values()
 self.assertEqual(len(dbvalues), len(d.keys()))
- with warnings.catch_warnings():
- warnings.filterwarnings('ignore',
- 'comparing unequal types not supported',
- DeprecationWarning)
- self.assertEqual(sorted(values), sorted(dbvalues))
+ if sys.version_info < (2, 6) :
+ values.sort()
+ dbvalues.sort()
+ self.assertEqual(values, dbvalues)
+ else : # XXX: Convert all to strings. Please, improve
+ values.sort(key=lambda x : str(x))
+ dbvalues.sort(key=lambda x : str(x))
+ self.assertEqual(repr(values), repr(dbvalues))
 
 items = d.items()
 self.assertEqual(len(items), len(values))
@@ -197,10 +211,21 @@
 self.d.append, 'unit test was here')
 
 
+ def test04_iterable(self) :
+ self.populateDB(self.d)
+ d = self.d
+ keys = d.keys()
+ keyset = set(keys)
+ self.assertEqual(len(keyset), len(keys))
+
+ for key in d :
+ self.assertIn(key, keyset)
+ keyset.remove(key)
+ self.assertEqual(len(keyset), 0)
+
 def checkrec(self, key, value):
 # override this in a subclass if the key type is different
 
- import sys
 if sys.version_info[0] >= 3 :
 if isinstance(key, bytes) :
 key = key.decode("iso8859-1") # 8 bits
@@ -219,7 +244,6 @@
 self.assertEqual(value, [x] * 10)
 
 elif key[0] == 'O':
- import sys
 if sys.version_info[0] < 3 :
 from types import InstanceType
 self.assertEqual(type(value), InstanceType)
@@ -287,7 +311,6 @@
 DBShelveTestCase.setUp(self)
 
 def tearDown(self):
- import sys
 if sys.version_info[0] >= 3 :
 from test_all import do_proxy_db_py3k
 do_proxy_db_py3k(self._flag_proxy_db_py3k)
Modified: python/trunk/Lib/bsddb/test/test_dbtables.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_dbtables.py	(original)
+++ python/trunk/Lib/bsddb/test/test_dbtables.py	Mon Mar 22 15:22:26 2010
@@ -20,11 +20,15 @@
 #
 # $Id$
 
-import os, re
-try:
- import cPickle
- pickle = cPickle
-except ImportError:
+import os, re, sys
+
+if sys.version_info[0] < 3 :
+ try:
+ import cPickle
+ pickle = cPickle
+ except ImportError:
+ import pickle
+else :
 import pickle
 
 import unittest
Modified: python/trunk/Lib/bsddb/test/test_distributed_transactions.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_distributed_transactions.py	(original)
+++ python/trunk/Lib/bsddb/test/test_distributed_transactions.py	Mon Mar 22 15:22:26 2010
@@ -37,7 +37,7 @@
 self.db = db.DB(self.dbenv)
 self.db.set_re_len(db.DB_GID_SIZE)
 if must_open_db :
- if db.version() > (4,1) :
+ if db.version() >= (4,2) :
 txn=self.dbenv.txn_begin()
 self.db.open(self.filename,
 db.DB_QUEUE, db.DB_CREATE | db.DB_THREAD, 0666,
Modified: python/trunk/Lib/bsddb/test/test_early_close.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_early_close.py	(original)
+++ python/trunk/Lib/bsddb/test/test_early_close.py	Mon Mar 22 15:22:26 2010
@@ -2,7 +2,7 @@
 is closed before its DB objects.
 """
 
-import os
+import os, sys
 import unittest
 
 from test_all import db, test_support, verbose, get_new_environment_path, get_new_database_path
@@ -155,22 +155,43 @@
 db.DB_INIT_LOG | db.DB_CREATE)
 d = db.DB(dbenv)
 txn = dbenv.txn_begin()
- if db.version() < (4,1) :
- d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE)
- else :
- d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE,
- txn=txn)
+ d.open(self.filename, dbtype = db.DB_HASH, flags = db.DB_CREATE,
+ txn=txn)
 d.put("XXX", "yyy", txn=txn)
 txn.commit()
 txn = dbenv.txn_begin()
 c1 = d.cursor(txn)
 c2 = c1.dup()
 self.assertEquals(("XXX", "yyy"), c1.first())
- import warnings
+
 # Not interested in warnings about implicit close.
- with warnings.catch_warnings():
+ import warnings
+ if sys.version_info < (2, 6) :
+ # Completely resetting the warning state is
+ # problematic with python >=2.6 with -3 (py3k warning),
+ # because some stdlib modules selectively ignores warnings.
 warnings.simplefilter("ignore")
 txn.commit()
+ warnings.resetwarnings()
+ else :
+ # When we drop support for python 2.3 and 2.4
+ # we could use: (in 2.5 we need a __future__ statement)
+ #
+ # with warnings.catch_warnings():
+ # warnings.simplefilter("ignore")
+ # txn.commit()
+ #
+ # We can not use "with" as is, because it would be invalid syntax
+ # in python 2.3, 2.4 and (with no __future__) 2.5.
+ # Here we simulate "with" following PEP 343 :
+ w = warnings.catch_warnings()
+ w.__enter__()
+ try :
+ warnings.simplefilter("ignore")
+ txn.commit()
+ finally :
+ w.__exit__()
+
 self.assertRaises(db.DBCursorClosedError, c2.first)
 
 if db.version() > (4,3,0) :
Modified: python/trunk/Lib/bsddb/test/test_lock.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_lock.py	(original)
+++ python/trunk/Lib/bsddb/test/test_lock.py	Mon Mar 22 15:22:26 2010
@@ -20,7 +20,7 @@
 
 class LockingTestCase(unittest.TestCase):
 import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4) :
 def assertTrue(self, expr, msg=None):
 self.failUnless(expr,msg=msg)
 
@@ -89,7 +89,18 @@
 for t in threads:
 t.join()
 
- def test03_lock_timeout(self):
+ if db.version() >= (4, 2) :
+ def test03_lock_timeout(self):
+ self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT)
+ self.assertEqual(self.env.get_timeout(db.DB_SET_LOCK_TIMEOUT), 0)
+ self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT)
+ self.assertEqual(self.env.get_timeout(db.DB_SET_TXN_TIMEOUT), 0)
+ self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT)
+ self.assertEqual(self.env.get_timeout(db.DB_SET_LOCK_TIMEOUT), 123456)
+ self.env.set_timeout(7890123, db.DB_SET_TXN_TIMEOUT)
+ self.assertEqual(self.env.get_timeout(db.DB_SET_TXN_TIMEOUT), 7890123)
+
+ def test04_lock_timeout2(self):
 self.env.set_timeout(0, db.DB_SET_LOCK_TIMEOUT)
 self.env.set_timeout(0, db.DB_SET_TXN_TIMEOUT)
 self.env.set_timeout(123456, db.DB_SET_LOCK_TIMEOUT)
@@ -124,6 +135,7 @@
 self.env.lock_get,anID2, "shared lock", db.DB_LOCK_READ)
 end_time=time.time()
 deadlock_detection.end=True
+ # Floating point rounding
 self.assertTrue((end_time-start_time) >= 0.0999)
 self.env.lock_put(lock)
 t.join()
Modified: python/trunk/Lib/bsddb/test/test_misc.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_misc.py	(original)
+++ python/trunk/Lib/bsddb/test/test_misc.py	Mon Mar 22 15:22:26 2010
@@ -1,7 +1,7 @@
 """Miscellaneous bsddb module test cases
 """
 
-import os
+import os, sys
 import unittest
 
 from test_all import db, dbshelve, hashopen, test_support, get_new_environment_path, get_new_database_path
@@ -9,6 +9,13 @@
 #----------------------------------------------------------------------
 
 class MiscTestCase(unittest.TestCase):
+ if sys.version_info < (2, 4) :
+ def assertTrue(self, expr, msg=None):
+ self.failUnless(expr, msg=msg)
+
+ def assertFalse(self, expr, msg=None):
+ self.failIf(expr, msg=msg)
+
 def setUp(self):
 self.filename = get_new_database_path()
 self.homeDir = get_new_environment_path()
@@ -27,7 +34,6 @@
 # check for crash fixed when db_home is used before open()
 self.assert_(env.db_home is None)
 env.open(self.homeDir, db.DB_CREATE)
- import sys
 if sys.version_info[0] < 3 :
 self.assertEqual(self.homeDir, env.db_home)
 else :
@@ -119,6 +125,19 @@
 test_support.unlink(self.filename)
 
 
+ def test08_ExceptionTypes(self) :
+ self.assertTrue(issubclass(db.DBError, Exception))
+ for i, j in db.__dict__.items() :
+ if i.startswith("DB") and i.endswith("Error") :
+ self.assertTrue(issubclass(j, db.DBError), msg=i)
+ if i not in ("DBKeyEmptyError", "DBNotFoundError") :
+ self.assertFalse(issubclass(j, KeyError), msg=i)
+
+ # This two exceptions have two bases
+ self.assertTrue(issubclass(db.DBKeyEmptyError, KeyError))
+ self.assertTrue(issubclass(db.DBNotFoundError, KeyError))
+
+
 #----------------------------------------------------------------------
 
 
Modified: python/trunk/Lib/bsddb/test/test_pickle.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_pickle.py	(original)
+++ python/trunk/Lib/bsddb/test/test_pickle.py	Mon Mar 22 15:22:26 2010
@@ -1,10 +1,16 @@
 
 import os
 import pickle
-try:
- import cPickle
-except ImportError:
+import sys
+
+if sys.version_info[0] < 3 :
+ try:
+ import cPickle
+ except ImportError:
+ cPickle = None
+else :
 cPickle = None
+
 import unittest
 
 from test_all import db, test_support, get_new_environment_path, get_new_database_path
Modified: python/trunk/Lib/bsddb/test/test_recno.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_recno.py	(original)
+++ python/trunk/Lib/bsddb/test/test_recno.py	Mon Mar 22 15:22:26 2010
@@ -1,7 +1,7 @@
 """TestCases for exercising a Recno DB.
 """
 
-import os
+import os, sys
 import errno
 from pprint import pprint
 import unittest
@@ -14,10 +14,19 @@
 #----------------------------------------------------------------------
 
 class SimpleRecnoTestCase(unittest.TestCase):
- import sys
- if sys.version_info[:3] < (2, 4, 0):
- def assertFalse(self, expr, msg=None):
- self.failIf(expr,msg=msg)
+ if sys.version_info < (2, 4) :
+ def assertFalse(self, expr, msg=None) :
+ return self.failIf(expr,msg=msg)
+ def assertTrue(self, expr, msg=None) :
+ return self.assert_(expr, msg=msg)
+
+ if (sys.version_info < (2, 7)) or ((sys.version_info >= (3, 0)) and
+ (sys.version_info < (3, 2))) :
+ def assertIsInstance(self, obj, datatype, msg=None) :
+ return self.assertEqual(type(obj), datatype, msg=msg)
+ def assertGreaterEqual(self, a, b, msg=None) :
+ return self.assertTrue(a>=b, msg=msg)
+
 
 def setUp(self):
 self.filename = get_new_database_path()
@@ -60,7 +69,10 @@
 try:
 data = d[0] # This should raise a KeyError!?!?!
 except db.DBInvalidArgError, val:
- self.assertEqual(val.args[0], db.EINVAL)
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.EINVAL)
+ else :
+ self.assertEqual(val.args[0], db.EINVAL)
 if verbose: print val
 else:
 self.fail("expected exception")
@@ -177,7 +189,10 @@
 if get_returns_none:
 self.fail("unexpected DBKeyEmptyError exception")
 else:
- self.assertEqual(val.args[0], db.DB_KEYEMPTY)
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.DB_KEYEMPTY)
+ else :
+ self.assertEqual(val.args[0], db.DB_KEYEMPTY)
 if verbose: print val
 else:
 if not get_returns_none:
@@ -265,7 +280,10 @@
 try: # this one will fail
 d.append('bad' * 20)
 except db.DBInvalidArgError, val:
- self.assertEqual(val.args[0], db.EINVAL)
+ if sys.version_info < (2, 6) :
+ self.assertEqual(val[0], db.EINVAL)
+ else :
+ self.assertEqual(val.args[0], db.EINVAL)
 if verbose: print val
 else:
 self.fail("expected exception")
Modified: python/trunk/Lib/bsddb/test/test_replication.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_replication.py	(original)
+++ python/trunk/Lib/bsddb/test/test_replication.py	Mon Mar 22 15:22:26 2010
@@ -4,7 +4,6 @@
 import os
 import time
 import unittest
-import weakref
 
 from test_all import db, test_support, have_threads, verbose, \
 get_new_environment_path, get_new_database_path
@@ -12,9 +11,9 @@
 
 #----------------------------------------------------------------------
 
-class DBReplicationManager(unittest.TestCase):
+class DBReplication(unittest.TestCase) :
 import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4) :
 def assertTrue(self, expr, msg=None):
 self.failUnless(expr,msg=msg)
 
@@ -35,16 +34,13 @@
 | db.DB_INIT_LOG | db.DB_INIT_MPOOL | db.DB_INIT_LOCK |
 db.DB_INIT_REP | db.DB_RECOVER | db.DB_THREAD, 0666)
 
- wr = weakref.ref(self)
 self.confirmed_master=self.client_startupdone=False
 def confirmed_master(a,b,c) :
 if b==db.DB_EVENT_REP_MASTER :
- self = wr()
 self.confirmed_master=True
 
 def client_startupdone(a,b,c) :
 if b==db.DB_EVENT_REP_STARTUPDONE :
- self = wr()
 self.client_startupdone=True
 
 self.dbenvMaster.set_event_notify(confirmed_master)
@@ -63,11 +59,21 @@
 self.dbClient.close()
 if self.dbMaster :
 self.dbMaster.close()
+
+ # Here we assign dummy event handlers to allow GC of the test object.
+ # Since the dummy handler doesn't use any outer scope variable, it
+ # doesn't keep any reference to the test object.
+ def dummy(*args) :
+ pass
+ self.dbenvMaster.set_event_notify(dummy)
+ self.dbenvClient.set_event_notify(dummy)
+
 self.dbenvClient.close()
 self.dbenvMaster.close()
 test_support.rmtree(self.homeDirClient)
 test_support.rmtree(self.homeDirMaster)
 
+class DBReplicationManager(DBReplication) :
 def test01_basic_replication(self) :
 master_port = test_support.find_unused_port()
 self.dbenvMaster.repmgr_set_local_site("127.0.0.1", master_port)
@@ -216,18 +222,15 @@
 self.assertTrue(time.time()<timeout)
 self.assertEquals(None, v)
 
-class DBBaseReplication(DBReplicationManager):
+class DBBaseReplication(DBReplication) :
 def setUp(self) :
- DBReplicationManager.setUp(self)
- wr = weakref.ref(self)
+ DBReplication.setUp(self)
 def confirmed_master(a,b,c) :
 if (b == db.DB_EVENT_REP_MASTER) or (b == db.DB_EVENT_REP_ELECTED) :
- self = wr()
 self.confirmed_master = True
 
 def client_startupdone(a,b,c) :
 if b == db.DB_EVENT_REP_STARTUPDONE :
- self = wr()
 self.client_startupdone = True
 
 self.dbenvMaster.set_event_notify(confirmed_master)
@@ -240,11 +243,9 @@
 # There are only two nodes, so we don't need to
 # do any routing decision
 def m2c(dbenv, control, rec, lsnp, envid, flags) :
- self = wr()
 self.m2c.put((control, rec))
 
 def c2m(dbenv, control, rec, lsnp, envid, flags) :
- self = wr()
 self.c2m.put((control, rec))
 
 self.dbenvMaster.rep_set_transport(13,m2c)
@@ -261,12 +262,10 @@
 #self.dbenvClient.set_verbose(db.DB_VERB_FILEOPS_ALL, True)
 
 def thread_master() :
- self = wr()
 return self.thread_do(self.dbenvMaster, self.c2m, 3,
 self.master_doing_election, True)
 
 def thread_client() :
- self = wr()
 return self.thread_do(self.dbenvClient, self.m2c, 13,
 self.client_doing_election, False)
 
@@ -299,6 +298,17 @@
 self.c2m.put(None)
 self.t_m.join()
 self.t_c.join()
+
+ # Here we assign dummy event handlers to allow GC of the test object.
+ # Since the dummy handler doesn't use any outer scope variable, it
+ # doesn't keep any reference to the test object.
+ def dummy(*args) :
+ pass
+ self.dbenvMaster.set_event_notify(dummy)
+ self.dbenvClient.set_event_notify(dummy)
+ self.dbenvMaster.rep_set_transport(13,dummy)
+ self.dbenvClient.rep_set_transport(3,dummy)
+
 self.dbenvClient.close()
 self.dbenvMaster.close()
 test_support.rmtree(self.homeDirClient)
@@ -358,6 +368,9 @@
 txn.commit()
 break
 
+ d = self.dbenvMaster.rep_stat(flags=db.DB_STAT_CLEAR);
+ self.assertTrue("master_changes" in d)
+
 txn=self.dbenvMaster.txn_begin()
 self.dbMaster.put("ABC", "123", txn=txn)
 txn.commit()
@@ -419,7 +432,6 @@
 break
 except db.DBRepUnavailError :
 pass
-
 if not election_status[0] and not self.confirmed_master :
 from threading import Thread
 election_status[0] = True
@@ -449,6 +461,14 @@
 
 self.assertTrue(self.confirmed_master)
 
+ if db.version() >= (4,7) :
+ def test04_test_clockskew(self) :
+ fast, slow = 1234, 1230
+ self.dbenvMaster.rep_set_clockskew(fast, slow)
+ self.assertEqual((fast, slow),
+ self.dbenvMaster.rep_get_clockskew())
+ self.basic_rep_threading()
+
 #----------------------------------------------------------------------
 
 def test_suite():
Modified: python/trunk/Lib/bsddb/test/test_sequence.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_sequence.py	(original)
+++ python/trunk/Lib/bsddb/test/test_sequence.py	Mon Mar 22 15:22:26 2010
@@ -6,7 +6,7 @@
 
 class DBSequenceTest(unittest.TestCase):
 import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4) :
 def assertTrue(self, expr, msg=None):
 self.failUnless(expr,msg=msg)
 
@@ -37,7 +37,7 @@
 self.seq = db.DBSequence(self.d, flags=0)
 start_value = 10 * self.int_32_max
 self.assertEqual(0xA00000000, start_value)
- self.assertEquals(None, self.seq.init_value(start_value))
+ self.assertEquals(None, self.seq.initial_value(start_value))
 self.assertEquals(None, self.seq.open(key='id', txn=None, flags=db.DB_CREATE))
 self.assertEquals(start_value, self.seq.get(5))
 self.assertEquals(start_value + 5, self.seq.get())
@@ -77,7 +77,7 @@
 self.seq = db.DBSequence(self.d, flags=0)
 seq_range = (10 * self.int_32_max, 11 * self.int_32_max - 1)
 self.assertEquals(None, self.seq.set_range(seq_range))
- self.seq.init_value(seq_range[0])
+ self.seq.initial_value(seq_range[0])
 self.assertEquals(None, self.seq.open(key='foo', txn=None, flags=db.DB_CREATE))
 self.assertEquals(seq_range, self.seq.get_range())
 
@@ -110,7 +110,7 @@
 value_minus=(-1L<<63)+1 # Two complement
 self.assertEquals(-9223372036854775807L,value_minus)
 self.seq = db.DBSequence(self.d, flags=0)
- self.assertEquals(None, self.seq.init_value(value_plus-1))
+ self.assertEquals(None, self.seq.initial_value(value_plus-1))
 self.assertEquals(None, self.seq.open(key='id', txn=None,
 flags=db.DB_CREATE))
 self.assertEquals(value_plus-1, self.seq.get(1))
@@ -119,7 +119,7 @@
 self.seq.remove(txn=None, flags=0)
 
 self.seq = db.DBSequence(self.d, flags=0)
- self.assertEquals(None, self.seq.init_value(value_minus))
+ self.assertEquals(None, self.seq.initial_value(value_minus))
 self.assertEquals(None, self.seq.open(key='id', txn=None,
 flags=db.DB_CREATE))
 self.assertEquals(value_minus, self.seq.get(1))
Modified: python/trunk/Lib/bsddb/test/test_thread.py
==============================================================================
--- python/trunk/Lib/bsddb/test/test_thread.py	(original)
+++ python/trunk/Lib/bsddb/test/test_thread.py	Mon Mar 22 15:22:26 2010
@@ -21,7 +21,6 @@
 
 if have_threads :
 from threading import Thread
- import sys
 if sys.version_info[0] < 3 :
 from threading import currentThread
 else :
@@ -36,8 +35,7 @@
 dbsetflags = 0
 envflags = 0
 
- import sys
- if sys.version_info[:3] < (2, 4, 0):
+ if sys.version_info < (2, 4) :
 def assertTrue(self, expr, msg=None):
 self.failUnless(expr,msg=msg)
 
@@ -99,7 +97,6 @@
 args = (self.d, x),
 name = 'reader %d' % x,
 )#verbose = verbose)
- import sys
 if sys.version_info[0] < 3 :
 rt.setDaemon(True)
 else :
@@ -118,7 +115,6 @@
 writers.append(wt)
 
 for t in writers:
- import sys
 if sys.version_info[0] < 3 :
 t.setDaemon(True)
 else :
@@ -131,7 +127,6 @@
 t.join()
 
 def writerThread(self, d, keys, readers):
- import sys
 if sys.version_info[0] < 3 :
 name = currentThread().getName()
 else :
@@ -161,7 +156,6 @@
 print "%s: thread finished" % name
 
 def readerThread(self, d, readerNum):
- import sys
 if sys.version_info[0] < 3 :
 name = currentThread().getName()
 else :
@@ -231,7 +225,6 @@
 args = (self.d, x),
 name = 'reader %d' % x,
 )#verbose = verbose)
- import sys
 if sys.version_info[0] < 3 :
 rt.setDaemon(True)
 else :
@@ -250,7 +243,6 @@
 writers.append(wt)
 
 for t in writers:
- import sys
 if sys.version_info[0] < 3 :
 t.setDaemon(True)
 else :
@@ -263,7 +255,6 @@
 t.join()
 
 def writerThread(self, d, keys, readers):
- import sys
 if sys.version_info[0] < 3 :
 name = currentThread().getName()
 else :
@@ -290,7 +281,6 @@
 print "%s: thread finished" % name
 
 def readerThread(self, d, readerNum):
- import sys
 if sys.version_info[0] < 3 :
 name = currentThread().getName()
 else :
@@ -361,7 +351,6 @@
 args = (self.d, x),
 name = 'reader %d' % x,
 )#verbose = verbose)
- import sys
 if sys.version_info[0] < 3 :
 rt.setDaemon(True)
 else :
@@ -379,7 +368,6 @@
 writers.append(wt)
 
 dt = Thread(target = self.deadlockThread)
- import sys
 if sys.version_info[0] < 3 :
 dt.setDaemon(True)
 else :
@@ -387,7 +375,6 @@
 dt.start()
 
 for t in writers:
- import sys
 if sys.version_info[0] < 3 :
 t.setDaemon(True)
 else :
@@ -403,7 +390,6 @@
 dt.join()
 
 def writerThread(self, d, keys, readers):
- import sys
 if sys.version_info[0] < 3 :
 name = currentThread().getName()
 else :
@@ -424,14 +410,17 @@
 readers.pop().start()
 except (db.DBLockDeadlockError, db.DBLockNotGrantedError), val:
 if verbose:
- print "%s: Aborting transaction (%s)" % (name, val.args[1])
+ if sys.version_info < (2, 6) :
+ print "%s: Aborting transaction (%s)" % (name, val[1])
+ else :
+ print "%s: Aborting transaction (%s)" % (name,
+ val.args[1])
 txn.abort()
 
 if verbose:
 print "%s: thread finished" % name
 
 def readerThread(self, d, readerNum):
- import sys
 if sys.version_info[0] < 3 :
 name = currentThread().getName()
 else :
@@ -455,7 +444,11 @@
 finished = True
 except (db.DBLockDeadlockError, db.DBLockNotGrantedError), val:
 if verbose:
- print "%s: Aborting transaction (%s)" % (name, val.args[1])
+ if sys.version_info < (2, 6) :
+ print "%s: Aborting transaction (%s)" % (name, val[1])
+ else :
+ print "%s: Aborting transaction (%s)" % (name,
+ val.args[1])
 c.close()
 txn.abort()
 
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Mon Mar 22 15:22:26 2010
@@ -81,7 +81,9 @@
 
 - Issue #1039, #8154: Fix os.execlp() crash with missing 2nd argument.
 
-- Issue #6949: Allow the _bsddb extension to be built with db-4.8.x.
+- Issue #8156: bsddb module updated to version 4.8.4.
+ http://www.jcea.es/programacion/pybsddb.htm#bsddb3-4.8.4.
+ This update drops support for Berkeley DB 4.0, and adds support for 4.8.
 
 - Issue #8142: Update libffi to the 3.0.9 release.
 
Modified: python/trunk/Modules/_bsddb.c
==============================================================================
--- python/trunk/Modules/_bsddb.c	(original)
+++ python/trunk/Modules/_bsddb.c	Mon Mar 22 15:22:26 2010
@@ -73,6 +73,10 @@
 * DBLock (A lock handle)
 * DBSequence (Sequence)
 *
+ * More datatypes added:
+ *
+ * DBLogCursor (Log Cursor)
+ *
 */
 
 /* --------------------------------------------------------------------- */
@@ -169,9 +173,6 @@
 
 #endif
 
-/* Should DB_INCOMPLETE be turned into a warning or an exception? */
-#define INCOMPLETE_IS_WARNING 1
-
 /* --------------------------------------------------------------------- */
 /* Exceptions */
 
@@ -191,10 +192,6 @@
 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
 
-#if !INCOMPLETE_IS_WARNING
-static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
-#endif
-
 static PyObject* DBInvalidArgError; /* EINVAL */
 static PyObject* DBAccessError; /* EACCES */
 static PyObject* DBNoSpaceError; /* ENOSPC */
@@ -208,6 +205,18 @@
 #if (DBVER >= 42)
 static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
 #endif
+#if (DBVER >= 44)
+static PyObject* DBRepLockoutError; /* DB_REP_LOCKOUT */
+#endif
+
+#if (DBVER >= 46)
+static PyObject* DBRepLeaseExpiredError; /* DB_REP_LEASE_EXPIRED */
+#endif
+
+#if (DBVER >= 47)
+static PyObject* DBForeignConflictError; /* DB_FOREIGN_CONFLICT */
+#endif
+
 
 static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
 
@@ -242,7 +251,7 @@
 #endif
 
 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
- DBLock_Type;
+ DBLock_Type, DBLogCursor_Type;
 #if (DBVER >= 43)
 staticforward PyTypeObject DBSequence_Type;
 #endif
@@ -254,6 +263,7 @@
 
 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
+#define DBLogCursorObject_Check(v) (Py_TYPE(v) == &DBLogCursor_Type)
 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
@@ -359,6 +369,9 @@
 #define CHECK_CURSOR_NOT_CLOSED(curs) \
 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
 
+#define CHECK_LOGCURSOR_NOT_CLOSED(logcurs) \
+ _CHECK_OBJECT_NOT_CLOSED(logcurs->logc, DBCursorClosedError, DBLogCursor)
+
 #if (DBVER >= 43)
 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
@@ -671,27 +684,8 @@
 unsigned int bytes_left;
 
 switch (err) {
- case 0: /* successful, no error */ break;
-
-#if (DBVER < 41)
- case DB_INCOMPLETE:
-#if INCOMPLETE_IS_WARNING
- bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
- /* Ensure that bytes_left never goes negative */
- if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
- bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
-		assert(bytes_left >= 0);
- strcat(errTxt, " -- ");
- strncat(errTxt, _db_errmsg, bytes_left);
- }
- _db_errmsg[0] = 0;
- exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
-
-#else /* do an exception instead */
- errObj = DBIncompleteError;
-#endif
- break;
-#endif /* DBVER < 41 */
+ case 0: /* successful, no error */
+ return 0;
 
 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
 case DB_KEYEXIST: errObj = DBKeyExistError; break;
@@ -724,6 +718,17 @@
 #if (DBVER >= 42)
 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
 #endif
+#if (DBVER >= 44)
+ case DB_REP_LOCKOUT : errObj = DBRepLockoutError; break;
+#endif
+
+#if (DBVER >= 46)
+ case DB_REP_LEASE_EXPIRED : errObj = DBRepLeaseExpiredError; break;
+#endif
+
+#if (DBVER >= 47)
+ case DB_FOREIGN_CONFLICT : errObj = DBForeignConflictError; break;
+#endif
 
 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
 
@@ -792,7 +797,6 @@
 if (makeDBError(err)) {
 return -1;
 }
- self->haveStat = 0;
 return 0;
 }
 
@@ -809,7 +813,6 @@
 if (makeDBError(err)) {
 return -1;
 }
- self->haveStat = 0;
 return 0;
 }
 
@@ -826,7 +829,7 @@
 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
 
 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
-				 &flags, &dlen, &doff)) 
+				 &flags, &dlen, &doff))
 return NULL;
 
 CHECK_CURSOR_NOT_CLOSED(self);
@@ -934,7 +937,6 @@
 if (self == NULL)
 return NULL;
 
- self->haveStat = 0;
 self->flags = 0;
 self->setflags = 0;
 self->myenvobj = NULL;
@@ -1081,6 +1083,54 @@
 }
 
 
+static DBLogCursorObject*
+newDBLogCursorObject(DB_LOGC* dblogc, DBEnvObject* env)
+{
+ DBLogCursorObject* self;
+
+ self = PyObject_New(DBLogCursorObject, &DBLogCursor_Type);
+
+ if (self == NULL)
+ return NULL;
+
+ self->logc = dblogc;
+ self->env = env;
+
+ INSERT_IN_DOUBLE_LINKED_LIST(self->env->children_logcursors, self);
+
+ self->in_weakreflist = NULL;
+ Py_INCREF(self->env);
+ return self;
+}
+
+
+/* Forward declaration */
+static PyObject *DBLogCursor_close_internal(DBLogCursorObject* self);
+
+static void
+DBLogCursor_dealloc(DBLogCursorObject* self)
+{
+ PyObject *dummy;
+
+ if (self->logc != NULL) {
+ dummy = DBLogCursor_close_internal(self);
+ /*
+ ** Raising exceptions while doing
+ ** garbage collection is a fatal error.
+ */
+ if (dummy)
+ Py_DECREF(dummy);
+ else
+ PyErr_Clear();
+ }
+ if (self->in_weakreflist != NULL) {
+ PyObject_ClearWeakRefs((PyObject *) self);
+ }
+ Py_DECREF(self->env);
+ PyObject_Del(self);
+}
+
+
 static DBEnvObject*
 newDBEnvObject(int flags)
 {
@@ -1096,6 +1146,7 @@
 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
 self->children_dbs = NULL;
 self->children_txns = NULL;
+ self->children_logcursors = NULL ;
 Py_INCREF(Py_None);
 self->private_obj = Py_None;
 Py_INCREF(Py_None);
@@ -1167,6 +1218,8 @@
 self->flag_prepare = 0;
 self->parent_txn = NULL;
 self->env = NULL;
+ /* We initialize just in case "txn_begin" fails */
+ self->txn = NULL;
 
 if (parent && ((PyObject *)parent!=Py_None)) {
 parent_txn = parent->txn;
@@ -1180,6 +1233,7 @@
 MYDB_END_ALLOW_THREADS;
 
 if (makeDBError(err)) {
+ /* Free object half initialized */
 Py_DECREF(self);
 return NULL;
 }
@@ -1213,7 +1267,7 @@
 if (self->txn) {
 int flag_prepare = self->flag_prepare;
 
- dummy=DBTxn_abort_discard_internal(self,0);
+ dummy=DBTxn_abort_discard_internal(self, 0);
 /*
 ** Raising exceptions while doing
 ** garbage collection is a fatal error.
@@ -1236,7 +1290,12 @@
 if (self->env) {
 Py_DECREF(self->env);
 } else {
- Py_DECREF(self->parent_txn);
+ /*
+ ** We can have "self->env==NULL" and "self->parent_txn==NULL"
+ ** if something happens when creating the transaction object
+ ** and we abort the object while half done.
+ */
+ Py_XDECREF(self->parent_txn);
 }
 PyObject_Del(self);
 }
@@ -1251,6 +1310,7 @@
 if (self == NULL)
 return NULL;
 self->in_weakreflist = NULL;
+ self->lock_initialized = 0; /* Just in case the call fails */
 
 MYDB_BEGIN_ALLOW_THREADS;
 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
@@ -1259,6 +1319,8 @@
 if (makeDBError(err)) {
 Py_DECREF(self);
 self = NULL;
+ } else {
+ self->lock_initialized = 1;
 }
 
 return self;
@@ -1272,6 +1334,7 @@
 PyObject_ClearWeakRefs((PyObject *) self);
 }
 /* TODO: is this lock held? should we release it? */
+ /* CAUTION: The lock can be not initialized if the creation has failed */
 
 PyObject_Del(self);
 }
@@ -1292,6 +1355,7 @@
 self->txn = NULL;
 
 self->in_weakreflist = NULL;
+ self->sequence = NULL; /* Just in case the call fails */
 
 MYDB_BEGIN_ALLOW_THREADS;
 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
@@ -1421,10 +1485,70 @@
 		PyErr_Print();
 	 }
 }
+#if (DBVER >= 46)
+ else if (PyList_Check(result))
+ {
+ char* data;
+ Py_ssize_t size;
+ int i, listlen;
+ DBT* dbts;
+
+ listlen = PyList_Size(result);
+
+ dbts = (DBT *)malloc(sizeof(DBT) * listlen);
+
+ for (i=0; i<listlen; i++)
+ {
+ if (!PyBytes_Check(PyList_GetItem(result, i)))
+ {
+ PyErr_SetString(
+ PyExc_TypeError,
+#if (PY_VERSION_HEX < 0x03000000)
+"The list returned by DB->associate callback should be a list of strings.");
+#else
+"The list returned by DB->associate callback should be a list of bytes.");
+#endif
+ PyErr_Print();
+ }
+
+ PyBytes_AsStringAndSize(
+ PyList_GetItem(result, i),
+ &data, &size);
+
+ CLEAR_DBT(dbts[i]);
+ dbts[i].data = malloc(size); /* TODO, check this */
+
+ if (dbts[i].data)
+ {
+ memcpy(dbts[i].data, data, size);
+ dbts[i].size = size;
+ dbts[i].ulen = dbts[i].size;
+ dbts[i].flags = DB_DBT_APPMALLOC; /* DB will free */
+ }
+ else
+ {
+ PyErr_SetString(PyExc_MemoryError,
+ "malloc failed in _db_associateCallback (list)");
+ PyErr_Print();
+ }
+ }
+
+ CLEAR_DBT(*secKey);
+
+ secKey->data = dbts;
+ secKey->size = listlen;
+ secKey->flags = DB_DBT_APPMALLOC | DB_DBT_MULTIPLE;
+ retval = 0;
+ }
+#endif
 else {
 PyErr_SetString(
 PyExc_TypeError,
- "DB associate callback should return DB_DONOTINDEX or string.");
+#if (PY_VERSION_HEX < 0x03000000)
+"DB associate callback should return DB_DONOTINDEX/string/list of strings.");
+#else
+"DB associate callback should return DB_DONOTINDEX/bytes/list of bytes.");
+#endif
 PyErr_Print();
 }
 
@@ -1443,29 +1567,18 @@
 int err, flags=0;
 DBObject* secondaryDB;
 PyObject* callback;
-#if (DBVER >= 41)
 PyObject *txnobj = NULL;
 DB_TXN *txn = NULL;
 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
 NULL};
-#else
- static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
-#endif
 
-#if (DBVER >= 41)
 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
 &secondaryDB, &callback, &flags,
 &txnobj)) {
-#else
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
- &secondaryDB, &callback, &flags)) {
-#endif
 return NULL;
 }
 
-#if (DBVER >= 41)
 if (!checkTxnObj(txnobj, &txn)) return NULL;
-#endif
 
 CHECK_DB_NOT_CLOSED(self);
 if (!DBObject_Check(secondaryDB)) {
@@ -1501,18 +1614,11 @@
 PyEval_InitThreads();
 #endif
 MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 41)
 err = self->db->associate(self->db,
 	 txn,
 secondaryDB->db,
 _db_associateCallback,
 flags);
-#else
- err = self->db->associate(self->db,
- secondaryDB->db,
- _db_associateCallback,
- flags);
-#endif
 MYDB_END_ALLOW_THREADS;
 
 if (err) {
@@ -1705,6 +1811,64 @@
 }
 
 
+#if (DBVER >= 47)
+/*
+** This function is available since Berkeley DB 4.4,
+** but 4.6 version is so buggy that we only support
+** it from BDB 4.7 and newer.
+*/
+static PyObject*
+DB_compact(DBObject* self, PyObject* args, PyObject* kwargs)
+{
+ PyObject* txnobj = NULL;
+ PyObject *startobj = NULL, *stopobj = NULL;
+ int flags = 0;
+ DB_TXN *txn = NULL;
+ DBT *start_p = NULL, *stop_p = NULL;
+ DBT start, stop;
+ int err;
+ DB_COMPACT c_data = { 0 };
+ static char* kwnames[] = { "txn", "start", "stop", "flags",
+ "compact_fillpercent", "compact_pages",
+ "compact_timeout", NULL };
+
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOiiiI:compact", kwnames,
+ &txnobj, &startobj, &stopobj, &flags,
+ &c_data.compact_fillpercent,
+ &c_data.compact_pages,
+ &c_data.compact_timeout))
+ return NULL;
+
+ CHECK_DB_NOT_CLOSED(self);
+ if (!checkTxnObj(txnobj, &txn)) {
+ return NULL;
+ }
+
+ if (startobj && make_key_dbt(self, startobj, &start, NULL)) {
+ start_p = &start;
+ }
+ if (stopobj && make_key_dbt(self, stopobj, &stop, NULL)) {
+ stop_p = &stop;
+ }
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->compact(self->db, txn, start_p, stop_p, &c_data,
+ flags, NULL);
+ MYDB_END_ALLOW_THREADS;
+
+ if (startobj)
+ FREE_DBT(start);
+ if (stopobj)
+ FREE_DBT(stop);
+
+ RETURN_IF_ERR();
+
+ return PyLong_FromUnsignedLong(c_data.compact_pages_truncated);
+}
+#endif
+
+
 static PyObject*
 DB_fd(DBObject* self)
 {
@@ -1720,6 +1884,55 @@
 }
 
 
+#if (DBVER >= 46)
+static PyObject*
+DB_exists(DBObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err, flags=0;
+ PyObject* txnobj = NULL;
+ PyObject* keyobj;
+ DBT key;
+ DB_TXN *txn;
+
+ static char* kwnames[] = {"key", "txn", "flags", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:exists", kwnames,
+ &keyobj, &txnobj, &flags))
+ return NULL;
+
+ CHECK_DB_NOT_CLOSED(self);
+ if (!make_key_dbt(self, keyobj, &key, NULL))
+ return NULL;
+ if (!checkTxnObj(txnobj, &txn)) {
+ FREE_DBT(key);
+ return NULL;
+ }
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->exists(self->db, txn, &key, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ FREE_DBT(key);
+
+ if (!err) {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+ if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)) {
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+
+ /*
+ ** If we reach there, there was an error. The
+ ** "return" should be unreachable.
+ */
+ RETURN_IF_ERR();
+ assert(0); /* This coude SHOULD be unreachable */
+ return NULL;
+}
+#endif
+
 static PyObject*
 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
 {
@@ -2046,8 +2259,8 @@
 length = PyObject_Length(cursorsObj);
 cursors = malloc((length+1) * sizeof(DBC*));
 if (!cursors) {
-	PyErr_NoMemory();
-	return NULL;
+ PyErr_NoMemory();
+ return NULL;
 }
 
 cursors[length] = NULL;
@@ -2118,7 +2331,6 @@
 int err, type = DB_UNKNOWN, flags=0, mode=0660;
 char* filename = NULL;
 char* dbname = NULL;
-#if (DBVER >= 41)
 PyObject *txnobj = NULL;
 DB_TXN *txn = NULL;
 /* with dbname */
@@ -2127,45 +2339,22 @@
 /* without dbname */
 static char* kwnames_basic[] = {
 "filename", "dbtype", "flags", "mode", "txn", NULL};
-#else
- /* with dbname */
- static char* kwnames[] = {
- "filename", "dbname", "dbtype", "flags", "mode", NULL};
- /* without dbname */
- static char* kwnames_basic[] = {
- "filename", "dbtype", "flags", "mode", NULL};
-#endif
 
-#if (DBVER >= 41)
 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
 				 &filename, &dbname, &type, &flags, &mode,
 &txnobj))
-#else
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
-				 &filename, &dbname, &type, &flags,
- &mode))
-#endif
 {
 	PyErr_Clear();
 	type = DB_UNKNOWN; flags = 0; mode = 0660;
 	filename = NULL; dbname = NULL;
-#if (DBVER >= 41)
 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
 kwnames_basic,
 					 &filename, &type, &flags, &mode,
 &txnobj))
 	 return NULL;
-#else
-	if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
- kwnames_basic,
-					 &filename, &type, &flags, &mode))
-	 return NULL;
-#endif
 }
 
-#if (DBVER >= 41)
 if (!checkTxnObj(txnobj, &txn)) return NULL;
-#endif
 
 if (NULL == self->db) {
 PyObject *t = Py_BuildValue("(is)", 0,
@@ -2177,24 +2366,17 @@
 return NULL;
 }
 
-#if (DBVER >= 41)
 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
 self->txn=(DBTxnObject *)txnobj;
 } else {
 self->txn=NULL;
 }
-#else
- self->txn=NULL;
-#endif
 
 MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 41)
 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
-#else
- err = self->db->open(self->db, filename, dbname, type, flags, mode);
-#endif
 MYDB_END_ALLOW_THREADS;
+
 if (makeDBError(err)) {
 PyObject *dummy;
 
@@ -2323,78 +2505,161 @@
 RETURN_NONE();
 }
 
-
+#if (DBVER >= 46)
 static PyObject*
-DB_set_bt_minkey(DBObject* self, PyObject* args)
+DB_set_priority(DBObject* self, PyObject* args)
 {
- int err, minkey;
+ int err, priority;
 
- if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
+ if (!PyArg_ParseTuple(args,"i:set_priority", &priority))
 return NULL;
 CHECK_DB_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db->set_bt_minkey(self->db, minkey);
+ err = self->db->set_priority(self->db, priority);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 RETURN_NONE();
 }
 
-static int
-_default_cmp(const DBT *leftKey,
-	 const DBT *rightKey)
+static PyObject*
+DB_get_priority(DBObject* self)
 {
- int res;
- int lsize = leftKey->size, rsize = rightKey->size;
+ int err = 0;
+ DB_CACHE_PRIORITY priority;
 
- res = memcmp(leftKey->data, rightKey->data,
-	 lsize < rsize ? lsize : rsize);
+ CHECK_DB_NOT_CLOSED(self);
 
- if (res == 0) {
- if (lsize < rsize) {
-	 res = -1;
- }
- else if (lsize > rsize) {
-	 res = 1;
- }
- }
- return res;
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_priority(self->db, &priority);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(priority);
 }
+#endif
 
-static int
-_db_compareCallback(DB* db,
-		 const DBT *leftKey,
-		 const DBT *rightKey)
+static PyObject*
+DB_set_q_extentsize(DBObject* self, PyObject* args)
 {
- int res = 0;
- PyObject *args;
- PyObject *result = NULL;
- DBObject *self = (DBObject *)db->app_private;
+ int err;
+ u_int32_t extentsize;
 
- if (self == NULL || self->btCompareCallback == NULL) {
-	MYDB_BEGIN_BLOCK_THREADS;
-	PyErr_SetString(PyExc_TypeError,
-			(self == 0
-			 ? "DB_bt_compare db is NULL."
-			 : "DB_bt_compare callback is NULL."));
-	/* we're in a callback within the DB code, we can't raise */
-	PyErr_Print();
-	res = _default_cmp(leftKey, rightKey);
-	MYDB_END_BLOCK_THREADS;
- } else {
-	MYDB_BEGIN_BLOCK_THREADS;
+ if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
+ return NULL;
+ CHECK_DB_NOT_CLOSED(self);
 
-	args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
-	if (args != NULL) {
-		result = PyEval_CallObject(self->btCompareCallback, args);
-	}
-	if (args == NULL || result == NULL) {
-	 /* we're in a callback within the DB code, we can't raise */
-	 PyErr_Print();
-	 res = _default_cmp(leftKey, rightKey);
-	} else if (NUMBER_Check(result)) {
-	 res = NUMBER_AsLong(result);
-	} else {
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->set_q_extentsize(self->db, extentsize);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DB_get_q_extentsize(DBObject* self)
+{
+ int err = 0;
+ u_int32_t extentsize;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_q_extentsize(self->db, &extentsize);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(extentsize);
+}
+#endif
+
+static PyObject*
+DB_set_bt_minkey(DBObject* self, PyObject* args)
+{
+ int err, minkey;
+
+ if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey))
+ return NULL;
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->set_bt_minkey(self->db, minkey);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DB_get_bt_minkey(DBObject* self)
+{
+ int err;
+ u_int32_t bt_minkey;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_bt_minkey(self->db, &bt_minkey);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(bt_minkey);
+}
+#endif
+
+static int
+_default_cmp(const DBT *leftKey,
+	 const DBT *rightKey)
+{
+ int res;
+ int lsize = leftKey->size, rsize = rightKey->size;
+
+ res = memcmp(leftKey->data, rightKey->data,
+	 lsize < rsize ? lsize : rsize);
+
+ if (res == 0) {
+ if (lsize < rsize) {
+	 res = -1;
+ }
+ else if (lsize > rsize) {
+	 res = 1;
+ }
+ }
+ return res;
+}
+
+static int
+_db_compareCallback(DB* db,
+		 const DBT *leftKey,
+		 const DBT *rightKey)
+{
+ int res = 0;
+ PyObject *args;
+ PyObject *result = NULL;
+ DBObject *self = (DBObject *)db->app_private;
+
+ if (self == NULL || self->btCompareCallback == NULL) {
+	MYDB_BEGIN_BLOCK_THREADS;
+	PyErr_SetString(PyExc_TypeError,
+			(self == 0
+			 ? "DB_bt_compare db is NULL."
+			 : "DB_bt_compare callback is NULL."));
+	/* we're in a callback within the DB code, we can't raise */
+	PyErr_Print();
+	res = _default_cmp(leftKey, rightKey);
+	MYDB_END_BLOCK_THREADS;
+ } else {
+	MYDB_BEGIN_BLOCK_THREADS;
+
+	args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
+	if (args != NULL) {
+		result = PyEval_CallObject(self->btCompareCallback, args);
+	}
+	if (args == NULL || result == NULL) {
+	 /* we're in a callback within the DB code, we can't raise */
+	 PyErr_Print();
+	 res = _default_cmp(leftKey, rightKey);
+	} else if (NUMBER_Check(result)) {
+	 res = NUMBER_AsLong(result);
+	} else {
 	 PyErr_SetString(PyExc_TypeError,
 			 "DB_bt_compare callback MUST return an int.");
 	 /* we're in a callback within the DB code, we can't raise */
@@ -2494,6 +2759,25 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_cachesize(DBObject* self)
+{
+ int err;
+ u_int32_t gbytes, bytes;
+ int ncache;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_cachesize(self->db, &gbytes, &bytes, &ncache);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return Py_BuildValue("(iii)", gbytes, bytes, ncache);
+}
+#endif
 
 static PyObject*
 DB_set_flags(DBObject* self, PyObject* args)
@@ -2513,6 +2797,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_flags(DBObject* self)
+{
+ int err;
+ u_int32_t flags;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_flags(self->db, &flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(flags);
+}
+#endif
 
 static PyObject*
 DB_set_h_ffactor(DBObject* self, PyObject* args)
@@ -2530,6 +2830,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_h_ffactor(DBObject* self)
+{
+ int err;
+ u_int32_t ffactor;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_h_ffactor(self->db, &ffactor);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(ffactor);
+}
+#endif
 
 static PyObject*
 DB_set_h_nelem(DBObject* self, PyObject* args)
@@ -2547,6 +2863,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_h_nelem(DBObject* self)
+{
+ int err;
+ u_int32_t nelem;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_h_nelem(self->db, &nelem);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(nelem);
+}
+#endif
 
 static PyObject*
 DB_set_lorder(DBObject* self, PyObject* args)
@@ -2564,6 +2896,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_lorder(DBObject* self)
+{
+ int err;
+ int lorder;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_lorder(self->db, &lorder);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lorder);
+}
+#endif
 
 static PyObject*
 DB_set_pagesize(DBObject* self, PyObject* args)
@@ -2581,6 +2929,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_pagesize(DBObject* self)
+{
+ int err;
+ u_int32_t pagesize;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_pagesize(self->db, &pagesize);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(pagesize);
+}
+#endif
 
 static PyObject*
 DB_set_re_delim(DBObject* self, PyObject* args)
@@ -2603,6 +2967,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_re_delim(DBObject* self)
+{
+ int err, re_delim;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_re_delim(self->db, &re_delim);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(re_delim);
+}
+#endif
+
 static PyObject*
 DB_set_re_len(DBObject* self, PyObject* args)
 {
@@ -2619,6 +2999,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_re_len(DBObject* self)
+{
+ int err;
+ u_int32_t re_len;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_re_len(self->db, &re_len);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(re_len);
+}
+#endif
 
 static PyObject*
 DB_set_re_pad(DBObject* self, PyObject* args)
@@ -2640,41 +3036,55 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DB_get_re_pad(DBObject* self)
+{
+ int err, re_pad;
+
+ CHECK_DB_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_re_pad(self->db, &re_pad);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(re_pad);
+}
+#endif
 
 static PyObject*
 DB_set_re_source(DBObject* self, PyObject* args)
 {
 int err;
- char *re_source;
+ char *source;
 
- if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
+ if (!PyArg_ParseTuple(args,"s:set_re_source", &source))
 return NULL;
 CHECK_DB_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db->set_re_source(self->db, re_source);
+ err = self->db->set_re_source(self->db, source);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 RETURN_NONE();
 }
 
-
+#if (DBVER >= 42)
 static PyObject*
-DB_set_q_extentsize(DBObject* self, PyObject* args)
+DB_get_re_source(DBObject* self)
 {
 int err;
- int extentsize;
+ const char *source;
 
- if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
- return NULL;
 CHECK_DB_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db->set_q_extentsize(self->db, extentsize);
+ err = self->db->get_re_source(self->db, &source);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
- RETURN_NONE();
+ return PyBytes_FromString(source);
 }
+#endif
 
 static PyObject*
 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
@@ -2711,8 +3121,6 @@
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 
- self->haveStat = 1;
-
 /* Turn the stat structure into a dictionary */
 type = _DB_get_type(self);
 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
@@ -2734,9 +3142,6 @@
 MAKE_HASH_ENTRY(pagecnt);
 #endif
 MAKE_HASH_ENTRY(pagesize);
-#if (DBVER < 41)
- MAKE_HASH_ENTRY(nelem);
-#endif
 MAKE_HASH_ENTRY(ffactor);
 MAKE_HASH_ENTRY(buckets);
 MAKE_HASH_ENTRY(free);
@@ -2783,9 +3188,7 @@
 MAKE_QUEUE_ENTRY(nkeys);
 MAKE_QUEUE_ENTRY(ndata);
 MAKE_QUEUE_ENTRY(pagesize);
-#if (DBVER >= 41)
 MAKE_QUEUE_ENTRY(extentsize);
-#endif
 MAKE_QUEUE_ENTRY(pages);
 MAKE_QUEUE_ENTRY(re_len);
 MAKE_QUEUE_ENTRY(re_pad);
@@ -2811,6 +3214,29 @@
 return d;
 }
 
+#if (DBVER >= 43)
+static PyObject*
+DB_stat_print(DBObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_DB_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->stat_print(self->db, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
 static PyObject*
 DB_sync(DBObject* self, PyObject* args)
 {
@@ -2896,7 +3322,7 @@
 PyObject *error;
 
 error=DB_close_internal(self, 0, 1);
- if (error ) {
+ if (error) {
 return error;
 }
 }
@@ -2934,7 +3360,6 @@
 return NUMBER_FromLong(oldValue);
 }
 
-#if (DBVER >= 41)
 static PyObject*
 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
 {
@@ -2955,21 +3380,37 @@
 RETURN_IF_ERR();
 RETURN_NONE();
 }
-#endif /* DBVER >= 41 */
-
-
-/*-------------------------------------------------------------- */
-/* Mapping and Dictionary-like access routines */
 
-Py_ssize_t DB_length(PyObject* _self)
+#if (DBVER >= 42)
+static PyObject*
+DB_get_encrypt_flags(DBObject* self)
 {
 int err;
- Py_ssize_t size = 0;
- int flags = 0;
- void* sp;
- DBObject* self = (DBObject*)_self;
+ u_int32_t flags;
 
- if (self->db == NULL) {
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get_encrypt_flags(self->db, &flags);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return NUMBER_FromLong(flags);
+}
+#endif
+
+
+
+/*-------------------------------------------------------------- */
+/* Mapping and Dictionary-like access routines */
+
+Py_ssize_t DB_length(PyObject* _self)
+{
+ int err;
+ Py_ssize_t size = 0;
+ void* sp;
+ DBObject* self = (DBObject*)_self;
+
+ if (self->db == NULL) {
 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
 if (t) {
 PyErr_SetObject(DBError, t);
@@ -2978,41 +3419,21 @@
 return -1;
 }
 
- if (self->haveStat) { /* Has the stat function been called recently? If
- so, we can use the cached value. */
- flags = DB_FAST_STAT;
- }
-
 MYDB_BEGIN_ALLOW_THREADS;
-redo_stat_for_length:
 #if (DBVER >= 43)
- err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
+ err = self->db->stat(self->db, /*txnid*/ NULL, &sp, 0);
 #else
- err = self->db->stat(self->db, &sp, flags);
+ err = self->db->stat(self->db, &sp, 0);
 #endif
+ MYDB_END_ALLOW_THREADS;
 
 /* All the stat structures have matching fields upto the ndata field,
 so we can use any of them for the type cast */
 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
 
- /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
- * redo a full stat to make sure.
- * Fixes SF python bug 1493322, pybsddb bug 1184012
- */
- if (size == 0 && (flags & DB_FAST_STAT)) {
- flags = 0;
- if (!err)
- free(sp);
- goto redo_stat_for_length;
- }
-
- MYDB_END_ALLOW_THREADS;
-
 if (err)
 return -1;
 
- self->haveStat = 1;
-
 free(sp);
 return size;
 }
@@ -3101,18 +3522,11 @@
 
 
 static PyObject*
-DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
+_DB_has_key(DBObject* self, PyObject* keyobj, PyObject* txnobj)
 {
 int err;
- PyObject* keyobj;
- DBT key, data;
- PyObject* txnobj = NULL;
+ DBT key;
 DB_TXN *txn = NULL;
- static char* kwnames[] = {"key","txn", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
- &keyobj, &txnobj))
- return NULL;
 
 CHECK_DB_NOT_CLOSED(self);
 if (!make_key_dbt(self, keyobj, &key, NULL))
@@ -3122,28 +3536,77 @@
 return NULL;
 }
 
+#if (DBVER < 46)
 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
 it has a record but can't allocate a buffer for the data. This saves
 having to deal with data we won't be using.
 */
- CLEAR_DBT(data);
- data.flags = DB_DBT_USERMEM;
+ {
+ DBT data ;
+ CLEAR_DBT(data);
+ data.flags = DB_DBT_USERMEM;
 
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db->get(self->db, txn, &key, &data, 0);
+ MYDB_END_ALLOW_THREADS;
+ }
+#else
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db->get(self->db, txn, &key, &data, 0);
+ err = self->db->exists(self->db, txn, &key, 0);
 MYDB_END_ALLOW_THREADS;
+#endif
+
 FREE_DBT(key);
 
+ /*
+ ** DB_BUFFER_SMALL is only used if we use "get".
+ ** We can drop it when we only use "exists",
+ ** when we drop suport for Berkeley DB < 4.6.
+ */
 if (err == DB_BUFFER_SMALL || err == 0) {
- return NUMBER_FromLong(1);
+ Py_INCREF(Py_True);
+ return Py_True;
 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
- return NUMBER_FromLong(0);
+ Py_INCREF(Py_False);
+ return Py_False;
 }
 
 makeDBError(err);
 return NULL;
 }
 
+static PyObject*
+DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
+{
+ PyObject* keyobj;
+ PyObject* txnobj = NULL;
+ static char* kwnames[] = {"key","txn", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
+ &keyobj, &txnobj))
+ return NULL;
+
+ return _DB_has_key(self, keyobj, txnobj);
+}
+
+
+static int DB_contains(DBObject* self, PyObject* keyobj)
+{
+ PyObject* result;
+ int result2 = 0;
+
+ result = _DB_has_key(self, keyobj, NULL) ;
+ if (result == NULL) {
+ return -1; /* Propague exception */
+ }
+ if (result != Py_False) {
+ result2 = 1;
+ }
+
+ Py_DECREF(result);
+ return result2;
+}
+
 
 #define _KEYS_LIST 1
 #define _VALUES_LIST 2
@@ -3297,6 +3760,116 @@
 }
 
 /* --------------------------------------------------------------------- */
+/* DBLogCursor methods */
+
+
+static PyObject*
+DBLogCursor_close_internal(DBLogCursorObject* self)
+{
+ int err = 0;
+
+ if (self->logc != NULL) {
+ EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->logc->close(self->logc, 0);
+ MYDB_END_ALLOW_THREADS;
+ self->logc = NULL;
+ }
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBLogCursor_close(DBLogCursorObject* self)
+{
+ return DBLogCursor_close_internal(self);
+}
+
+
+static PyObject*
+_DBLogCursor_get(DBLogCursorObject* self, int flag, DB_LSN *lsn2)
+{
+ int err;
+ DBT data;
+ DB_LSN lsn = {0, 0};
+ PyObject *dummy, *retval;
+
+ CLEAR_DBT(data);
+ data.flags = DB_DBT_MALLOC; /* Berkeley DB must do the malloc */
+
+ CHECK_LOGCURSOR_NOT_CLOSED(self);
+
+ if (lsn2)
+ lsn = *lsn2;
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->logc->get(self->logc, &lsn, &data, flag);
+ MYDB_END_ALLOW_THREADS;
+
+ if (err == DB_NOTFOUND) {
+ Py_INCREF(Py_None);
+ retval = Py_None;
+ }
+ else if (makeDBError(err)) {
+ retval = NULL;
+ }
+ else {
+ retval = dummy = BuildValue_S(data.data, data.size);
+ if (dummy) {
+ retval = Py_BuildValue("(ii)O", lsn.file, lsn.offset, dummy);
+ Py_DECREF(dummy);
+ }
+ }
+
+ FREE_DBT(data);
+ return retval;
+}
+
+static PyObject*
+DBLogCursor_current(DBLogCursorObject* self)
+{
+ return _DBLogCursor_get(self, DB_CURRENT, NULL);
+}
+
+static PyObject*
+DBLogCursor_first(DBLogCursorObject* self)
+{
+ return _DBLogCursor_get(self, DB_FIRST, NULL);
+}
+
+static PyObject*
+DBLogCursor_last(DBLogCursorObject* self)
+{
+ return _DBLogCursor_get(self, DB_LAST, NULL);
+}
+
+static PyObject*
+DBLogCursor_next(DBLogCursorObject* self)
+{
+ return _DBLogCursor_get(self, DB_NEXT, NULL);
+}
+
+static PyObject*
+DBLogCursor_prev(DBLogCursorObject* self)
+{
+ return _DBLogCursor_get(self, DB_PREV, NULL);
+}
+
+static PyObject*
+DBLogCursor_set(DBLogCursorObject* self, PyObject* args)
+{
+ DB_LSN lsn;
+
+ if (!PyArg_ParseTuple(args, "(ii):set", &lsn.file, &lsn.offset))
+ return NULL;
+
+ return _DBLogCursor_get(self, DB_SET, &lsn);
+}
+
+
+
+/* --------------------------------------------------------------------- */
 /* DBCursor methods */
 
 
@@ -3371,7 +3944,6 @@
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 
- self->mydb->haveStat = 0;
 RETURN_NONE();
 }
 
@@ -3498,7 +4070,7 @@
 {
 PyErr_Clear();
 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
- kwnames_keyOnly, 
+ kwnames_keyOnly,
 					 &keyobj, &flags, &dlen, &doff))
 {
 PyErr_Clear();
@@ -3659,7 +4231,6 @@
 MYDB_END_ALLOW_THREADS;
 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
 RETURN_IF_ERR();
- self->mydb->haveStat = 0;
 RETURN_NONE();
 }
 
@@ -3974,6 +4545,13 @@
 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
 }
 
+#if (DBVER >= 46)
+static PyObject*
+DBC_prev_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
+{
+ return _DBCursor_get(self,DB_PREV_DUP,args,kwargs,"|iii:prev_dup");
+}
+#endif
 
 static PyObject*
 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
@@ -4016,6 +4594,44 @@
 }
 
 
+#if (DBVER >= 46)
+static PyObject*
+DBC_set_priority(DBCursorObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err, priority;
+ static char* kwnames[] = { "priority", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_priority", kwnames,
+				 &priority))
+ return NULL;
+
+ CHECK_CURSOR_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->dbc->set_priority(self->dbc, priority);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+
+static PyObject*
+DBC_get_priority(DBCursorObject* self)
+{
+ int err;
+ DB_CACHE_PRIORITY priority;
+
+ CHECK_CURSOR_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->dbc->get_priority(self->dbc, &priority);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(priority);
+}
+#endif
+
+
 
 /* --------------------------------------------------------------------- */
 /* DBEnv methods */
@@ -4029,12 +4645,16 @@
 
 if (!self->closed) { /* Don't close more than once */
 while(self->children_txns) {
- dummy=DBTxn_abort_discard_internal(self->children_txns,0);
- Py_XDECREF(dummy);
+ dummy = DBTxn_abort_discard_internal(self->children_txns, 0);
+ Py_XDECREF(dummy);
 }
 while(self->children_dbs) {
- dummy=DB_close_internal(self->children_dbs, 0, 0);
- Py_XDECREF(dummy);
+ dummy = DB_close_internal(self->children_dbs, 0, 0);
+ Py_XDECREF(dummy);
+ }
+ while(self->children_logcursors) {
+ dummy = DBLogCursor_close_internal(self->children_logcursors);
+ Py_XDECREF(dummy);
 }
 }
 
@@ -4084,39 +4704,227 @@
 
 
 static PyObject*
-DBEnv_remove(DBEnvObject* self, PyObject* args)
+DBEnv_memp_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
 {
- int err, flags=0;
- char *db_home;
+ int err;
+ DB_MPOOL_STAT *gsp;
+ DB_MPOOL_FSTAT **fsp, **fsp2;
+ PyObject* d = NULL, *d2, *d3, *r;
+ u_int32_t flags = 0;
+ static char* kwnames[] = { "flags", NULL };
 
- if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat",
+ kwnames, &flags))
 return NULL;
+
 CHECK_ENV_NOT_CLOSED(self);
+
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->remove(self->db_env, db_home, flags);
+ err = self->db_env->memp_stat(self->db_env, &gsp, &fsp, flags);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
- RETURN_NONE();
+
+ /* Turn the stat structure into a dictionary */
+ d = PyDict_New();
+ if (d == NULL) {
+ if (gsp)
+ free(gsp);
+ return NULL;
+ }
+
+#define MAKE_ENTRY(name) _addIntToDict(d, #name, gsp->st_##name)
+
+ MAKE_ENTRY(gbytes);
+ MAKE_ENTRY(ncache);
+#if (DBVER >= 46)
+ MAKE_ENTRY(max_ncache);
+#endif
+ MAKE_ENTRY(regsize);
+#if (DBVER >= 43)
+ MAKE_ENTRY(mmapsize);
+ MAKE_ENTRY(maxopenfd);
+ MAKE_ENTRY(maxwrite);
+ MAKE_ENTRY(maxwrite_sleep);
+#endif
+ MAKE_ENTRY(map);
+ MAKE_ENTRY(cache_hit);
+ MAKE_ENTRY(cache_miss);
+ MAKE_ENTRY(page_create);
+ MAKE_ENTRY(page_in);
+ MAKE_ENTRY(page_out);
+ MAKE_ENTRY(ro_evict);
+ MAKE_ENTRY(rw_evict);
+ MAKE_ENTRY(page_trickle);
+ MAKE_ENTRY(pages);
+ MAKE_ENTRY(page_clean);
+ MAKE_ENTRY(page_dirty);
+ MAKE_ENTRY(hash_buckets);
+ MAKE_ENTRY(hash_searches);
+ MAKE_ENTRY(hash_longest);
+ MAKE_ENTRY(hash_examined);
+ MAKE_ENTRY(hash_nowait);
+ MAKE_ENTRY(hash_wait);
+#if (DBVER >= 45)
+ MAKE_ENTRY(hash_max_nowait);
+#endif
+ MAKE_ENTRY(hash_max_wait);
+ MAKE_ENTRY(region_wait);
+ MAKE_ENTRY(region_nowait);
+#if (DBVER >= 45)
+ MAKE_ENTRY(mvcc_frozen);
+ MAKE_ENTRY(mvcc_thawed);
+ MAKE_ENTRY(mvcc_freed);
+#endif
+ MAKE_ENTRY(alloc);
+ MAKE_ENTRY(alloc_buckets);
+ MAKE_ENTRY(alloc_max_buckets);
+ MAKE_ENTRY(alloc_pages);
+ MAKE_ENTRY(alloc_max_pages);
+#if (DBVER >= 45)
+ MAKE_ENTRY(io_wait);
+#endif
+#if (DBVER >= 48)
+ MAKE_ENTRY(sync_interrupted);
+#endif
+
+#undef MAKE_ENTRY
+ free(gsp);
+
+ d2 = PyDict_New();
+ if (d2 == NULL) {
+ Py_DECREF(d);
+ if (fsp)
+ free(fsp);
+ return NULL;
+ }
+#define MAKE_ENTRY(name) _addIntToDict(d3, #name, (*fsp2)->st_##name)
+ for(fsp2=fsp;*fsp2; fsp2++) {
+ d3 = PyDict_New();
+ if (d3 == NULL) {
+ Py_DECREF(d);
+ Py_DECREF(d2);
+ if (fsp)
+ free(fsp);
+ return NULL;
+ }
+ MAKE_ENTRY(pagesize);
+ MAKE_ENTRY(cache_hit);
+ MAKE_ENTRY(cache_miss);
+ MAKE_ENTRY(map);
+ MAKE_ENTRY(page_create);
+ MAKE_ENTRY(page_in);
+ MAKE_ENTRY(page_out);
+ if(PyDict_SetItemString(d2, (*fsp2)->file_name, d3)) {
+ Py_DECREF(d);
+ Py_DECREF(d2);
+ Py_DECREF(d3);
+ if (fsp)
+ free(fsp);
+ return NULL;
+ }
+ Py_DECREF(d3);
+ }
+
+#undef MAKE_ENTRY
+ free(fsp);
+
+ r = Py_BuildValue("(OO)", d, d2);
+ Py_DECREF(d);
+ Py_DECREF(d2);
+ return r;
 }
 
-#if (DBVER >= 41)
+#if (DBVER >= 43)
 static PyObject*
-DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+DBEnv_memp_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
 {
 int err;
- u_int32_t flags=0;
- char *file = NULL;
- char *database = NULL;
- PyObject *txnobj = NULL;
- DB_TXN *txn = NULL;
- static char* kwnames[] = { "file", "database", "txn", "flags",
- NULL };
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
 
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
-		&file, &database, &txnobj, &flags)) {
-	return NULL;
- }
- if (!checkTxnObj(txnobj, &txn)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->memp_stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
+static PyObject*
+DBEnv_memp_trickle(DBEnvObject* self, PyObject* args)
+{
+ int err, percent, nwrotep;
+
+ if (!PyArg_ParseTuple(args, "i:memp_trickle", &percent))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->memp_trickle(self->db_env, percent, &nwrotep);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(nwrotep);
+}
+
+static PyObject*
+DBEnv_memp_sync(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ DB_LSN lsn = {0, 0};
+ DB_LSN *lsn_p = NULL;
+
+ if (!PyArg_ParseTuple(args, "|(ii):memp_sync", &lsn.file, &lsn.offset))
+ return NULL;
+ if ((lsn.file!=0) || (lsn.offset!=0)) {
+ lsn_p = &lsn;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->memp_sync(self->db_env, lsn_p);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_remove(DBEnvObject* self, PyObject* args)
+{
+ int err, flags=0;
+ char *db_home;
+
+ if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->remove(self->db_env, db_home, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ u_int32_t flags=0;
+ char *file = NULL;
+ char *database = NULL;
+ PyObject *txnobj = NULL;
+ DB_TXN *txn = NULL;
+ static char* kwnames[] = { "file", "database", "txn", "flags",
+ NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
+		&file, &database, &txnobj, &flags)) {
+	return NULL;
+ }
+ if (!checkTxnObj(txnobj, &txn)) {
 return NULL;
 }
 CHECK_ENV_NOT_CLOSED(self);
@@ -4140,59 +4948,440 @@
 static char* kwnames[] = { "file", "database", "newname", "txn",
 "flags", NULL };
 
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
-		&file, &database, &newname, &txnobj, &flags)) {
-	return NULL;
- }
- if (!checkTxnObj(txnobj, &txn)) {
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
+		&file, &database, &newname, &txnobj, &flags)) {
+	return NULL;
+ }
+ if (!checkTxnObj(txnobj, &txn)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
+ flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+
+
+static PyObject*
+DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ u_int32_t flags=0;
+ char *passwd = NULL;
+ static char* kwnames[] = { "passwd", "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
+		&passwd, &flags)) {
+	return NULL;
+ }
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_encrypt(self->db_env, passwd, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_encrypt_flags(DBEnvObject* self)
+{
+ int err;
+ u_int32_t flags;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_encrypt_flags(self->db_env, &flags);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return NUMBER_FromLong(flags);
+}
+
+static PyObject*
+DBEnv_get_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ int flag;
+ u_int32_t timeout;
+ static char* kwnames[] = {"flag", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:get_timeout", kwnames,
+ &flag)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_timeout(self->db_env, &timeout, flag);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(timeout);
+}
+#endif
+
+
+static PyObject*
+DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ u_int32_t flags=0;
+ u_int32_t timeout = 0;
+ static char* kwnames[] = { "timeout", "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
+		&timeout, &flags)) {
+	return NULL;
+ }
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ long shm_key = 0;
+
+ if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ err = self->db_env->set_shm_key(self->db_env, shm_key);
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_shm_key(DBEnvObject* self)
+{
+ int err;
+ long shm_key;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_shm_key(self->db_env, &shm_key);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return NUMBER_FromLong(shm_key);
+}
+#endif
+
+#if (DBVER >= 46)
+static PyObject*
+DBEnv_set_cache_max(DBEnvObject* self, PyObject* args)
+{
+ int err, gbytes, bytes;
+
+ if (!PyArg_ParseTuple(args, "ii:set_cache_max",
+ &gbytes, &bytes))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_cache_max(self->db_env, gbytes, bytes);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_get_cache_max(DBEnvObject* self)
+{
+ int err;
+ u_int32_t gbytes, bytes;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_cache_max(self->db_env, &gbytes, &bytes);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return Py_BuildValue("(ii)", gbytes, bytes);
+}
+#endif
+
+#if (DBVER >= 46)
+static PyObject*
+DBEnv_set_thread_count(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ u_int32_t count;
+
+ if (!PyArg_ParseTuple(args, "i:set_thread_count", &count))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_thread_count(self->db_env, count);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_get_thread_count(DBEnvObject* self)
+{
+ int err;
+ u_int32_t count;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_thread_count(self->db_env, &count);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(count);
+}
+#endif
+
+static PyObject*
+DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
+{
+ int err, gbytes=0, bytes=0, ncache=0;
+
+ if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
+ &gbytes, &bytes, &ncache))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_cachesize(DBEnvObject* self)
+{
+ int err;
+ u_int32_t gbytes, bytes;
+ int ncache;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_cachesize(self->db_env, &gbytes, &bytes, &ncache);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return Py_BuildValue("(iii)", gbytes, bytes, ncache);
+}
+#endif
+
+
+static PyObject*
+DBEnv_set_flags(DBEnvObject* self, PyObject* args)
+{
+ int err, flags=0, onoff=0;
+
+ if (!PyArg_ParseTuple(args, "ii:set_flags",
+ &flags, &onoff))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_flags(self->db_env, flags, onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_flags(DBEnvObject* self)
+{
+ int err;
+ u_int32_t flags;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_flags(self->db_env, &flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(flags);
+}
+#endif
+
+#if (DBVER >= 47)
+static PyObject*
+DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
+{
+ int err, flags, onoff;
+
+ if (!PyArg_ParseTuple(args, "ii:log_set_config",
+ &flags, &onoff))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_set_config(self->db_env, flags, onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_log_get_config(DBEnvObject* self, PyObject* args)
+{
+ int err, flag, onoff;
+
+ if (!PyArg_ParseTuple(args, "i:log_get_config", &flag))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_get_config(self->db_env, flag, &onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return PyBool_FromLong(onoff);
+}
+#endif /* DBVER >= 47 */
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_mutex_set_max(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int value;
+
+ if (!PyArg_ParseTuple(args, "i:mutex_set_max", &value))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_set_max(self->db_env, value);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_mutex_get_max(DBEnvObject* self)
+{
+ int err;
+ u_int32_t value;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_get_max(self->db_env, &value);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return NUMBER_FromLong(value);
+}
+
+static PyObject*
+DBEnv_mutex_set_align(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int align;
+
+ if (!PyArg_ParseTuple(args, "i:mutex_set_align", &align))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_set_align(self->db_env, align);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_mutex_get_align(DBEnvObject* self)
+{
+ int err;
+ u_int32_t align;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_get_align(self->db_env, &align);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return NUMBER_FromLong(align);
+}
+
+static PyObject*
+DBEnv_mutex_set_increment(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int increment;
+
+ if (!PyArg_ParseTuple(args, "i:mutex_set_increment", &increment))
 return NULL;
- }
+
 CHECK_ENV_NOT_CLOSED(self);
+
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
- flags);
+ err = self->db_env->mutex_set_increment(self->db_env, increment);
 MYDB_END_ALLOW_THREADS;
+
 RETURN_IF_ERR();
 RETURN_NONE();
 }
 
 static PyObject*
-DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+DBEnv_mutex_get_increment(DBEnvObject* self)
 {
 int err;
- u_int32_t flags=0;
- char *passwd = NULL;
- static char* kwnames[] = { "passwd", "flags", NULL };
+ u_int32_t increment;
 
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
-		&passwd, &flags)) {
-	return NULL;
- }
+ CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->set_encrypt(self->db_env, passwd, flags);
+ err = self->db_env->mutex_get_increment(self->db_env, &increment);
 MYDB_END_ALLOW_THREADS;
 
 RETURN_IF_ERR();
- RETURN_NONE();
+
+ return NUMBER_FromLong(increment);
 }
-#endif /* DBVER >= 41 */
 
 static PyObject*
-DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+DBEnv_mutex_set_tas_spins(DBEnvObject* self, PyObject* args)
 {
 int err;
- u_int32_t flags=0;
- u_int32_t timeout = 0;
- static char* kwnames[] = { "timeout", "flags", NULL };
+ int tas_spins;
 
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
-		&timeout, &flags)) {
-	return NULL;
- }
+ if (!PyArg_ParseTuple(args, "i:mutex_set_tas_spins", &tas_spins))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
+ err = self->db_env->mutex_set_tas_spins(self->db_env, tas_spins);
 MYDB_END_ALLOW_THREADS;
 
 RETURN_IF_ERR();
@@ -4200,93 +5389,113 @@
 }
 
 static PyObject*
-DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
+DBEnv_mutex_get_tas_spins(DBEnvObject* self)
 {
 int err;
- long shm_key = 0;
+ u_int32_t tas_spins;
 
- if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
- return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 
- err = self->db_env->set_shm_key(self->db_env, shm_key);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_get_tas_spins(self->db_env, &tas_spins);
+ MYDB_END_ALLOW_THREADS;
+
 RETURN_IF_ERR();
- RETURN_NONE();
+
+ return NUMBER_FromLong(tas_spins);
 }
+#endif
 
 static PyObject*
-DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
+DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
 {
- int err, gbytes=0, bytes=0, ncache=0;
+ int err;
+ char *dir;
 
- if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
- &gbytes, &bytes, &ncache))
+ if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
 return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
+ err = self->db_env->set_data_dir(self->db_env, dir);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 RETURN_NONE();
 }
 
-
+#if (DBVER >= 42)
 static PyObject*
-DBEnv_set_flags(DBEnvObject* self, PyObject* args)
+DBEnv_get_data_dirs(DBEnvObject* self)
 {
- int err, flags=0, onoff=0;
+ int err;
+ PyObject *tuple;
+ PyObject *item;
+ const char **dirpp;
+ int size, i;
 
- if (!PyArg_ParseTuple(args, "ii:set_flags",
- &flags, &onoff))
- return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->set_flags(self->db_env, flags, onoff);
+ err = self->db_env->get_data_dirs(self->db_env, &dirpp);
 MYDB_END_ALLOW_THREADS;
+
 RETURN_IF_ERR();
- RETURN_NONE();
-}
 
+ /*
+ ** Calculate size. Python C API
+ ** actually allows for tuple resizing,
+ ** but this is simple enough.
+ */
+ for (size=0; *(dirpp+size) ; size++);
+
+ tuple = PyTuple_New(size);
+ if (!tuple)
+ return NULL;
 
-#if (DBVER >= 47)
+ for (i=0; i<size; i++) {
+ item = PyBytes_FromString (*(dirpp+i));
+ if (item == NULL) {
+ Py_DECREF(tuple);
+ tuple = NULL;
+ break;
+ }
+ PyTuple_SET_ITEM(tuple, i, item);
+ }
+ return tuple;
+}
+#endif
+
+#if (DBVER >= 44)
 static PyObject*
-DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
+DBEnv_set_lg_filemode(DBEnvObject* self, PyObject* args)
 {
- int err, flags, onoff;
+ int err, filemode;
 
- if (!PyArg_ParseTuple(args, "ii:log_set_config",
- &flags, &onoff))
+ if (!PyArg_ParseTuple(args, "i:set_lg_filemode", &filemode))
 return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->log_set_config(self->db_env, flags, onoff);
+ err = self->db_env->set_lg_filemode(self->db_env, filemode);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 RETURN_NONE();
 }
-#endif /* DBVER >= 47 */
-
 
 static PyObject*
-DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
+DBEnv_get_lg_filemode(DBEnvObject* self)
 {
- int err;
- char *dir;
+ int err, filemode;
 
- if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
- return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->set_data_dir(self->db_env, dir);
+ err = self->db_env->get_lg_filemode(self->db_env, &filemode);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
- RETURN_NONE();
+ return NUMBER_FromLong(filemode);
 }
-
+#endif
 
 static PyObject*
 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
@@ -4304,6 +5513,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lg_bsize(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lg_bsize;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lg_bsize(self->db_env, &lg_bsize);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lg_bsize);
+}
+#endif
 
 static PyObject*
 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
@@ -4322,6 +5547,23 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lg_dir(DBEnvObject* self)
+{
+ int err;
+ const char *dirp;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lg_dir(self->db_env, &dirp);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return PyBytes_FromString(dirp);
+}
+#endif
+
 static PyObject*
 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
 {
@@ -4372,6 +5614,55 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lg_regionmax(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lg_regionmax;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lg_regionmax(self->db_env, &lg_regionmax);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lg_regionmax);
+}
+#endif
+
+#if (DBVER >= 47)
+static PyObject*
+DBEnv_set_lk_partitions(DBEnvObject* self, PyObject* args)
+{
+ int err, lk_partitions;
+
+ if (!PyArg_ParseTuple(args, "i:set_lk_partitions", &lk_partitions))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_lk_partitions(self->db_env, lk_partitions);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_get_lk_partitions(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lk_partitions;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lk_partitions(self->db_env, &lk_partitions);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lk_partitions);
+}
+#endif
 
 static PyObject*
 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
@@ -4389,6 +5680,23 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lk_detect(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lk_detect;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lk_detect(self->db_env, &lk_detect);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lk_detect);
+}
+#endif
+
 
 #if (DBVER < 45)
 static PyObject*
@@ -4426,6 +5734,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lk_max_locks(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lk_max;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lk_max_locks(self->db_env, &lk_max);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lk_max);
+}
+#endif
 
 static PyObject*
 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
@@ -4443,6 +5767,22 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lk_max_lockers(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lk_max;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lk_max_lockers(self->db_env, &lk_max);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lk_max);
+}
+#endif
 
 static PyObject*
 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
@@ -4460,6 +5800,40 @@
 RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lk_max_objects(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lk_max;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lk_max_objects(self->db_env, &lk_max);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lk_max);
+}
+#endif
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_mp_mmapsize(DBEnvObject* self)
+{
+ int err;
+ size_t mmapsize;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_mp_mmapsize(self->db_env, &mmapsize);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(mmapsize);
+}
+#endif
+
 
 static PyObject*
 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
@@ -4496,6 +5870,26 @@
 }
 
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_tmp_dir(DBEnvObject* self)
+{
+ int err;
+ const char *dirpp;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_tmp_dir(self->db_env, &dirpp);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+
+ return PyBytes_FromString(dirpp);
+}
+#endif
+
+
 static PyObject*
 DBEnv_txn_recover(DBEnvObject* self)
 {
@@ -4535,7 +5929,7 @@
 Py_DECREF(list);
 return NULL;
 }
- txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
+ txn=newDBTxnObject(self, NULL, preplist[i].txn, 0);
 if (!txn) {
 Py_DECREF(list);
 Py_DECREF(gid);
@@ -4603,11 +5997,29 @@
 CHECK_ENV_NOT_CLOSED(self);
 
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
+ err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_tx_max(DBEnvObject* self)
+{
+ int err;
+ u_int32_t max;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_tx_max(self->db_env, &max);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
- RETURN_NONE();
+ return PyLong_FromUnsignedLong(max);
 }
+#endif
 
 
 static PyObject*
@@ -4619,12 +6031,31 @@
 return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 
+ MYDB_BEGIN_ALLOW_THREADS;
 err = self->db_env->set_tx_max(self->db_env, max);
+ MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 RETURN_NONE();
 }
 
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_tx_timestamp(DBEnvObject* self)
+{
+ int err;
+ time_t timestamp;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_tx_timestamp(self->db_env, &timestamp);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(timestamp);
+}
+#endif
+
 static PyObject*
 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
 {
@@ -4636,7 +6067,9 @@
 return NULL;
 CHECK_ENV_NOT_CLOSED(self);
 timestamp = (time_t)stamp;
+ MYDB_BEGIN_ALLOW_THREADS;
 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
+ MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
 RETURN_NONE();
 }
@@ -4730,6 +6163,26 @@
 
 #if (DBVER >= 44)
 static PyObject*
+DBEnv_fileid_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ char *file;
+ u_int32_t flags = 0;
+ static char* kwnames[] = { "file", "flags", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:fileid_reset", kwnames,
+ &file, &flags))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->fileid_reset(self->db_env, file, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
 {
 int err;
@@ -4750,6 +6203,30 @@
 }
 #endif /* DBVER >= 4.4 */
 
+
+#if (DBVER >= 43)
+static PyObject*
+DBEnv_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
 static PyObject*
 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
 {
@@ -4785,9 +6262,6 @@
 MAKE_ENTRY(lg_size);
 MAKE_ENTRY(record);
 #endif
-#if (DBVER < 41)
- MAKE_ENTRY(lg_max);
-#endif
 MAKE_ENTRY(w_mbytes);
 MAKE_ENTRY(w_bytes);
 MAKE_ENTRY(wc_mbytes);
@@ -4814,6 +6288,29 @@
 } /* DBEnv_log_stat */
 
 
+#if (DBVER >= 43)
+static PyObject*
+DBEnv_log_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:log_stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
 static PyObject*
 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
 {
@@ -4840,13 +6337,8 @@
 
 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
 
-#if (DBVER < 41)
- MAKE_ENTRY(lastid);
-#endif
-#if (DBVER >=41)
 MAKE_ENTRY(id);
 MAKE_ENTRY(cur_maxid);
-#endif
 MAKE_ENTRY(nmodes);
 MAKE_ENTRY(maxlocks);
 MAKE_ENTRY(maxlockers);
@@ -4871,10 +6363,8 @@
 MAKE_ENTRY(lock_wait);
 #endif
 MAKE_ENTRY(ndeadlocks);
-#if (DBVER >= 41)
 MAKE_ENTRY(locktimeout);
 MAKE_ENTRY(txntimeout);
-#endif
 MAKE_ENTRY(nlocktimeouts);
 MAKE_ENTRY(ntxntimeouts);
 #if (DBVER >= 46)
@@ -4900,6 +6390,45 @@
 return d;
 }
 
+#if (DBVER >= 43)
+static PyObject*
+DBEnv_lock_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:lock_stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->lock_stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
+static PyObject*
+DBEnv_log_cursor(DBEnvObject* self)
+{
+ int err;
+ DB_LOGC* dblogc;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_cursor(self->db_env, &dblogc, 0);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return (PyObject*) newDBLogCursorObject(dblogc, self);
+}
+
+
 static PyObject*
 DBEnv_log_flush(DBEnvObject* self)
 {
@@ -4916,51 +6445,224 @@
 }
 
 static PyObject*
-DBEnv_log_archive(DBEnvObject* self, PyObject* args)
+DBEnv_log_file(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ DB_LSN lsn = {0, 0};
+ int size = 20;
+ char *name = NULL;
+ PyObject *retval;
+
+ if (!PyArg_ParseTuple(args, "(ii):log_file", &lsn.file, &lsn.offset))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ do {
+ name = malloc(size);
+ if (!name) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_file(self->db_env, &lsn, name, size);
+ MYDB_END_ALLOW_THREADS;
+ if (err == EINVAL) {
+ free(name);
+ size *= 2;
+ } else if (err) {
+ free(name);
+ RETURN_IF_ERR();
+ assert(0); /* Unreachable... supposely */
+ return NULL;
+ }
+/*
+** If the final buffer we try is too small, we will
+** get this exception:
+** DBInvalidArgError:
+** (22, 'Invalid argument -- DB_ENV->log_file: name buffer is too short')
+*/
+ } while ((err == EINVAL) && (size<(1<<17)));
+
+ RETURN_IF_ERR(); /* Maybe the size is not the problem */
+
+ retval = Py_BuildValue("s", name);
+ free(name);
+ return retval;
+}
+
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_log_printf(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ char *string;
+ PyObject *txnobj = NULL;
+ DB_TXN *txn = NULL;
+ static char* kwnames[] = {"string", "txn", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O:log_printf", kwnames,
+ &string, &txnobj))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ if (!checkTxnObj(txnobj, &txn))
+ return NULL;
+
+ /*
+ ** Do not use the format string directly, to avoid attacks.
+ */
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_printf(self->db_env, txn, "%s", string);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
+static PyObject*
+DBEnv_log_archive(DBEnvObject* self, PyObject* args)
+{
+ int flags=0;
+ int err;
+ char **log_list = NULL;
+ PyObject* list;
+ PyObject* item = NULL;
+
+ if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_archive(self->db_env, &log_list, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ list = PyList_New(0);
+ if (list == NULL) {
+ if (log_list)
+ free(log_list);
+ return NULL;
+ }
+
+ if (log_list) {
+ char **log_list_start;
+ for (log_list_start = log_list; *log_list != NULL; ++log_list) {
+ item = PyBytes_FromString (*log_list);
+ if (item == NULL) {
+ Py_DECREF(list);
+ list = NULL;
+ break;
+ }
+ if (PyList_Append(list, item)) {
+ Py_DECREF(list);
+ list = NULL;
+ Py_DECREF(item);
+ break;
+ }
+ Py_DECREF(item);
+ }
+ free(log_list_start);
+ }
+ return list;
+}
+
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_mutex_stat(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ DB_MUTEX_STAT* statp = NULL;
+ PyObject* d = NULL;
+ u_int32_t flags = 0;
+
+ if (!PyArg_ParseTuple(args, "|i:mutex_stat", &flags))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_stat(self->db_env, &statp, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ /* Turn the stat structure into a dictionary */
+ d = PyDict_New();
+ if (d == NULL) {
+ if (statp)
+ free(statp);
+ return NULL;
+ }
+
+#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
+
+ MAKE_ENTRY(mutex_align);
+ MAKE_ENTRY(mutex_tas_spins);
+ MAKE_ENTRY(mutex_cnt);
+ MAKE_ENTRY(mutex_free);
+ MAKE_ENTRY(mutex_inuse);
+ MAKE_ENTRY(mutex_inuse_max);
+ MAKE_ENTRY(regsize);
+ MAKE_ENTRY(region_wait);
+ MAKE_ENTRY(region_nowait);
+
+#undef MAKE_ENTRY
+ free(statp);
+ return d;
+}
+#endif
+
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_mutex_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:mutex_stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->mutex_stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
+#if (DBVER >= 43)
+static PyObject*
+DBEnv_txn_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
 {
- int flags=0;
 int err;
- char **log_list = NULL;
- PyObject* list;
- PyObject* item = NULL;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
 
- if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
+ kwnames, &flags))
+ {
 return NULL;
+ }
 
 CHECK_ENV_NOT_CLOSED(self);
+
 MYDB_BEGIN_ALLOW_THREADS;
- err = self->db_env->log_archive(self->db_env, &log_list, flags);
+ err = self->db_env->txn_stat_print(self->db_env, flags);
 MYDB_END_ALLOW_THREADS;
 RETURN_IF_ERR();
-
- list = PyList_New(0);
- if (list == NULL) {
- if (log_list)
- free(log_list);
- return NULL;
- }
-
- if (log_list) {
- char **log_list_start;
- for (log_list_start = log_list; *log_list != NULL; ++log_list) {
- item = PyBytes_FromString (*log_list);
- if (item == NULL) {
- Py_DECREF(list);
- list = NULL;
- break;
- }
- if (PyList_Append(list, item)) {
- Py_DECREF(list);
- list = NULL;
- Py_DECREF(item);
- break;
- }
- Py_DECREF(item);
- }
- free(log_list_start);
- }
- return list;
+ RETURN_NONE();
 }
+#endif
 
 
 static PyObject*
@@ -5079,6 +6781,83 @@
 }
 #endif
 
+#if (DBVER >= 43)
+static PyObject*
+DBEnv_set_mp_max_openfd(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int maxopenfd;
+
+ if (!PyArg_ParseTuple(args, "i:set_mp_max_openfd", &maxopenfd)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_mp_max_openfd(self->db_env, maxopenfd);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_get_mp_max_openfd(DBEnvObject* self)
+{
+ int err;
+ int maxopenfd;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_mp_max_openfd(self->db_env, &maxopenfd);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(maxopenfd);
+}
+
+
+static PyObject*
+DBEnv_set_mp_max_write(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int maxwrite, maxwrite_sleep;
+
+ if (!PyArg_ParseTuple(args, "ii:set_mp_max_write", &maxwrite,
+ &maxwrite_sleep)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_mp_max_write(self->db_env, maxwrite,
+ maxwrite_sleep);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_get_mp_max_write(DBEnvObject* self)
+{
+ int err;
+ int maxwrite;
+#if (DBVER >= 46)
+ db_timeout_t maxwrite_sleep;
+#else
+ int maxwrite_sleep;
+#endif
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_mp_max_write(self->db_env, &maxwrite,
+ &maxwrite_sleep);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ return Py_BuildValue("(ii)", maxwrite, (int)maxwrite_sleep);
+}
+#endif
+
+
 static PyObject*
 DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
 {
@@ -5635,6 +7414,175 @@
 }
 #endif
 
+
+#if (DBVER >= 47)
+static PyObject*
+DBEnv_rep_set_clockskew(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ unsigned int fast, slow;
+
+#if (PY_VERSION_HEX >= 0x02040000)
+ if (!PyArg_ParseTuple(args,"II:rep_set_clockskew", &fast, &slow))
+ return NULL;
+#else
+ if (!PyArg_ParseTuple(args,"ii:rep_set_clockskew", &fast, &slow))
+ return NULL;
+#endif
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_clockskew(self->db_env, fast, slow);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_clockskew(DBEnvObject* self)
+{
+ int err;
+ unsigned int fast, slow;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_get_clockskew(self->db_env, &fast, &slow);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+#if (PY_VERSION_HEX >= 0x02040000)
+ return Py_BuildValue("(II)", fast, slow);
+#else
+ return Py_BuildValue("(ii)", fast, slow);
+#endif
+}
+#endif
+
+#if (DBVER >= 43)
+static PyObject*
+DBEnv_rep_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+static PyObject*
+DBEnv_rep_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ DB_REP_STAT *statp;
+ PyObject *stats;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_stat(self->db_env, &statp, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ stats=PyDict_New();
+ if (stats == NULL) {
+ free(statp);
+ return NULL;
+ }
+
+#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
+#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(stats , #name, statp->st_##name)
+
+#if (DBVER >= 44)
+ MAKE_ENTRY(bulk_fills);
+ MAKE_ENTRY(bulk_overflows);
+ MAKE_ENTRY(bulk_records);
+ MAKE_ENTRY(bulk_transfers);
+ MAKE_ENTRY(client_rerequests);
+ MAKE_ENTRY(client_svc_miss);
+ MAKE_ENTRY(client_svc_req);
+#endif
+ MAKE_ENTRY(dupmasters);
+#if (DBVER >= 43)
+ MAKE_ENTRY(egen);
+ MAKE_ENTRY(election_nvotes);
+ MAKE_ENTRY(startup_complete);
+ MAKE_ENTRY(pg_duplicated);
+ MAKE_ENTRY(pg_records);
+ MAKE_ENTRY(pg_requested);
+ MAKE_ENTRY(next_pg);
+ MAKE_ENTRY(waiting_pg);
+#endif
+ MAKE_ENTRY(election_cur_winner);
+ MAKE_ENTRY(election_gen);
+ MAKE_DB_LSN_ENTRY(election_lsn);
+ MAKE_ENTRY(election_nsites);
+ MAKE_ENTRY(election_priority);
+#if (DBVER >= 44)
+ MAKE_ENTRY(election_sec);
+ MAKE_ENTRY(election_usec);
+#endif
+ MAKE_ENTRY(election_status);
+ MAKE_ENTRY(election_tiebreaker);
+ MAKE_ENTRY(election_votes);
+ MAKE_ENTRY(elections);
+ MAKE_ENTRY(elections_won);
+ MAKE_ENTRY(env_id);
+ MAKE_ENTRY(env_priority);
+ MAKE_ENTRY(gen);
+ MAKE_ENTRY(log_duplicated);
+ MAKE_ENTRY(log_queued);
+ MAKE_ENTRY(log_queued_max);
+ MAKE_ENTRY(log_queued_total);
+ MAKE_ENTRY(log_records);
+ MAKE_ENTRY(log_requested);
+ MAKE_ENTRY(master);
+ MAKE_ENTRY(master_changes);
+#if (DBVER >= 47)
+ MAKE_ENTRY(max_lease_sec);
+ MAKE_ENTRY(max_lease_usec);
+ MAKE_DB_LSN_ENTRY(max_perm_lsn);
+#endif
+ MAKE_ENTRY(msgs_badgen);
+ MAKE_ENTRY(msgs_processed);
+ MAKE_ENTRY(msgs_recover);
+ MAKE_ENTRY(msgs_send_failures);
+ MAKE_ENTRY(msgs_sent);
+ MAKE_ENTRY(newsites);
+ MAKE_DB_LSN_ENTRY(next_lsn);
+ MAKE_ENTRY(nsites);
+ MAKE_ENTRY(nthrottles);
+ MAKE_ENTRY(outdated);
+#if (DBVER >= 46)
+ MAKE_ENTRY(startsync_delayed);
+#endif
+ MAKE_ENTRY(status);
+ MAKE_ENTRY(txns_applied);
+ MAKE_DB_LSN_ENTRY(waiting_lsn);
+
+#undef MAKE_DB_LSN_ENTRY
+#undef MAKE_ENTRY
+
+ free(statp);
+ return stats;
+}
+
 /* --------------------------------------------------------------------- */
 /* REPLICATION METHODS: Replication Manager */
 
@@ -6076,6 +8024,76 @@
 return NUMBER_FromLong(id);
 }
 
+
+static PyObject*
+DBTxn_set_timeout(DBTxnObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ u_int32_t flags=0;
+ u_int32_t timeout = 0;
+ static char* kwnames[] = { "timeout", "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
+		&timeout, &flags)) {
+	return NULL;
+ }
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->txn->set_timeout(self->txn, (db_timeout_t)timeout, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+
+#if (DBVER >= 44)
+static PyObject*
+DBTxn_set_name(DBTxnObject* self, PyObject* args)
+{
+ int err;
+ const char *name;
+
+ if (!PyArg_ParseTuple(args, "s:set_name", &name))
+ return NULL;
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->txn->set_name(self->txn, name);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
+#if (DBVER >= 44)
+static PyObject*
+DBTxn_get_name(DBTxnObject* self)
+{
+ int err;
+ const char *name;
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->txn->get_name(self->txn, &name);
+ MYDB_END_ALLOW_THREADS;
+
+ RETURN_IF_ERR();
+#if (PY_VERSION_HEX < 0x03000000)
+ if (!name) {
+ return PyString_FromString("");
+ }
+ return PyString_FromString(name);
+#else
+ if (!name) {
+ return PyUnicode_FromString("");
+ }
+ return PyUnicode_FromString(name);
+#endif
+}
+#endif
+
+
 #if (DBVER >= 43)
 /* --------------------------------------------------------------------- */
 /* DBSequence methods */
@@ -6179,12 +8197,12 @@
 }
 
 static PyObject*
-DBSequence_init_value(DBSequenceObject* self, PyObject* args)
+DBSequence_initial_value(DBSequenceObject* self, PyObject* args)
 {
 int err;
 PY_LONG_LONG value;
 db_seq_t value2;
- if (!PyArg_ParseTuple(args,"L:init_value", &value))
+ if (!PyArg_ParseTuple(args,"L:initial_value", &value))
 return NULL;
 CHECK_SEQUENCE_NOT_CLOSED(self)
 
@@ -6362,6 +8380,29 @@
 return Py_BuildValue("(LL)", min, max);
 }
 
+
+static PyObject*
+DBSequence_stat_print(DBSequenceObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+
+ CHECK_SEQUENCE_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->sequence->stat_print(self->sequence, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
 static PyObject*
 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
 {
@@ -6413,11 +8454,18 @@
 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
 {"close", (PyCFunction)DB_close, METH_VARARGS},
+#if (DBVER >= 47)
+ {"compact", (PyCFunction)DB_compact, METH_VARARGS|METH_KEYWORDS},
+#endif
 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
+#if (DBVER >= 46)
+ {"exists", (PyCFunction)DB_exists,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
@@ -6434,24 +8482,70 @@
 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_bt_minkey", (PyCFunction)DB_get_bt_minkey, METH_NOARGS},
+#endif
 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
-#if (DBVER >= 41)
+#if (DBVER >= 42)
+ {"get_cachesize", (PyCFunction)DB_get_cachesize, METH_NOARGS},
+#endif
 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 42)
+ {"get_encrypt_flags", (PyCFunction)DB_get_encrypt_flags, METH_NOARGS},
 #endif
+
 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_flags", (PyCFunction)DB_get_flags, METH_NOARGS},
+#endif
 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_h_ffactor", (PyCFunction)DB_get_h_ffactor, METH_NOARGS},
+#endif
 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_h_nelem", (PyCFunction)DB_get_h_nelem, METH_NOARGS},
+#endif
 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lorder", (PyCFunction)DB_get_lorder, METH_NOARGS},
+#endif
 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_pagesize", (PyCFunction)DB_get_pagesize, METH_NOARGS},
+#endif
 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_re_delim", (PyCFunction)DB_get_re_delim, METH_NOARGS},
+#endif
 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_re_len", (PyCFunction)DB_get_re_len, METH_NOARGS},
+#endif
 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_re_pad", (PyCFunction)DB_get_re_pad, METH_NOARGS},
+#endif
 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_re_source", (PyCFunction)DB_get_re_source, METH_NOARGS},
+#endif
 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_q_extentsize",(PyCFunction)DB_get_q_extentsize, METH_NOARGS},
+#endif
 {"set_private", (PyCFunction)DB_set_private, METH_O},
 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
+#if (DBVER >= 46)
+ {"set_priority", (PyCFunction)DB_set_priority, METH_VARARGS},
+ {"get_priority", (PyCFunction)DB_get_priority, METH_NOARGS},
+#endif
 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 43)
+ {"stat_print", (PyCFunction)DB_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
@@ -6463,6 +8557,20 @@
 };
 
 
+/* We need this to support __contains__() */
+static PySequenceMethods DB_sequence = {
+ 0, /* sq_length, mapping wins here */
+ 0, /* sq_concat */
+ 0, /* sq_repeat */
+ 0, /* sq_item */
+ 0, /* sq_slice */
+ 0, /* sq_ass_item */
+ 0, /* sq_ass_slice */
+ (objobjproc)DB_contains, /* sq_contains */
+ 0, /* sq_inplace_concat */
+ 0, /* sq_inplace_repeat */
+};
+
 static PyMappingMethods DB_mapping = {
 DB_length, /*mp_length*/
 (binaryfunc)DB_subscript, /*mp_subscript*/
@@ -6493,8 +8601,29 @@
 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 46)
+ {"prev_dup", (PyCFunction)DBC_prev_dup,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
+#if (DBVER >= 46)
+ {"set_priority", (PyCFunction)DBC_set_priority,
+ METH_VARARGS|METH_KEYWORDS},
+ {"get_priority", (PyCFunction)DBC_get_priority, METH_NOARGS},
+#endif
+ {NULL, NULL} /* sentinel */
+};
+
+
+static PyMethodDef DBLogCursor_methods[] = {
+ {"close", (PyCFunction)DBLogCursor_close, METH_NOARGS},
+ {"current", (PyCFunction)DBLogCursor_current, METH_NOARGS},
+ {"first", (PyCFunction)DBLogCursor_first, METH_NOARGS},
+ {"last", (PyCFunction)DBLogCursor_last, METH_NOARGS},
+ {"next", (PyCFunction)DBLogCursor_next, METH_NOARGS},
+ {"prev", (PyCFunction)DBLogCursor_prev, METH_NOARGS},
+ {"set", (PyCFunction)DBLogCursor_set, METH_VARARGS},
 {NULL, NULL} /* sentinel */
 };
 
@@ -6503,59 +8632,178 @@
 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
-#if (DBVER >= 41)
 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 46)
+ {"set_thread_count", (PyCFunction)DBEnv_set_thread_count, METH_VARARGS},
+ {"get_thread_count", (PyCFunction)DBEnv_get_thread_count, METH_NOARGS},
+#endif
 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 42)
+ {"get_encrypt_flags", (PyCFunction)DBEnv_get_encrypt_flags, METH_NOARGS},
+ {"get_timeout", (PyCFunction)DBEnv_get_timeout,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+ {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
+ {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_shm_key", (PyCFunction)DBEnv_get_shm_key, METH_NOARGS},
+#endif
+#if (DBVER >= 46)
+ {"set_cache_max", (PyCFunction)DBEnv_set_cache_max, METH_VARARGS},
+ {"get_cache_max", (PyCFunction)DBEnv_get_cache_max, METH_NOARGS},
+#endif
+ {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_cachesize", (PyCFunction)DBEnv_get_cachesize, METH_NOARGS},
+#endif
+ {"memp_trickle", (PyCFunction)DBEnv_memp_trickle, METH_VARARGS},
+ {"memp_sync", (PyCFunction)DBEnv_memp_sync, METH_VARARGS},
+ {"memp_stat", (PyCFunction)DBEnv_memp_stat,
+ METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 43)
+ {"memp_stat_print", (PyCFunction)DBEnv_memp_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+#if (DBVER >= 44)
+ {"mutex_set_max", (PyCFunction)DBEnv_mutex_set_max, METH_VARARGS},
+ {"mutex_get_max", (PyCFunction)DBEnv_mutex_get_max, METH_NOARGS},
+ {"mutex_set_align", (PyCFunction)DBEnv_mutex_set_align, METH_VARARGS},
+ {"mutex_get_align", (PyCFunction)DBEnv_mutex_get_align, METH_NOARGS},
+ {"mutex_set_increment", (PyCFunction)DBEnv_mutex_set_increment,
+ METH_VARARGS},
+ {"mutex_get_increment", (PyCFunction)DBEnv_mutex_get_increment,
+ METH_NOARGS},
+ {"mutex_set_tas_spins", (PyCFunction)DBEnv_mutex_set_tas_spins,
+ METH_VARARGS},
+ {"mutex_get_tas_spins", (PyCFunction)DBEnv_mutex_get_tas_spins,
+ METH_NOARGS},
+ {"mutex_stat", (PyCFunction)DBEnv_mutex_stat, METH_VARARGS},
+#if (DBVER >= 44)
+ {"mutex_stat_print", (PyCFunction)DBEnv_mutex_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+#endif
+ {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_data_dirs", (PyCFunction)DBEnv_get_data_dirs, METH_NOARGS},
+#endif
+#if (DBVER >= 42)
+ {"get_flags", (PyCFunction)DBEnv_get_flags, METH_NOARGS},
 #endif
- {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
- {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
- {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
- {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
- {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
+ {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
 #if (DBVER >= 47)
- {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
+ {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
+ {"log_get_config", (PyCFunction)DBEnv_log_get_config, METH_VARARGS},
+#endif
+ {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lg_bsize", (PyCFunction)DBEnv_get_lg_bsize, METH_NOARGS},
+#endif
+ {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lg_dir", (PyCFunction)DBEnv_get_lg_dir, METH_NOARGS},
 #endif
- {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
- {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
- {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
+ {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
 #if (DBVER >= 42)
- {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
+ {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
 #endif
 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
- {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lg_regionmax",(PyCFunction)DBEnv_get_lg_regionmax, METH_NOARGS},
+#endif
+#if (DBVER >= 44)
+ {"set_lg_filemode", (PyCFunction)DBEnv_set_lg_filemode, METH_VARARGS},
+ {"get_lg_filemode", (PyCFunction)DBEnv_get_lg_filemode, METH_NOARGS},
+#endif
+#if (DBVER >= 47)
+ {"set_lk_partitions", (PyCFunction)DBEnv_set_lk_partitions, METH_VARARGS},
+ {"get_lk_partitions", (PyCFunction)DBEnv_get_lk_partitions, METH_NOARGS},
+#endif
+ {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lk_detect", (PyCFunction)DBEnv_get_lk_detect, METH_NOARGS},
+#endif
 #if (DBVER < 45)
- {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
+ {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
 #endif
 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lk_max_locks", (PyCFunction)DBEnv_get_lk_max_locks, METH_NOARGS},
+#endif
 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lk_max_lockers", (PyCFunction)DBEnv_get_lk_max_lockers, METH_NOARGS},
+#endif
 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
- {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
- {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
- {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
- {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
- {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
- {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lk_max_objects", (PyCFunction)DBEnv_get_lk_max_objects, METH_NOARGS},
+#endif
+#if (DBVER >= 43)
+ {"stat_print", (PyCFunction)DBEnv_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+ {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_mp_mmapsize", (PyCFunction)DBEnv_get_mp_mmapsize, METH_NOARGS},
+#endif
+ {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_tmp_dir", (PyCFunction)DBEnv_get_tmp_dir, METH_NOARGS},
+#endif
+ {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
+ {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
+ {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
+#if (DBVER >= 43)
+ {"txn_stat_print", (PyCFunction)DBEnv_txn_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+#if (DBVER >= 42)
+ {"get_tx_max", (PyCFunction)DBEnv_get_tx_max, METH_NOARGS},
+ {"get_tx_timestamp", (PyCFunction)DBEnv_get_tx_timestamp, METH_NOARGS},
+#endif
+ {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
- {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
- {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
- {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
- {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
- {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
- {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
- {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
- {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
- {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
+ {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
+ {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
+ {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
+ {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
+ {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
+ {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
+#if (DBVER >= 43)
+ {"lock_stat_print", (PyCFunction)DBEnv_lock_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+ {"log_cursor", (PyCFunction)DBEnv_log_cursor, METH_NOARGS},
+ {"log_file", (PyCFunction)DBEnv_log_file, METH_VARARGS},
+#if (DBVER >= 44)
+ {"log_printf", (PyCFunction)DBEnv_log_printf,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+ {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
+ {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
+ {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
+#if (DBVER >= 43)
+ {"log_stat_print", (PyCFunction)DBEnv_log_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
 #if (DBVER >= 44)
- {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
+ {"fileid_reset", (PyCFunction)DBEnv_fileid_reset, METH_VARARGS|METH_KEYWORDS},
+ {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
 #endif
 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
- {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
+ {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
 #if (DBVER < 48)
 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
 METH_VARARGS||METH_KEYWORDS},
 #endif
- {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
+#if (DBVER >= 43)
+ {"set_mp_max_openfd", (PyCFunction)DBEnv_set_mp_max_openfd, METH_VARARGS},
+ {"get_mp_max_openfd", (PyCFunction)DBEnv_get_mp_max_openfd, METH_NOARGS},
+ {"set_mp_max_write", (PyCFunction)DBEnv_set_mp_max_write, METH_VARARGS},
+ {"get_mp_max_write", (PyCFunction)DBEnv_get_mp_max_write, METH_NOARGS},
+#endif
+ {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
 #if (DBVER >= 42)
 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
 #endif
@@ -6593,6 +8841,17 @@
 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
 #endif
+#if (DBVER >= 47)
+ {"rep_set_clockskew", (PyCFunction)DBEnv_rep_set_clockskew, METH_VARARGS},
+ {"rep_get_clockskew", (PyCFunction)DBEnv_rep_get_clockskew, METH_VARARGS},
+#endif
+ {"rep_stat", (PyCFunction)DBEnv_rep_stat,
+ METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 43)
+ {"rep_stat_print", (PyCFunction)DBEnv_rep_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
+
 #if (DBVER >= 45)
 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
 METH_VARARGS|METH_KEYWORDS},
@@ -6623,6 +8882,12 @@
 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
+ {"set_timeout", (PyCFunction)DBTxn_set_timeout,
+ METH_VARARGS|METH_KEYWORDS},
+#if (DBVER >= 44)
+ {"set_name", (PyCFunction)DBTxn_set_name, METH_VARARGS},
+ {"get_name", (PyCFunction)DBTxn_get_name, METH_NOARGS},
+#endif
 {NULL, NULL} /* sentinel */
 };
 
@@ -6633,7 +8898,7 @@
 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
- {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
+ {"initial_value", (PyCFunction)DBSequence_initial_value, METH_VARARGS},
 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
@@ -6643,6 +8908,8 @@
 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
+ {"stat_print", (PyCFunction)DBSequence_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
 {NULL, NULL} /* sentinel */
 };
 #endif
@@ -6656,7 +8923,9 @@
 CHECK_ENV_NOT_CLOSED(self);
 
 #if (DBVER >= 42)
+ MYDB_BEGIN_ALLOW_THREADS;
 self->db_env->get_home(self->db_env, &home);
+ MYDB_END_ALLOW_THREADS;
 #else
 home=self->db_env->db_home;
 #endif
@@ -6691,7 +8960,7 @@
 0, /*tp_compare*/
 0, /*tp_repr*/
 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
+ &DB_sequence,/*tp_as_sequence*/
 &DB_mapping,/*tp_as_mapping*/
 0, /*tp_hash*/
 0,			/* tp_call */
@@ -6759,6 +9028,49 @@
 };
 
 
+statichere PyTypeObject DBLogCursor_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
+ PyVarObject_HEAD_INIT(NULL, 0)
+#endif
+ "DBLogCursor", /*tp_name*/
+ sizeof(DBLogCursorObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ /* methods */
+ (destructor)DBLogCursor_dealloc,/*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ offsetof(DBLogCursorObject, in_weakreflist), /* tp_weaklistoffset */
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DBLogCursor_methods, /*tp_methods*/
+ 0, /*tp_members*/
+};
+
+
 statichere PyTypeObject DBEnv_Type = {
 #if (PY_VERSION_HEX < 0x03000000)
 PyObject_HEAD_INIT(NULL)
@@ -7043,14 +9355,26 @@
 {
 PyObject* m;
 PyObject* d;
- PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
- PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
- PyObject* cvsid_s = PyBytes_FromString( rcs_id );
 PyObject* py_api;
+ PyObject* pybsddb_version_s;
+ PyObject* db_version_s;
+ PyObject* cvsid_s;
+
+#if (PY_VERSION_HEX < 0x03000000)
+ pybsddb_version_s = PyString_FromString(PY_BSDDB_VERSION);
+ db_version_s = PyString_FromString(DB_VERSION_STRING);
+ cvsid_s = PyString_FromString(rcs_id);
+#else
+ /* This data should be ascii, so UTF-8 conversion is fine */
+ pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
+ db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
+ cvsid_s = PyUnicode_FromString(rcs_id);
+#endif
 
 /* Initialize object types */
 if ((PyType_Ready(&DB_Type) < 0)
 || (PyType_Ready(&DBCursor_Type) < 0)
+ || (PyType_Ready(&DBLogCursor_Type) < 0)
 || (PyType_Ready(&DBEnv_Type) < 0)
 || (PyType_Ready(&DBTxn_Type) < 0)
 || (PyType_Ready(&DBLock_Type) < 0)
@@ -7153,6 +9477,10 @@
 ADD_INT(d, DB_TXN_SYNC);
 ADD_INT(d, DB_TXN_NOWAIT);
 
+#if (DBVER >= 46)
+ ADD_INT(d, DB_TXN_WAIT);
+#endif
+
 ADD_INT(d, DB_EXCL);
 ADD_INT(d, DB_FCNTL_LOCKING);
 ADD_INT(d, DB_ODDFILESIZE);
@@ -7164,6 +9492,7 @@
 ADD_INT(d, DB_VERIFY);
 ADD_INT(d, DB_UPGRADE);
 
+ ADD_INT(d, DB_PRINTABLE);
 ADD_INT(d, DB_AGGRESSIVE);
 ADD_INT(d, DB_NOORDERCHK);
 ADD_INT(d, DB_ORDERCHKONLY);
@@ -7249,6 +9578,10 @@
 ADD_INT(d, DB_REVSPLITOFF);
 ADD_INT(d, DB_SNAPSHOT);
 
+#if (DBVER >= 43)
+ ADD_INT(d, DB_INORDER);
+#endif
+
 ADD_INT(d, DB_JOIN_NOSORT);
 
 ADD_INT(d, DB_AFTER);
@@ -7258,12 +9591,6 @@
 ADD_INT(d, DB_CACHED_COUNTS);
 #endif
 
-#if (DBVER >= 41)
- _addIntToDict(d, "DB_CHECKPOINT", 0);
-#else
- ADD_INT(d, DB_CHECKPOINT);
- ADD_INT(d, DB_CURLSN);
-#endif
 #if (DBVER <= 41)
 ADD_INT(d, DB_COMMIT);
 #endif
@@ -7274,6 +9601,7 @@
 ADD_INT(d, DB_FIRST);
 ADD_INT(d, DB_FLUSH);
 ADD_INT(d, DB_GET_BOTH);
+ ADD_INT(d, DB_GET_BOTH_RANGE);
 ADD_INT(d, DB_GET_RECNO);
 ADD_INT(d, DB_JOIN_ITEM);
 ADD_INT(d, DB_KEYFIRST);
@@ -7288,6 +9616,9 @@
 ADD_INT(d, DB_POSITION);
 ADD_INT(d, DB_PREV);
 ADD_INT(d, DB_PREV_NODUP);
+#if (DBVER >= 46)
+ ADD_INT(d, DB_PREV_DUP);
+#endif
 #if (DBVER < 45)
 ADD_INT(d, DB_RECORDCOUNT);
 #endif
@@ -7303,17 +9634,18 @@
 ADD_INT(d, DB_MULTIPLE_KEY);
 
 #if (DBVER >= 44)
+ ADD_INT(d, DB_IMMUTABLE_KEY);
 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
 ADD_INT(d, DB_READ_COMMITTED);
 #endif
 
+#if (DBVER >= 44)
+ ADD_INT(d, DB_FREELIST_ONLY);
+ ADD_INT(d, DB_FREE_SPACE);
+#endif
+
 ADD_INT(d, DB_DONOTINDEX);
 
-#if (DBVER >= 41)
- _addIntToDict(d, "DB_INCOMPLETE", 0);
-#else
- ADD_INT(d, DB_INCOMPLETE);
-#endif
 ADD_INT(d, DB_KEYEMPTY);
 ADD_INT(d, DB_KEYEXIST);
 ADD_INT(d, DB_LOCK_DEADLOCK);
@@ -7334,14 +9666,30 @@
 ADD_INT(d, DB_PANIC_ENVIRONMENT);
 ADD_INT(d, DB_NOPANIC);
 
-#if (DBVER >= 41)
 ADD_INT(d, DB_OVERWRITE);
+
+#if (DBVER >= 43)
+ ADD_INT(d, DB_STAT_SUBSYSTEM);
+ ADD_INT(d, DB_STAT_MEMP_HASH);
+#endif
+
+#if (DBVER >= 48)
+ ADD_INT(d, DB_OVERWRITE_DUP);
 #endif
 
-#ifdef DB_REGISTER
+#if (DBVER >= 47)
+ ADD_INT(d, DB_FOREIGN_ABORT);
+ ADD_INT(d, DB_FOREIGN_CASCADE);
+ ADD_INT(d, DB_FOREIGN_NULLIFY);
+#endif
+
+#if (DBVER >= 44)
 ADD_INT(d, DB_REGISTER);
 #endif
 
+ ADD_INT(d, DB_EID_INVALID);
+ ADD_INT(d, DB_EID_BROADCAST);
+
 #if (DBVER >= 42)
 ADD_INT(d, DB_TIME_NOTGRANTED);
 ADD_INT(d, DB_TXN_NOT_DURABLE);
@@ -7414,6 +9762,32 @@
 
 ADD_INT(d, DB_REP_MASTER);
 ADD_INT(d, DB_REP_CLIENT);
+
+ ADD_INT(d, DB_REP_PERMANENT);
+
+#if (DBVER >= 44)
+ ADD_INT(d, DB_REP_CONF_NOAUTOINIT);
+ ADD_INT(d, DB_REP_CONF_DELAYCLIENT);
+ ADD_INT(d, DB_REP_CONF_BULK);
+ ADD_INT(d, DB_REP_CONF_NOWAIT);
+ ADD_INT(d, DB_REP_ANYWHERE);
+ ADD_INT(d, DB_REP_REREQUEST);
+#endif
+
+#if (DBVER >= 42)
+ ADD_INT(d, DB_REP_NOBUFFER);
+#endif
+
+#if (DBVER >= 46)
+ ADD_INT(d, DB_REP_LEASE_EXPIRED);
+ ADD_INT(d, DB_IGNORE_LEASE);
+#endif
+
+#if (DBVER >= 47)
+ ADD_INT(d, DB_REP_CONF_LEASE);
+ ADD_INT(d, DB_REPMGR_CONF_2SITE_STRICT);
+#endif
+
 #if (DBVER >= 45)
 ADD_INT(d, DB_REP_ELECTION);
 
@@ -7425,6 +9799,11 @@
 #if (DBVER >= 46)
 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
+ ADD_INT(d, DB_REP_LEASE_TIMEOUT);
+#endif
+#if (DBVER >= 47)
+ ADD_INT(d, DB_REP_HEARTBEAT_MONITOR);
+ ADD_INT(d, DB_REP_HEARTBEAT_SEND);
 #endif
 
 #if (DBVER >= 45)
@@ -7437,7 +9816,6 @@
 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
 ADD_INT(d, DB_REPMGR_CONNECTED);
 ADD_INT(d, DB_REPMGR_DISCONNECTED);
- ADD_INT(d, DB_STAT_CLEAR);
 ADD_INT(d, DB_STAT_ALL);
 #endif
 
@@ -7453,12 +9831,16 @@
 ADD_INT(d, DB_DSYNC_LOG);
 #endif
 
-#if (DBVER >= 41)
 ADD_INT(d, DB_ENCRYPT_AES);
 ADD_INT(d, DB_AUTO_COMMIT);
-#else
- /* allow Berkeley DB 4.1 aware apps to run on older versions */
- _addIntToDict(d, "DB_AUTO_COMMIT", 0);
+ ADD_INT(d, DB_PRIORITY_VERY_LOW);
+ ADD_INT(d, DB_PRIORITY_LOW);
+ ADD_INT(d, DB_PRIORITY_DEFAULT);
+ ADD_INT(d, DB_PRIORITY_HIGH);
+ ADD_INT(d, DB_PRIORITY_VERY_HIGH);
+
+#if (DBVER >= 46)
+ ADD_INT(d, DB_PRIORITY_UNCHANGED);
 #endif
 
 ADD_INT(d, EINVAL);
@@ -7522,12 +9904,7 @@
 }
 #endif
 
-
-#if !INCOMPLETE_IS_WARNING
- MAKE_EX(DBIncompleteError);
-#endif
 MAKE_EX(DBCursorClosedError);
- MAKE_EX(DBKeyEmptyError);
 MAKE_EX(DBKeyExistError);
 MAKE_EX(DBLockDeadlockError);
 MAKE_EX(DBLockNotGrantedError);
@@ -7553,23 +9930,52 @@
 #if (DBVER >= 42)
 MAKE_EX(DBRepHandleDeadError);
 #endif
+#if (DBVER >= 44)
+ MAKE_EX(DBRepLockoutError);
+#endif
 
 MAKE_EX(DBRepUnavailError);
 
+#if (DBVER >= 46)
+ MAKE_EX(DBRepLeaseExpiredError);
+#endif
+
+#if (DBVER >= 47)
+ MAKE_EX(DBForeignConflictError);
+#endif
+
 #undef MAKE_EX
 
- /* Initiliase the C API structure and add it to the module */
- bsddb_api.db_type = &DB_Type;
- bsddb_api.dbcursor_type = &DBCursor_Type;
- bsddb_api.dbenv_type = &DBEnv_Type;
- bsddb_api.dbtxn_type = &DBTxn_Type;
- bsddb_api.dblock_type = &DBLock_Type;
+ /* Initialise the C API structure and add it to the module */
+ bsddb_api.db_type = &DB_Type;
+ bsddb_api.dbcursor_type = &DBCursor_Type;
+ bsddb_api.dblogcursor_type = &DBLogCursor_Type;
+ bsddb_api.dbenv_type = &DBEnv_Type;
+ bsddb_api.dbtxn_type = &DBTxn_Type;
+ bsddb_api.dblock_type = &DBLock_Type;
 #if (DBVER >= 43)
- bsddb_api.dbsequence_type = &DBSequence_Type;
+ bsddb_api.dbsequence_type = &DBSequence_Type;
 #endif
- bsddb_api.makeDBError = makeDBError;
+ bsddb_api.makeDBError = makeDBError;
 
+ /*
+ ** Capsules exist from Python 3.1, but I
+ ** don't want to break the API compatibility
+ ** for already published Python versions.
+ */
+#if (PY_VERSION_HEX < 0x03020000)
 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
+#else
+ {
+ char py_api_name[250];
+
+ strcpy(py_api_name, _bsddbModuleName);
+ strcat(py_api_name, ".api");
+
+ py_api = PyCapsule_New((void*)&bsddb_api, py_api_name, NULL);
+ }
+#endif
+
 PyDict_SetItemString(d, "api", py_api);
 Py_DECREF(py_api);
 
Modified: python/trunk/Modules/bsddb.h
==============================================================================
--- python/trunk/Modules/bsddb.h	(original)
+++ python/trunk/Modules/bsddb.h	Mon Mar 22 15:22:26 2010
@@ -70,6 +70,10 @@
 * DBLock (A lock handle)
 * DBSequence (Sequence)
 *
+ * New datatypes:
+ *
+ * DBLogCursor (Log Cursor)
+ *
 */
 
 /* --------------------------------------------------------------------- */
@@ -105,7 +109,7 @@
 #error "eek! DBVER can't handle minor versions > 9"
 #endif
 
-#define PY_BSDDB_VERSION "4.7.3"
+#define PY_BSDDB_VERSION "4.8.4"
 
 /* Python object definitions */
 
@@ -122,6 +126,7 @@
 
 struct DBObject; /* Forward declaration */
 struct DBCursorObject; /* Forward declaration */
+struct DBLogCursorObject; /* Forward declaration */
 struct DBTxnObject; /* Forward declaration */
 struct DBSequenceObject; /* Forward declaration */
 
@@ -134,6 +139,7 @@
 PyObject* event_notifyCallback;
 struct DBObject *children_dbs;
 struct DBTxnObject *children_txns;
+ struct DBLogCursorObject *children_logcursors;
 PyObject *private_obj;
 PyObject *rep_transport;
 PyObject *in_weakreflist; /* List of weak references */
@@ -145,7 +151,6 @@
 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
 u_int32_t flags; /* saved flags from open() */
 u_int32_t setflags; /* saved flags from set_flags() */
- int haveStat;
 struct behaviourFlags moduleFlags;
 struct DBTxnObject *txn;
 struct DBCursorObject *children_cursors;
@@ -193,9 +198,20 @@
 } DBTxnObject;
 
 
+typedef struct DBLogCursorObject {
+ PyObject_HEAD
+ DB_LOGC* logc;
+ DBEnvObject* env;
+ struct DBLogCursorObject **sibling_prev_p;
+ struct DBLogCursorObject *sibling_next;
+ PyObject *in_weakreflist; /* List of weak references */
+} DBLogCursorObject;
+
+
 typedef struct {
 PyObject_HEAD
 DB_LOCK lock;
+ int lock_initialized; /* Signal if we actually have a lock */
 PyObject *in_weakreflist; /* List of weak references */
 } DBLockObject;
 
@@ -220,6 +236,7 @@
 /* To access the structure from an external module, use code like the
 following (error checking missed out for clarity):
 
+ // If you are using Python before 3.2:
 BSDDB_api* bsddb_api;
 PyObject* mod;
 PyObject* cobj;
@@ -231,6 +248,15 @@
 Py_DECREF(cobj);
 Py_DECREF(mod);
 
+
+ // If you are using Python 3.2 or up:
+ BSDDB_api* bsddb_api;
+
+ // Use "bsddb3._pybsddb.api" if you're using
+ // the standalone pybsddb add-on.
+ bsddb_api = (void **)PyCapsule_Import("bsddb._bsddb.api", 1);
+
+
 The structure's members must not be changed.
 */
 
@@ -238,6 +264,7 @@
 /* Type objects */
 PyTypeObject* db_type;
 PyTypeObject* dbcursor_type;
+ PyTypeObject* dblogcursor_type;
 PyTypeObject* dbenv_type;
 PyTypeObject* dbtxn_type;
 PyTypeObject* dblock_type;
@@ -247,7 +274,6 @@
 
 /* Functions */
 int (*makeDBError)(int err);
-
 } BSDDB_api;
 
 
Modified: python/trunk/setup.py
==============================================================================
--- python/trunk/setup.py	(original)
+++ python/trunk/setup.py	Mon Mar 22 15:22:26 2010
@@ -708,7 +708,7 @@
 # versions of BerkeleyDB already installed.
 
 max_db_ver = (4, 8)
- min_db_ver = (3, 3)
+ min_db_ver = (4, 1)
 db_setup_debug = False # verbose debug prints from this script?
 
 def allow_db_ver(db_ver):


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /