bsddb code updated to version 4.7.3pre2. This code is the same than
Python 2.6 one, since the intention is to keep an unified 2.x/3.x
codebase.

The Python code is automatically translated using "2to3". Please, do not
update this code in Python 3.0 by hand. Update the 2.6 one and then do
"2to3".
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c
index 7c0eae3..9e89273 100644
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -36,7 +36,7 @@
 /*
  * Handwritten code to wrap version 3.x of the Berkeley DB library,
  * written to replace a SWIG-generated file.  It has since been updated
- * to compile with BerkeleyDB versions 3.2 through 4.2.
+ * to compile with Berkeley DB versions 3.2 through 4.2.
  *
  * This module was started by Andrew Kuchling to remove the dependency
  * on SWIG in a package by Gregory P. Smith who based his work on a
@@ -48,7 +48,10 @@
  * the DB 3.x API and to build a solid unit test suite.  Robin has
  * since gone onto other projects (wxPython).
  *
- * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
+ * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
+ *
+ * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
+ * Jesus Cea licenses this code to PSF under a Contributor Agreement.
  *
  * Use the pybsddb-users@lists.sf.net mailing list for all questions.
  * Things can change faster than the header of this file is updated.  This
@@ -92,7 +95,7 @@
 #include "bsddb.h"
 #undef COMPILING_BSDDB_C
 
-static char *svn_id = "$Id$";
+static char *rcs_id = "$Id$";
 
 /* --------------------------------------------------------------------- */
 /* Various macro definitions */
@@ -101,6 +104,27 @@
 typedef int Py_ssize_t;
 #endif
 
+#if (PY_VERSION_HEX < 0x02060000)  /* really: before python trunk r63675 */
+/* This code now uses PyBytes* API function names instead of PyString*.
+ * These #defines map to their equivalent on earlier python versions.    */
+#define PyBytes_FromStringAndSize PyString_FromStringAndSize
+#define PyBytes_FromString PyString_FromString
+#define PyBytes_AsStringAndSize PyString_AsStringAndSize
+#define PyBytes_Check PyString_Check
+#define PyBytes_GET_SIZE PyString_GET_SIZE
+#define PyBytes_AS_STRING PyString_AS_STRING
+#endif
+
+#if (PY_VERSION_HEX >= 0x03000000)
+#define NUMBER_Check    PyLong_Check
+#define NUMBER_AsLong   PyLong_AsLong
+#define NUMBER_FromLong PyLong_FromLong
+#else
+#define NUMBER_Check    PyInt_Check
+#define NUMBER_AsLong   PyInt_AsLong
+#define NUMBER_FromLong PyInt_FromLong
+#endif
+
 #ifdef WITH_THREAD
 
 /* These are for when calling Python --> C */
@@ -164,10 +188,8 @@
 static PyObject* DBNoServerError;       /* DB_NOSERVER */
 static PyObject* DBNoServerHomeError;   /* DB_NOSERVER_HOME */
 static PyObject* DBNoServerIDError;     /* DB_NOSERVER_ID */
-#if (DBVER >= 33)
 static PyObject* DBPageNotFoundError;   /* DB_PAGE_NOTFOUND */
 static PyObject* DBSecondaryBadError;   /* DB_SECONDARY_BAD */
-#endif
 
 #if !INCOMPLETE_IS_WARNING
 static PyObject* DBIncompleteError;     /* DB_INCOMPLETE */
@@ -183,6 +205,12 @@
 static PyObject* DBNoSuchFileError;     /* ENOENT */
 static PyObject* DBPermissionsError;    /* EPERM  */
 
+#if (DBVER >= 42)
+static PyObject* DBRepHandleDeadError;  /* DB_REP_HANDLE_DEAD */
+#endif
+
+static PyObject* DBRepUnavailError;     /* DB_REP_UNAVAIL */
+
 #if (DBVER < 43)
 #define	DB_BUFFER_SMALL		ENOMEM
 #endif
@@ -201,7 +229,24 @@
 #define DEFAULT_CURSOR_SET_RETURNS_NONE         1   /* 0 in pybsddb < 4.2, python < 2.4 */
 
 
-static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
+/* See comment in Python 2.6 "object.h" */
+#ifndef staticforward
+#define staticforward static
+#endif
+#ifndef statichere
+#define statichere static
+#endif
+
+staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
+              DBLock_Type;
+#if (DBVER >= 43)
+staticforward PyTypeObject DBSequence_Type;
+#endif
+
+#ifndef Py_TYPE
+/* for compatibility with Python 2.5 and earlier */
+#define Py_TYPE(ob)              (((PyObject*)(ob))->ob_type)
+#endif
 
 #define DBObject_Check(v)           (Py_TYPE(v) == &DB_Type)
 #define DBCursorObject_Check(v)     (Py_TYPE(v) == &DBCursor_Type)
@@ -212,10 +257,77 @@
 #define DBSequenceObject_Check(v)   (Py_TYPE(v) == &DBSequence_Type)
 #endif
 
+#if (DBVER < 46)
+  #define _DBC_close(dbc)           dbc->c_close(dbc)
+  #define _DBC_count(dbc,a,b)       dbc->c_count(dbc,a,b)
+  #define _DBC_del(dbc,a)           dbc->c_del(dbc,a)
+  #define _DBC_dup(dbc,a,b)         dbc->c_dup(dbc,a,b)
+  #define _DBC_get(dbc,a,b,c)       dbc->c_get(dbc,a,b,c)
+  #define _DBC_pget(dbc,a,b,c,d)    dbc->c_pget(dbc,a,b,c,d)
+  #define _DBC_put(dbc,a,b,c)       dbc->c_put(dbc,a,b,c)
+#else
+  #define _DBC_close(dbc)           dbc->close(dbc)
+  #define _DBC_count(dbc,a,b)       dbc->count(dbc,a,b)
+  #define _DBC_del(dbc,a)           dbc->del(dbc,a)
+  #define _DBC_dup(dbc,a,b)         dbc->dup(dbc,a,b)
+  #define _DBC_get(dbc,a,b,c)       dbc->get(dbc,a,b,c)
+  #define _DBC_pget(dbc,a,b,c,d)    dbc->pget(dbc,a,b,c,d)
+  #define _DBC_put(dbc,a,b,c)       dbc->put(dbc,a,b,c)
+#endif
+
 
 /* --------------------------------------------------------------------- */
 /* Utility macros and functions */
 
+#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object)                   \
+    {                                                                   \
+        object->sibling_next=backlink;                                  \
+        object->sibling_prev_p=&(backlink);                             \
+        backlink=object;                                                \
+        if (object->sibling_next) {                                     \
+          object->sibling_next->sibling_prev_p=&(object->sibling_next); \
+        }                                                               \
+    }
+
+#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object)                          \
+    {                                                                    \
+        if (object->sibling_next) {                                      \
+            object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
+        }                                                                \
+        *(object->sibling_prev_p)=object->sibling_next;                  \
+    }
+
+#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object)               \
+    {                                                                    \
+        if (object->sibling_next) {                                      \
+            object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
+        }                                                                \
+        if (object->sibling_prev_p) {                                    \
+            *(object->sibling_prev_p)=object->sibling_next;              \
+        }                                                                \
+    }
+
+#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object)  \
+    {                                                      \
+        object->sibling_next_txn=backlink;                 \
+        object->sibling_prev_p_txn=&(backlink);            \
+        backlink=object;                                   \
+        if (object->sibling_next_txn) {                    \
+            object->sibling_next_txn->sibling_prev_p_txn=  \
+                &(object->sibling_next_txn);               \
+        }                                                  \
+    }
+
+#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object)             \
+    {                                                           \
+        if (object->sibling_next_txn) {                         \
+            object->sibling_next_txn->sibling_prev_p_txn=       \
+                object->sibling_prev_p_txn;                     \
+        }                                                       \
+        *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
+    }
+
+
 #define RETURN_IF_ERR()          \
     if (makeDBError(err)) {      \
         return NULL;             \
@@ -227,8 +339,10 @@
     if ((nonNull) == NULL) {          \
         PyObject *errTuple = NULL;    \
         errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
-        PyErr_SetObject((pyErrObj), errTuple);  \
-	Py_DECREF(errTuple);          \
+        if (errTuple) { \
+            PyErr_SetObject((pyErrObj), errTuple);  \
+            Py_DECREF(errTuple);          \
+        } \
         return NULL;                  \
     }
 
@@ -251,6 +365,9 @@
 
 #define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
 
+#define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
+                                         dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
+
 
 static int makeDBError(int err);
 
@@ -258,104 +375,34 @@
 /* Return the access method type of the DBObject */
 static int _DB_get_type(DBObject* self)
 {
-#if (DBVER >= 33)
     DBTYPE type;
     int err;
+
     err = self->db->get_type(self->db, &type);
     if (makeDBError(err)) {
         return -1;
     }
     return type;
-#else
-    return self->db->get_type(self->db);
-#endif
-}
-
-
-/* Handy function to free a DBT and any self-allocated data within.
-   To be used on self created DBTs.  The make_dbt and make_key_dbt
-   functions have their own free routines that do more that this. */
-static void free_dbt(DBT *dbt)
-{
-    if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
-         free(dbt->data);
-         dbt->data = NULL;
-    }
-}
-
-
-/* Cleanup a Python buffer API view created by make_dbt() */
-static void free_buf_view(PyObject *obj, Py_buffer *view)
-{
-    if (view) {
-        PyBuffer_Release(view);
-        PyMem_Free(view);
-    }
-}
-
-
-/* Cleanup a DBT and an associated Python buffer API view
-   created by make_key_dbt() */
-#define FREE_DBT_VIEW(dbt, obj, view)    \
-            do { \
-                free_dbt(&(dbt)); \
-                free_buf_view((obj), (view)); \
-            } while(0);
-
-
-static Py_buffer * _malloc_view(PyObject *obj)
-{
-    Py_buffer *view;
-
-    if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
-        PyErr_SetString(PyExc_MemoryError,
-                        "Py_buffer malloc failed");
-        return NULL;
-    }
-
-    if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE))
-        return NULL;
-
-    if (view->ndim > 1) {
-        PyErr_SetString(PyExc_BufferError,
-                        "buffers must be single dimension");
-        PyBuffer_Release(view);
-        PyMem_Free(view);
-        return NULL;
-    }
-    return view;
 }
 
 
 /* Create a DBT structure (containing key and data values) from Python
-   strings.  Returns >= 1 on success, 0 on an error.  The returned_view_p
-   may be filled with a newly allocated Py_buffer view on success.
-   The caller MUST call free_buf_view() on any returned Py_buffer. */
-static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
+   strings.  Returns 1 on success, 0 on an error. */
+static int make_dbt(PyObject* obj, DBT* dbt)
 {
-    Py_buffer *view;
-
-    /* simple way to ensure the caller can detect if we've returned a
-       new buffer view or not: require their pointer to start out NULL. */
-    assert(*returned_view_p == NULL);
-
     CLEAR_DBT(*dbt);
     if (obj == Py_None) {
         /* no need to do anything, the structure has already been zeroed */
-        return 1;
     }
-    if (!PyObject_CheckBuffer(obj)) {
+    else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
         PyErr_SetString(PyExc_TypeError,
-                        "Data values must support the buffer API or be None.");
+#if (PY_VERSION_HEX < 0x03000000)
+                        "Data values must be of type string or None.");
+#else
+                        "Data values must be of type bytes or None.");
+#endif
         return 0;
     }
-
-    if ( !(view = _malloc_view(obj)) )
-        return 0;
-
-    dbt->data = view->buf;
-    dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
-    *returned_view_p = view;
     return 1;
 }
 
@@ -363,19 +410,12 @@
 /* Recno and Queue DBs can have integer keys.  This function figures out
    what's been given, verifies that it's allowed, and then makes the DBT.
 
-   Caller MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
-   returned DBT and Py_buffer values when done. */
+   Caller MUST call FREE_DBT(key) when done. */
 static int
-make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
-             Py_buffer** returned_view_p)
+make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
 {
     db_recno_t recno;
     int type;
-    Py_buffer *view;
-
-    /* simple way to ensure the caller can detect if we've returned a
-       new buffer view or not: require their pointer to start out NULL. */
-    assert(*returned_view_p == NULL);
 
     CLEAR_DBT(*key);
     if (keyobj == Py_None) {
@@ -391,7 +431,41 @@
         /* no need to do anything, the structure has already been zeroed */
     }
 
-    else if (PyLong_Check(keyobj)) {
+    else if (PyBytes_Check(keyobj)) {
+        /* verify access method type */
+        type = _DB_get_type(self);
+        if (type == -1)
+            return 0;
+        if (type == DB_RECNO || type == DB_QUEUE) {
+            PyErr_SetString(
+                PyExc_TypeError,
+#if (PY_VERSION_HEX < 0x03000000)
+                "String keys not allowed for Recno and Queue DB's");
+#else
+                "Bytes keys not allowed for Recno and Queue DB's");
+#endif
+            return 0;
+        }
+
+        /*
+         * NOTE(gps): I don't like doing a data copy here, it seems
+         * wasteful.  But without a clean way to tell FREE_DBT if it
+         * should free key->data or not we have to.  Other places in
+         * the code check for DB_THREAD and forceably set DBT_MALLOC
+         * when we otherwise would leave flags 0 to indicate that.
+         */
+        key->data = malloc(PyBytes_GET_SIZE(keyobj));
+        if (key->data == NULL) {
+            PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
+            return 0;
+        }
+        memcpy(key->data, PyBytes_AS_STRING(keyobj),
+               PyBytes_GET_SIZE(keyobj));
+        key->flags = DB_DBT_REALLOC;
+        key->size = PyBytes_GET_SIZE(keyobj);
+    }
+
+    else if (NUMBER_Check(keyobj)) {
         /* verify access method type */
         type = _DB_get_type(self);
         if (type == -1)
@@ -410,7 +484,7 @@
 
         /* Make a key out of the requested recno, use allocated space so DB
          * will be able to realloc room for the real key if needed. */
-        recno = PyLong_AS_LONG(keyobj);
+        recno = NUMBER_AsLong(keyobj);
         key->data = malloc(sizeof(db_recno_t));
         if (key->data == NULL) {
             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
@@ -420,44 +494,13 @@
         memcpy(key->data, &recno, sizeof(db_recno_t));
         key->flags = DB_DBT_REALLOC;
     }
-
-    else if (PyObject_CheckBuffer(keyobj)) {
-        /* verify access method type */
-        type = _DB_get_type(self);
-        if (type == -1)
-            return 0;
-        if (type == DB_RECNO || type == DB_QUEUE) {
-            PyErr_SetString(
-                PyExc_TypeError,
-                "Non-integer keys not allowed for Recno and Queue DB's");
-            return 0;
-        }
-
-        if ( !(view = _malloc_view(keyobj)) )
-            return 0;
-
-        /*
-         * NOTE(gps): I don't like doing a data copy here, it seems
-         * wasteful.  But without a clean way to tell FREE_DBT if it
-         * should free key->data or not we have to.  Other places in
-         * the code check for DB_THREAD and forceably set DBT_MALLOC
-         * when we otherwise would leave flags 0 to indicate that.
-         */
-        key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
-        key->data = malloc(key->size);
-        if (key->data == NULL) {
-            PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
-            key->size = 0;
-            return 0;
-        }
-        memcpy(key->data, view->buf, key->size);
-        key->flags = DB_DBT_REALLOC;
-        *returned_view_p = view;
-    }
-
     else {
         PyErr_Format(PyExc_TypeError,
-                     "buffer or int object expected for key, %s found",
+#if (PY_VERSION_HEX < 0x03000000)
+                     "String or Integer object expected for key, %s found",
+#else
+                     "Bytes or Integer object expected for key, %s found",
+#endif
                      Py_TYPE(keyobj)->tp_name);
         return 0;
     }
@@ -518,6 +561,102 @@
 }
 
 
+/*
+** We need these functions because some results
+** are undefined if pointer is NULL. Some other
+** give None instead of "".
+**
+** This functions are static and will be
+** -I hope- inlined.
+*/
+static const char *DummyString = "This string is a simple placeholder";
+static PyObject *Build_PyString(const char *p,int s)
+{
+  if (!p) {
+    p=DummyString;
+    assert(s==0);
+  }
+  return PyBytes_FromStringAndSize(p,s);
+}
+
+static PyObject *BuildValue_S(const void *p,int s)
+{
+  if (!p) {
+    p=DummyString;
+    assert(s==0);
+  }
+  return PyBytes_FromStringAndSize(p, s);
+}
+
+static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
+{
+PyObject *a, *b, *r;
+
+  if (!p1) {
+    p1=DummyString;
+    assert(s1==0);
+  }
+  if (!p2) {
+    p2=DummyString;
+    assert(s2==0);
+  }
+
+  if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
+      return NULL;
+  }
+  if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
+      Py_DECREF(a);
+      return NULL;
+  }
+
+#if (PY_VERSION_HEX >= 0x02040000)
+  r = PyTuple_Pack(2, a, b) ;
+#else
+  r = Py_BuildValue("OO", a, b);
+#endif
+  Py_DECREF(a);
+  Py_DECREF(b);
+  return r;
+}
+
+static PyObject *BuildValue_IS(int i,const void *p,int s)
+{
+  PyObject *a, *r;
+
+  if (!p) {
+    p=DummyString;
+    assert(s==0);
+  }
+
+  if (!(a = PyBytes_FromStringAndSize(p, s))) {
+      return NULL;
+  }
+
+  r = Py_BuildValue("iO", i, a);
+  Py_DECREF(a);
+  return r;
+}
+
+static PyObject *BuildValue_LS(long l,const void *p,int s)
+{
+  PyObject *a, *r;
+
+  if (!p) {
+    p=DummyString;
+    assert(s==0);
+  }
+
+  if (!(a = PyBytes_FromStringAndSize(p, s))) {
+      return NULL;
+  }
+
+  r = Py_BuildValue("lO", l, a);
+  Py_DECREF(a);
+  return r;
+}
+
+
+
 /* make a nice exception object to raise for errors. */
 static int makeDBError(int err)
 {
@@ -542,7 +681,7 @@
                 strncat(errTxt, _db_errmsg, bytes_left);
             }
             _db_errmsg[0] = 0;
-            exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
+            exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
 
 #else  /* do an exception instead */
         errObj = DBIncompleteError;
@@ -561,10 +700,8 @@
         case DB_NOSERVER:           errObj = DBNoServerError;       break;
         case DB_NOSERVER_HOME:      errObj = DBNoServerHomeError;   break;
         case DB_NOSERVER_ID:        errObj = DBNoServerIDError;     break;
-#if (DBVER >= 33)
         case DB_PAGE_NOTFOUND:      errObj = DBPageNotFoundError;   break;
         case DB_SECONDARY_BAD:      errObj = DBSecondaryBadError;   break;
-#endif
         case DB_BUFFER_SMALL:       errObj = DBNoMemoryError;       break;
 
 #if (DBVER >= 43)
@@ -580,6 +717,12 @@
         case ENOENT:  errObj = DBNoSuchFileError;   break;
         case EPERM :  errObj = DBPermissionsError;  break;
 
+#if (DBVER >= 42)
+        case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
+#endif
+
+        case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
+
         default:      errObj = DBError;             break;
     }
 
@@ -594,9 +737,13 @@
         }
         _db_errmsg[0] = 0;
 
-	errTuple = Py_BuildValue("(is)", err, errTxt);
+        errTuple = Py_BuildValue("(is)", err, errTxt);
+        if (errTuple == NULL) {
+            Py_DECREF(errObj);
+            return !0;
+        }
         PyErr_SetObject(errObj, errTuple);
-	Py_DECREF(errTuple);
+        Py_DECREF(errTuple);
     }
 
     return ((errObj != NULL) || exceptionRaised);
@@ -683,16 +830,11 @@
     flags |= extra_flags;
     CLEAR_DBT(key);
     CLEAR_DBT(data);
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        data.flags = DB_DBT_MALLOC;
-        key.flags = DB_DBT_MALLOC;
-    }
     if (!add_partial_dbt(&data, dlen, doff))
         return NULL;
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags);
+    err = _DBC_get(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
@@ -713,21 +855,15 @@
 
         case DB_RECNO:
         case DB_QUEUE:
-            retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
-                                   data.data, data.size);
+            retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
             break;
         case DB_HASH:
         case DB_BTREE:
         default:
-            retval = Py_BuildValue("y#y#", key.data, key.size,
-                                   data.data, data.size);
+            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
             break;
         }
     }
-    if (!err) {
-        free_dbt(&key);
-        free_dbt(&data);
-    }
     return retval;
 }
 
@@ -735,7 +871,7 @@
 /* add an integer to a dictionary using the given name as a key */
 static void _addIntToDict(PyObject* dict, char *name, int value)
 {
-    PyObject* v = PyLong_FromLong((long) value);
+    PyObject* v = NUMBER_FromLong((long) value);
     if (!v || PyDict_SetItemString(dict, name, v))
         PyErr_Clear();
 
@@ -747,12 +883,12 @@
 {
     PyObject* v;
 	/* if the value fits in regular int, use that. */
-#ifdef HAVE_LONG_LONG
+#ifdef PY_LONG_LONG
 	if (sizeof(time_t) > sizeof(long))
 		v = PyLong_FromLongLong((PY_LONG_LONG) value);
 	else
 #endif
-		v = PyLong_FromLong((long) value);
+		v = NUMBER_FromLong((long) value);
     if (!v || PyDict_SetItemString(dict, name, v))
         PyErr_Clear();
 
@@ -771,7 +907,14 @@
 }
 #endif
 
+static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
+{
+    PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
+    if (!v || PyDict_SetItemString(dict, name, v))
+        PyErr_Clear();
 
+    Py_XDECREF(v);
+}
 
 /* --------------------------------------------------------------------- */
 /* Allocators and deallocators */
@@ -791,11 +934,16 @@
     self->flags = 0;
     self->setflags = 0;
     self->myenvobj = NULL;
-#if (DBVER >= 33)
+    self->db = NULL;
+    self->children_cursors = NULL;
+#if (DBVER >=43)
+    self->children_sequences = NULL;
+#endif
     self->associateCallback = NULL;
     self->btCompareCallback = NULL;
     self->primaryDBType = 0;
-#endif
+    Py_INCREF(Py_None);
+    self->private_obj = Py_None;
     self->in_weakreflist = NULL;
 
     /* keep a reference to our python DBEnv object */
@@ -803,7 +951,14 @@
         Py_INCREF(arg);
         self->myenvobj = arg;
         db_env = arg->db_env;
+        INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
+    } else {
+      self->sibling_prev_p=NULL;
+      self->sibling_next=NULL;
     }
+    self->txn=NULL;
+    self->sibling_prev_p_txn=NULL;
+    self->sibling_next_txn=NULL;
 
     if (self->myenvobj)
         self->moduleFlags = self->myenvobj->moduleFlags;
@@ -815,9 +970,7 @@
     err = db_create(&self->db, db_env, flags);
     if (self->db != NULL) {
         self->db->set_errcall(self->db, _db_errorCallback);
-#if (DBVER >= 33)
         self->db->app_private = (void*)self;
-#endif
     }
     MYDB_END_ALLOW_THREADS;
     /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
@@ -828,32 +981,24 @@
             Py_DECREF(self->myenvobj);
             self->myenvobj = NULL;
         }
-        PyObject_Del(self);
+        Py_DECREF(self);
         self = NULL;
     }
     return self;
 }
 
 
+/* Forward declaration */
+static PyObject *DB_close_internal(DBObject* self, int flags);
+
 static void
 DB_dealloc(DBObject* self)
 {
+  PyObject *dummy;
+
     if (self->db != NULL) {
-        /* avoid closing a DB when its DBEnv has been closed out from under
-         * it */
-        if (!self->myenvobj ||
-            (self->myenvobj && self->myenvobj->db_env))
-        {
-            MYDB_BEGIN_ALLOW_THREADS;
-            self->db->close(self->db, 0);
-            MYDB_END_ALLOW_THREADS;
-        } else {
-            PyErr_WarnEx(PyExc_RuntimeWarning,
-			 "DB could not be closed in destructor:"
-			 " DBEnv already closed",
-			 1);
-        }
-        self->db = NULL;
+      dummy=DB_close_internal(self,0);
+      Py_XDECREF(dummy);
     }
     if (self->in_weakreflist != NULL) {
         PyObject_ClearWeakRefs((PyObject *) self);
@@ -862,7 +1007,6 @@
         Py_DECREF(self->myenvobj);
         self->myenvobj = NULL;
     }
-#if (DBVER >= 33)
     if (self->associateCallback != NULL) {
         Py_DECREF(self->associateCallback);
         self->associateCallback = NULL;
@@ -871,13 +1015,12 @@
         Py_DECREF(self->btCompareCallback);
         self->btCompareCallback = NULL;
     }
-#endif
+    Py_DECREF(self->private_obj);
     PyObject_Del(self);
 }
 
-
 static DBCursorObject*
-newDBCursorObject(DBC* dbc, DBObject* db)
+newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
 {
     DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
     if (self == NULL)
@@ -885,40 +1028,37 @@
 
     self->dbc = dbc;
     self->mydb = db;
+
+    INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
+    if (txn && ((PyObject *)txn!=Py_None)) {
+	    INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
+	    self->txn=txn;
+    } else {
+	    self->txn=NULL;
+    }
+
     self->in_weakreflist = NULL;
     Py_INCREF(self->mydb);
     return self;
 }
 
 
+/* Forward declaration */
+static PyObject *DBC_close_internal(DBCursorObject* self);
+
 static void
 DBCursor_dealloc(DBCursorObject* self)
 {
-    int err;
+    PyObject *dummy;
 
+    if (self->dbc != NULL) {
+      dummy=DBC_close_internal(self);
+      Py_XDECREF(dummy);
+    }
     if (self->in_weakreflist != NULL) {
         PyObject_ClearWeakRefs((PyObject *) self);
     }
-
-    if (self->dbc != NULL) {
-	/* If the underlying database has been closed, we don't
-	   need to do anything. If the environment has been closed
-	   we need to leak, as BerkeleyDB will crash trying to access
-	   the environment. There was an exception when the 
-	   user closed the environment even though there still was
-	   a database open. */
-	if (self->mydb->db && self->mydb->myenvobj &&
-	    !self->mydb->myenvobj->closed)
-        /* test for: open db + no environment or non-closed environment */
-	if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
-	    !self->mydb->myenvobj->closed))) {
-            MYDB_BEGIN_ALLOW_THREADS;
-            err = self->dbc->c_close(self->dbc);
-            MYDB_END_ALLOW_THREADS;
-        }
-        self->dbc = NULL;
-    }
-    Py_XDECREF( self->mydb );
+    Py_DECREF(self->mydb);
     PyObject_Del(self);
 }
 
@@ -935,88 +1075,134 @@
     self->flags = flags;
     self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
     self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
+    self->children_dbs = NULL;
+    self->children_txns = NULL;
+    Py_INCREF(Py_None);
+    self->private_obj = Py_None;
+    Py_INCREF(Py_None);
+    self->rep_transport = Py_None;
     self->in_weakreflist = NULL;
+    self->event_notifyCallback = NULL;
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = db_env_create(&self->db_env, flags);
     MYDB_END_ALLOW_THREADS;
     if (makeDBError(err)) {
-        PyObject_Del(self);
+        Py_DECREF(self);
         self = NULL;
     }
     else {
         self->db_env->set_errcall(self->db_env, _db_errorCallback);
+        self->db_env->app_private = self;
     }
     return self;
 }
 
+/* Forward declaration */
+static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
 
 static void
 DBEnv_dealloc(DBEnvObject* self)
 {
+  PyObject *dummy;
+
+    if (self->db_env && !self->closed) {
+      dummy=DBEnv_close_internal(self,0);
+      Py_XDECREF(dummy);
+    }
+
+    Py_XDECREF(self->event_notifyCallback);
+    self->event_notifyCallback = NULL;
+
     if (self->in_weakreflist != NULL) {
         PyObject_ClearWeakRefs((PyObject *) self);
     }
-
-    if (self->db_env && !self->closed) {
-        MYDB_BEGIN_ALLOW_THREADS;
-        self->db_env->close(self->db_env, 0);
-        MYDB_END_ALLOW_THREADS;
-    }
+    Py_DECREF(self->private_obj);
+    Py_DECREF(self->rep_transport);
     PyObject_Del(self);
 }
 
 
 static DBTxnObject*
-newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
+newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
 {
     int err;
+    DB_TXN *parent_txn = NULL;
+
     DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
     if (self == NULL)
         return NULL;
-    Py_INCREF(myenv);
-    self->env = (PyObject*)myenv;
-    self->in_weakreflist = NULL;
 
-    MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
-    err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
-#else
-    err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
-#endif
-    MYDB_END_ALLOW_THREADS;
-    if (makeDBError(err)) {
-        Py_DECREF(self->env);
-        PyObject_Del(self);
-        self = NULL;
+    self->in_weakreflist = NULL;
+    self->children_txns = NULL;
+    self->children_dbs = NULL;
+    self->children_cursors = NULL;
+    self->children_sequences = NULL;
+    self->flag_prepare = 0;
+    self->parent_txn = NULL;
+    self->env = NULL;
+
+    if (parent && ((PyObject *)parent!=Py_None)) {
+        parent_txn = parent->txn;
     }
+
+    if (txn) {
+        self->txn = txn;
+    } else {
+        MYDB_BEGIN_ALLOW_THREADS;
+        err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
+        MYDB_END_ALLOW_THREADS;
+
+        if (makeDBError(err)) {
+            Py_DECREF(self);
+            return NULL;
+        }
+    }
+
+    /* Can't use 'parent' because could be 'parent==Py_None' */
+    if (parent_txn) {
+        self->parent_txn = parent;
+        Py_INCREF(parent);
+        self->env = NULL;
+        INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
+    } else {
+        self->parent_txn = NULL;
+        Py_INCREF(myenv);
+        self->env = myenv;
+        INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
+    }
+
     return self;
 }
 
+/* Forward declaration */
+static PyObject *
+DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
 
 static void
 DBTxn_dealloc(DBTxnObject* self)
 {
+  PyObject *dummy;
+
+    if (self->txn) {
+        int flag_prepare = self->flag_prepare;
+        dummy=DBTxn_abort_discard_internal(self,0);
+        Py_XDECREF(dummy);
+        if (!flag_prepare) {
+            PyErr_Warn(PyExc_RuntimeWarning,
+              "DBTxn aborted in destructor.  No prior commit() or abort().");
+        }
+    }
+
     if (self->in_weakreflist != NULL) {
         PyObject_ClearWeakRefs((PyObject *) self);
     }
 
-    if (self->txn) {
-        /* it hasn't been finalized, abort it! */
-        MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
-        self->txn->abort(self->txn);
-#else
-        txn_abort(self->txn);
-#endif
-        MYDB_END_ALLOW_THREADS;
-        PyErr_WarnEx(PyExc_RuntimeWarning,
-		     "DBTxn aborted in destructor. "
-		     " No prior commit() or abort().",
-		     1);
+    if (self->env) {
+        Py_DECREF(self->env);
+    } else {
+        Py_DECREF(self->parent_txn);
     }
-
-    Py_DECREF(self->env);
     PyObject_Del(self);
 }
 
@@ -1032,15 +1218,11 @@
     self->in_weakreflist = NULL;
 
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
                                   &self->lock);
-#else
-    err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
-#endif
     MYDB_END_ALLOW_THREADS;
     if (makeDBError(err)) {
-        PyObject_Del(self);
+        Py_DECREF(self);
         self = NULL;
     }
 
@@ -1070,25 +1252,37 @@
         return NULL;
     Py_INCREF(mydb);
     self->mydb = mydb;
-    self->in_weakreflist = NULL;
 
+    INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
+    self->txn = NULL;
+
+    self->in_weakreflist = NULL;
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = db_sequence_create(&self->sequence, self->mydb->db, flags);
     MYDB_END_ALLOW_THREADS;
     if (makeDBError(err)) {
-        Py_DECREF(self->mydb);
-        PyObject_Del(self);
+        Py_DECREF(self);
         self = NULL;
     }
 
     return self;
 }
 
+/* Forward declaration */
+static PyObject
+*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
 
 static void
 DBSequence_dealloc(DBSequenceObject* self)
 {
+    PyObject *dummy;
+
+    if (self->sequence != NULL) {
+        dummy=DBSequence_close_internal(self,0,0);
+        Py_XDECREF(dummy);
+    }
+
     if (self->in_weakreflist != NULL) {
         PyObject_ClearWeakRefs((PyObject *) self);
     }
@@ -1102,16 +1296,17 @@
 /* DB methods */
 
 static PyObject*
-DB_append(DBObject* self, PyObject* args)
+DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
 {
     PyObject* txnobj = NULL;
     PyObject* dataobj;
-    Py_buffer* data_buf_view = NULL;
     db_recno_t recno;
     DBT key, data;
     DB_TXN *txn = NULL;
+    static char* kwnames[] = { "data", "txn", NULL };
 
-    if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
+                                     &dataobj, &txnobj))
         return NULL;
 
     CHECK_DB_NOT_CLOSED(self);
@@ -1124,21 +1319,16 @@
     key.ulen = key.size;
     key.flags = DB_DBT_USERMEM;
 
+    if (!make_dbt(dataobj, &data)) return NULL;
     if (!checkTxnObj(txnobj, &txn)) return NULL;
-    if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
 
-    if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
-        free_buf_view(dataobj, data_buf_view);
+    if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
         return NULL;
-    }
 
-    free_buf_view(dataobj, data_buf_view);
-    return PyLong_FromLong(recno);
+    return NUMBER_FromLong(recno);
 }
 
 
-#if (DBVER >= 33)
-
 static int
 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
                       DBT* secKey)
@@ -1155,11 +1345,9 @@
         MYDB_BEGIN_BLOCK_THREADS;
 
         if (type == DB_RECNO || type == DB_QUEUE)
-            args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
-                                 priData->data, priData->size);
+            args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
         else
-            args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
-                                 priData->data, priData->size);
+            args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
         if (args != NULL) {
                 result = PyEval_CallObject(callback, args);
         }
@@ -1169,19 +1357,15 @@
         else if (result == Py_None) {
             retval = DB_DONOTINDEX;
         }
-        else if (PyLong_Check(result)) {
-            retval = PyLong_AsLong(result);
+        else if (NUMBER_Check(result)) {
+            retval = NUMBER_AsLong(result);
         }
-        else if (PyByteArray_Check(result) || PyBytes_Check(result)) {
+        else if (PyBytes_Check(result)) {
             char* data;
             Py_ssize_t size;
 
             CLEAR_DBT(*secKey);
-            size = Py_SIZE(result);
-            if (PyByteArray_Check(result))
-                data = PyByteArray_AS_STRING(result);
-            else
-                data = PyBytes_AS_STRING(result);
+            PyBytes_AsStringAndSize(result, &data, &size);
             secKey->flags = DB_DBT_APPMALLOC;   /* DB will free */
             secKey->data = malloc(size);        /* TODO, check this */
 	    if (secKey->data) {
@@ -1198,7 +1382,7 @@
         else {
             PyErr_SetString(
                PyExc_TypeError,
-               "DB associate callback should return DB_DONOTINDEX or bytes.");
+               "DB associate callback should return DB_DONOTINDEX or string.");
             PyErr_Print();
         }
 
@@ -1300,25 +1484,51 @@
 }
 
 
+static PyObject*
+DB_close_internal(DBObject* self, int flags)
+{
+    PyObject *dummy;
+    int err;
+
+    if (self->db != NULL) {
+        /* Can be NULL if db is not in an environment */
+        EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
+
+        if (self->txn) {
+            EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
+            self->txn=NULL;
+        }
+
+        while(self->children_cursors) {
+          dummy=DBC_close_internal(self->children_cursors);
+          Py_XDECREF(dummy);
+        }
+
+#if (DBVER >= 43)
+        while(self->children_sequences) {
+            dummy=DBSequence_close_internal(self->children_sequences,0,0);
+            Py_XDECREF(dummy);
+        }
 #endif
 
-
-static PyObject*
-DB_close(DBObject* self, PyObject* args)
-{
-    int err, flags=0;
-    if (!PyArg_ParseTuple(args,"|i:close", &flags))
-        return NULL;
-    if (self->db != NULL) {
-        if (self->myenvobj)
-            CHECK_ENV_NOT_CLOSED(self->myenvobj);
+        MYDB_BEGIN_ALLOW_THREADS;
         err = self->db->close(self->db, flags);
+        MYDB_END_ALLOW_THREADS;
         self->db = NULL;
         RETURN_IF_ERR();
     }
     RETURN_NONE();
 }
 
+static PyObject*
+DB_close(DBObject* self, PyObject* args)
+{
+    int flags=0;
+    if (!PyArg_ParseTuple(args,"|i:close", &flags))
+        return NULL;
+    return DB_close_internal(self,flags);
+}
+
 
 static PyObject*
 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
@@ -1349,7 +1559,7 @@
     CLEAR_DBT(key);
     CLEAR_DBT(data);
     if (CHECK_DBFLAG(self, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
+        /* Tell Berkeley DB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
         key.flags = DB_DBT_MALLOC;
     }
@@ -1365,10 +1575,9 @@
         retval = Py_None;
     }
     else if (!err) {
-        retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
-                               data.size);
-        free_dbt(&key);
-        free_dbt(&data);
+        retval = BuildValue_SS(key.data, key.size, data.data, data.size);
+        FREE_DBT(key);
+        FREE_DBT(data);
     }
 
     RETURN_IF_ERR();
@@ -1409,7 +1618,7 @@
     err = self->db->cursor(self->db, txn, &dbc, flags);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
-    return (PyObject*) newDBCursorObject(dbc, self);
+    return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
 }
 
 
@@ -1419,7 +1628,6 @@
     PyObject* txnobj = NULL;
     int flags = 0;
     PyObject* keyobj;
-    Py_buffer* key_buf_view = NULL;
     DBT key;
     DB_TXN *txn = NULL;
     static char* kwnames[] = { "key", "txn", "flags", NULL };
@@ -1428,37 +1636,35 @@
                                      &keyobj, &txnobj, &flags))
         return NULL;
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
     if (!checkTxnObj(txnobj, &txn)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
     if (-1 == _DB_delete(self, txn, &key, 0)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    FREE_DBT(key);
     RETURN_NONE();
 }
 
 
 static PyObject*
-DB_fd(DBObject* self, PyObject* args)
+DB_fd(DBObject* self)
 {
     int err, the_fd;
 
-    if (!PyArg_ParseTuple(args,":fd"))
-        return NULL;
     CHECK_DB_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->fd(self->db, &the_fd);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
-    return PyLong_FromLong(the_fd);
+    return NUMBER_FromLong(the_fd);
 }
 
 
@@ -1470,7 +1676,6 @@
     PyObject* keyobj;
     PyObject* dfltobj = NULL;
     PyObject* retval = NULL;
-    Py_buffer* key_buf_view = NULL;
     int dlen = -1;
     int doff = -1;
     DBT key, data;
@@ -1484,20 +1689,20 @@
         return NULL;
 
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, &flags))
         return NULL;
     if (!checkTxnObj(txnobj, &txn)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
     CLEAR_DBT(data);
     if (CHECK_DBFLAG(self, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
+        /* Tell Berkeley DB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
     }
     if (!add_partial_dbt(&data, dlen, doff)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
@@ -1518,19 +1723,17 @@
     }
     else if (!err) {
         if (flags & DB_SET_RECNO) /* return both key and data */
-            retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
-                                   data.size);
+            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
         else /* return just the data */
-            retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
-        free_dbt(&data);
+            retval = Build_PyString(data.data, data.size);
+        FREE_DBT(data);
     }
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    FREE_DBT(key);
 
     RETURN_IF_ERR();
     return retval;
 }
 
-#if (DBVER >= 33)
 static PyObject*
 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
 {
@@ -1539,7 +1742,6 @@
     PyObject* keyobj;
     PyObject* dfltobj = NULL;
     PyObject* retval = NULL;
-    Py_buffer* key_buf_view = NULL;
     int dlen = -1;
     int doff = -1;
     DBT key, pkey, data;
@@ -1553,26 +1755,26 @@
         return NULL;
 
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, &flags))
         return NULL;
     if (!checkTxnObj(txnobj, &txn)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
     CLEAR_DBT(data);
     if (CHECK_DBFLAG(self, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
+        /* Tell Berkeley DB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
     }
     if (!add_partial_dbt(&data, dlen, doff)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
     CLEAR_DBT(pkey);
     pkey.flags = DB_DBT_MALLOC;
-    
+
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
     MYDB_END_ALLOW_THREADS;
@@ -1591,22 +1793,22 @@
     else if (!err) {
         PyObject *pkeyObj;
         PyObject *dataObj;
-        dataObj = PyBytes_FromStringAndSize(data.data, data.size);
+        dataObj = Build_PyString(data.data, data.size);
 
         if (self->primaryDBType == DB_RECNO ||
             self->primaryDBType == DB_QUEUE)
-            pkeyObj = PyLong_FromLong(*(int *)pkey.data);
+            pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
         else
-            pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
+            pkeyObj = Build_PyString(pkey.data, pkey.size);
 
         if (flags & DB_SET_RECNO) /* return key , pkey and data */
         {
             PyObject *keyObj;
             int type = _DB_get_type(self);
             if (type == DB_RECNO || type == DB_QUEUE)
-                keyObj = PyLong_FromLong(*(int *)key.data);
+                keyObj = NUMBER_FromLong(*(int *)key.data);
             else
-                keyObj = PyBytes_FromStringAndSize(key.data, key.size);
+                keyObj = Build_PyString(key.data, key.size);
 #if (PY_VERSION_HEX >= 0x02040000)
             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
 #else
@@ -1624,15 +1826,14 @@
         }
         Py_DECREF(dataObj);
         Py_DECREF(pkeyObj);
-	free_dbt(&pkey);
-        free_dbt(&data);
+        FREE_DBT(pkey);
+        FREE_DBT(data);
     }
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    FREE_DBT(key);
 
     RETURN_IF_ERR();
     return retval;
 }
-#endif
 
 
 /* Return size of entry */
@@ -1643,7 +1844,6 @@
     PyObject* txnobj = NULL;
     PyObject* keyobj;
     PyObject* retval = NULL;
-    Py_buffer* key_buf_view = NULL;
     DBT key, data;
     DB_TXN *txn = NULL;
     static char* kwnames[] = { "key", "txn", NULL };
@@ -1652,10 +1852,10 @@
                                      &keyobj, &txnobj))
         return NULL;
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, &flags))
         return NULL;
     if (!checkTxnObj(txnobj, &txn)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
     CLEAR_DBT(data);
@@ -1668,12 +1868,12 @@
     err = self->db->get(self->db, txn, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
     if (err == DB_BUFFER_SMALL) {
-        retval = PyLong_FromLong((long)data.size);
+        retval = NUMBER_FromLong((long)data.size);
         err = 0;
     }
 
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
-    free_dbt(&data);
+    FREE_DBT(key);
+    FREE_DBT(data);
     RETURN_IF_ERR();
     return retval;
 }
@@ -1687,25 +1887,22 @@
     PyObject* keyobj;
     PyObject* dataobj;
     PyObject* retval = NULL;
-    Py_buffer* data_buf_view = NULL;
-    Py_buffer* key_buf_view = NULL;
     DBT key, data;
     void *orig_data;
     DB_TXN *txn = NULL;
     static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
 
-
     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
                                      &keyobj, &dataobj, &txnobj, &flags))
         return NULL;
 
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
-    if ( !checkTxnObj(txnobj, &txn) ||
-         !make_dbt(dataobj, &data, &data_buf_view) )
+    if ( !make_dbt(dataobj, &data) ||
+         !checkTxnObj(txnobj, &txn) )
     {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
@@ -1713,7 +1910,7 @@
     orig_data = data.data;
 
     if (CHECK_DBFLAG(self, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
+        /* Tell Berkeley DB to malloc the return value (thread safe) */
         /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
         data.flags = DB_DBT_MALLOC;
     }
@@ -1722,8 +1919,6 @@
     err = self->db->get(self->db, txn, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
-    free_buf_view(dataobj, data_buf_view);
-
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 	    && self->moduleFlags.getReturnsNone) {
         err = 0;
@@ -1732,61 +1927,47 @@
     }
     else if (!err) {
         /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
-        /* XXX(gps) I think not: buffer API input vs. bytes object output. */
-        /* XXX(guido) But what if the input is PyString? */
-        retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
+        retval = Build_PyString(data.data, data.size);
 
         /* Even though the flags require DB_DBT_MALLOC, data is not always
            allocated.  4.4: allocated, 4.5: *not* allocated. :-( */
         if (data.data != orig_data)
-            free_dbt(&data);
+            FREE_DBT(data);
     }
 
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    FREE_DBT(key);
     RETURN_IF_ERR();
     return retval;
 }
 
 
 static PyObject*
-DB_get_byteswapped(DBObject* self, PyObject* args)
+DB_get_byteswapped(DBObject* self)
 {
-#if (DBVER >= 33)
     int err = 0;
-#endif
     int retval = -1;
 
-    if (!PyArg_ParseTuple(args,":get_byteswapped"))
-        return NULL;
     CHECK_DB_NOT_CLOSED(self);
 
-#if (DBVER >= 33)
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->get_byteswapped(self->db, &retval);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
-#else
-    MYDB_BEGIN_ALLOW_THREADS;
-    retval = self->db->get_byteswapped(self->db);
-    MYDB_END_ALLOW_THREADS;
-#endif
-    return PyLong_FromLong(retval);
+    return NUMBER_FromLong(retval);
 }
 
 
 static PyObject*
-DB_get_type(DBObject* self, PyObject* args)
+DB_get_type(DBObject* self)
 {
     int type;
 
-    if (!PyArg_ParseTuple(args,":get_type"))
-        return NULL;
     CHECK_DB_NOT_CLOSED(self);
 
     type = _DB_get_type(self);
     if (type == -1)
         return NULL;
-    return PyLong_FromLong(type);
+    return NUMBER_FromLong(type);
 }
 
 
@@ -1845,7 +2026,7 @@
        but does not hold python references to them or prevent
        them from being closed prematurely.  This can cause
        python to crash when things are done in the wrong order. */
-    return (PyObject*) newDBCursorObject(dbc, self);
+    return (PyObject*) newDBCursorObject(dbc, NULL, self);
 }
 
 
@@ -1855,7 +2036,6 @@
     int err, flags=0;
     PyObject* txnobj = NULL;
     PyObject* keyobj;
-    Py_buffer* key_buf_view = NULL;
     DBT key;
     DB_TXN *txn = NULL;
     DB_KEY_RANGE range;
@@ -1865,18 +2045,16 @@
                                      &keyobj, &txnobj, &flags))
         return NULL;
     CHECK_DB_NOT_CLOSED(self);
-    if (!checkTxnObj(txnobj, &txn))
-        return NULL;
-    if (!make_dbt(keyobj, &key, &key_buf_view))
+    if (!make_dbt(keyobj, &key))
         /* BTree only, don't need to allow for an int key */
         return NULL;
+    if (!checkTxnObj(txnobj, &txn))
+        return NULL;
 
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->key_range(self->db, txn, &key, &range, flags);
     MYDB_END_ALLOW_THREADS;
 
-    free_buf_view(keyobj, key_buf_view);
-
     RETURN_IF_ERR();
     return Py_BuildValue("ddd", range.less, range.equal, range.greater);
 }
@@ -1940,11 +2118,24 @@
     if (NULL == self->db) {
         PyObject *t = Py_BuildValue("(is)", 0,
                                 "Cannot call open() twice for DB object");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         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);
@@ -1953,8 +2144,10 @@
 #endif
     MYDB_END_ALLOW_THREADS;
     if (makeDBError(err)) {
-        self->db->close(self->db, 0);
-        self->db = NULL;
+        PyObject *dummy;
+
+        dummy=DB_close_internal(self,0);
+        Py_XDECREF(dummy);
         return NULL;
     }
 
@@ -1963,6 +2156,7 @@
 #endif
 
     self->flags = flags;
+
     RETURN_NONE();
 }
 
@@ -1974,9 +2168,7 @@
     PyObject* txnobj = NULL;
     int dlen = -1;
     int doff = -1;
-    PyObject *keyobj, *dataobj, *retval;
-    Py_buffer *data_buf_view = NULL;
-    Py_buffer *key_buf_view = NULL;
+    PyObject* keyobj, *dataobj, *retval;
     DBT key, data;
     DB_TXN *txn = NULL;
     static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
@@ -1987,31 +2179,28 @@
         return NULL;
 
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
-    if ( !make_dbt(dataobj, &data, &data_buf_view) ||
+    if ( !make_dbt(dataobj, &data) ||
          !add_partial_dbt(&data, dlen, doff) ||
          !checkTxnObj(txnobj, &txn) )
     {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
-        free_buf_view(dataobj, data_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
     if (-1 == _DB_put(self, txn, &key, &data, flags)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
-        free_buf_view(dataobj, data_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
     if (flags & DB_APPEND)
-        retval = PyLong_FromLong(*((db_recno_t*)key.data));
+        retval = NUMBER_FromLong(*((db_recno_t*)key.data));
     else {
         retval = Py_None;
         Py_INCREF(retval);
     }
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
-    free_buf_view(dataobj, data_buf_view);
+    FREE_DBT(key);
     return retval;
 }
 
@@ -2030,7 +2219,12 @@
         return NULL;
     CHECK_DB_NOT_CLOSED(self);
 
+    EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->remove(self->db, filename, database, flags);
+    MYDB_END_ALLOW_THREADS;
+
     self->db = NULL;
     RETURN_IF_ERR();
     RETURN_NONE();
@@ -2060,6 +2254,25 @@
 
 
 static PyObject*
+DB_get_private(DBObject* self)
+{
+    /* We can give out the private field even if db is closed */
+    Py_INCREF(self->private_obj);
+    return self->private_obj;
+}
+
+static PyObject*
+DB_set_private(DBObject* self, PyObject* private_obj)
+{
+    /* We can set the private field even if db is closed */
+    Py_DECREF(self->private_obj);
+    Py_INCREF(private_obj);
+    self->private_obj = private_obj;
+    RETURN_NONE();
+}
+
+
+static PyObject*
 DB_set_bt_minkey(DBObject* self, PyObject* args)
 {
     int err, minkey;
@@ -2075,17 +2288,16 @@
     RETURN_NONE();
 }
 
-#if (DBVER >= 33)
-static int 
+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, 
+  res = memcmp(leftKey->data, rightKey->data,
 	       lsize < rsize ? lsize : rsize);
-  
+
   if (res == 0) {
       if (lsize < rsize) {
 	  res = -1;
@@ -2098,7 +2310,7 @@
 }
 
 static int
-_db_compareCallback(DB* db, 
+_db_compareCallback(DB* db,
 		    const DBT *leftKey,
 		    const DBT *rightKey)
 {
@@ -2120,8 +2332,7 @@
     } else {
 	MYDB_BEGIN_BLOCK_THREADS;
 
-	args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
-			     rightKey->data, rightKey->size);
+	args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
 	if (args != NULL) {
 		/* XXX(twouters) I highly doubt this INCREF is correct */
 		Py_INCREF(self);
@@ -2131,8 +2342,8 @@
 	    /* we're in a callback within the DB code, we can't raise */
 	    PyErr_Print();
 	    res = _default_cmp(leftKey, rightKey);
-	} else if (PyLong_Check(result)) {
-	    res = PyLong_AsLong(result);
+	} else if (NUMBER_Check(result)) {
+	    res = NUMBER_AsLong(result);
 	} else {
 	    PyErr_SetString(PyExc_TypeError,
 			    "DB_bt_compare callback MUST return an int.");
@@ -2140,7 +2351,7 @@
 	    PyErr_Print();
 	    res = _default_cmp(leftKey, rightKey);
 	}
-    
+
 	Py_XDECREF(args);
 	Py_XDECREF(result);
 
@@ -2150,15 +2361,11 @@
 }
 
 static PyObject*
-DB_set_bt_compare(DBObject* self, PyObject* args)
+DB_set_bt_compare(DBObject* self, PyObject* comparator)
 {
     int err;
-    PyObject *comparator;
     PyObject *tuple, *result;
 
-    if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
-	return NULL;
-
     CHECK_DB_NOT_CLOSED(self);
 
     if (!PyCallable_Check(comparator)) {
@@ -2166,7 +2373,7 @@
 	return NULL;
     }
 
-    /* 
+    /*
      * Perform a test call of the comparator function with two empty
      * string objects here.  verify that it returns an int (0).
      * err if not.
@@ -2176,11 +2383,11 @@
     Py_DECREF(tuple);
     if (result == NULL)
         return NULL;
-    if (!PyLong_Check(result)) {
+    if (!NUMBER_Check(result)) {
 	PyErr_SetString(PyExc_TypeError,
 		        "callback MUST return an int");
 	return NULL;
-    } else if (PyLong_AsLong(result) != 0) {
+    } else if (NUMBER_AsLong(result) != 0) {
 	PyErr_SetString(PyExc_TypeError,
 		        "callback failed to return 0 on two empty strings");
 	return NULL;
@@ -2215,7 +2422,6 @@
     RETURN_IF_ERR();
     RETURN_NONE();
 }
-#endif /* DBVER >= 33 */
 
 
 static PyObject*
@@ -2447,10 +2653,8 @@
     MYDB_BEGIN_ALLOW_THREADS;
 #if (DBVER >= 43)
     err = self->db->stat(self->db, txn, &sp, flags);
-#elif (DBVER >= 33)
-    err = self->db->stat(self->db, &sp, flags);
 #else
-    err = self->db->stat(self->db, &sp, NULL, flags);
+    err = self->db->stat(self->db, &sp, flags);
 #endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
@@ -2474,6 +2678,9 @@
         MAKE_HASH_ENTRY(version);
         MAKE_HASH_ENTRY(nkeys);
         MAKE_HASH_ENTRY(ndata);
+#if (DBVER >= 46)
+        MAKE_HASH_ENTRY(pagecnt);
+#endif
         MAKE_HASH_ENTRY(pagesize);
 #if (DBVER < 41)
         MAKE_HASH_ENTRY(nelem);
@@ -2496,6 +2703,9 @@
         MAKE_BT_ENTRY(version);
         MAKE_BT_ENTRY(nkeys);
         MAKE_BT_ENTRY(ndata);
+#if (DBVER >= 46)
+        MAKE_BT_ENTRY(pagecnt);
+#endif
         MAKE_BT_ENTRY(pagesize);
         MAKE_BT_ENTRY(minkey);
         MAKE_BT_ENTRY(re_len);
@@ -2505,6 +2715,9 @@
         MAKE_BT_ENTRY(leaf_pg);
         MAKE_BT_ENTRY(dup_pg);
         MAKE_BT_ENTRY(over_pg);
+#if (DBVER >= 43)
+        MAKE_BT_ENTRY(empty_pg);
+#endif
         MAKE_BT_ENTRY(free);
         MAKE_BT_ENTRY(int_pgfree);
         MAKE_BT_ENTRY(leaf_pgfree);
@@ -2518,6 +2731,9 @@
         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);
@@ -2561,7 +2777,6 @@
 }
 
 
-#if (DBVER >= 33)
 static PyObject*
 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
 {
@@ -2582,9 +2797,8 @@
     err = self->db->truncate(self->db, txn, &count, flags);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
-    return PyLong_FromLong(count);
+    return NUMBER_FromLong(count);
 }
-#endif
 
 
 static PyObject*
@@ -2632,15 +2846,14 @@
     if (outFile)
         fclose(outFile);
 
-    /* DB.verify acts as a DB handle destructor (like close); this was
-     * documented in BerkeleyDB 4.2 but had the undocumented effect
-     * of not being safe in prior versions while still requiring an explicit
-     * DB.close call afterwards.  Lets call close for the user to emulate
-     * the safe 4.2 behaviour. */
-#if (DBVER <= 41)
-    self->db->close(self->db, 0);
-#endif
-    self->db = NULL;
+    {  /* DB.verify acts as a DB handle destructor (like close) */
+        PyObject *error;
+
+        error=DB_close_internal(self,0);
+        if (error ) {
+          return error;
+        }
+     }
 
     RETURN_IF_ERR();
     RETURN_NONE();
@@ -2663,7 +2876,7 @@
         ++oldValue;
     self->moduleFlags.getReturnsNone = (flags >= 1);
     self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
-    return PyLong_FromLong(oldValue);
+    return NUMBER_FromLong(oldValue);
 }
 
 #if (DBVER >= 41)
@@ -2703,8 +2916,10 @@
 
     if (self->db == NULL) {
         PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         return -1;
     }
 
@@ -2717,17 +2932,15 @@
 redo_stat_for_length:
 #if (DBVER >= 43)
     err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
-#elif (DBVER >= 33)
-    err = self->db->stat(self->db, &sp, flags);
 #else
-    err = self->db->stat(self->db, &sp, NULL, flags);
+    err = self->db->stat(self->db, &sp, flags);
 #endif
 
     /* 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 BerkeleyDB no longer had the stat values cached.
+    /* 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
      */
@@ -2754,17 +2967,16 @@
 {
     int err;
     PyObject* retval;
-    Py_buffer* key_buf_view = NULL;
     DBT key;
     DBT data;
 
     CHECK_DB_NOT_CLOSED(self);
-    if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
 
     CLEAR_DBT(data);
     if (CHECK_DBFLAG(self, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
+        /* Tell Berkeley DB to malloc the return value (thread safe) */
         data.flags = DB_DBT_MALLOC;
     }
     MYDB_BEGIN_ALLOW_THREADS;
@@ -2778,11 +2990,11 @@
         retval = NULL;
     }
     else {
-        retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
-        free_dbt(&data);
+        retval = Build_PyString(data.data, data.size);
+        FREE_DBT(data);
     }
 
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    FREE_DBT(key);
     return retval;
 }
 
@@ -2793,21 +3005,21 @@
     DBT key, data;
     int retval;
     int flags = 0;
-    Py_buffer *data_buf_view = NULL;
-    Py_buffer *key_buf_view = NULL;
 
     if (self->db == NULL) {
         PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         return -1;
     }
 
-    if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, NULL))
         return -1;
 
     if (dataobj != NULL) {
-        if (!make_dbt(dataobj, &data, &data_buf_view))
+        if (!make_dbt(dataobj, &data))
             retval =  -1;
         else {
             if (self->setflags & (DB_DUP|DB_DUPSORT))
@@ -2828,29 +3040,30 @@
         /* dataobj == NULL, so delete the key */
         retval = _DB_delete(self, NULL, &key, 0);
     }
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
-    free_buf_view(dataobj, data_buf_view);
+    FREE_DBT(key);
     return retval;
 }
 
 
 static PyObject*
-DB_has_key(DBObject* self, PyObject* args)
+DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
 {
     int err;
     PyObject* keyobj;
-    Py_buffer* key_buf_view = NULL;
     DBT key, data;
     PyObject* txnobj = NULL;
     DB_TXN *txn = NULL;
+    static char* kwnames[] = {"key","txn", NULL};
 
-    if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
+    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, &key_buf_view))
+    if (!make_key_dbt(self, keyobj, &key, NULL))
         return NULL;
     if (!checkTxnObj(txnobj, &txn)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);
         return NULL;
     }
 
@@ -2864,12 +3077,12 @@
     MYDB_BEGIN_ALLOW_THREADS;
     err = self->db->get(self->db, txn, &key, &data, 0);
     MYDB_END_ALLOW_THREADS;
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    FREE_DBT(key);
 
     if (err == DB_BUFFER_SMALL || err == 0) {
-        return PyLong_FromLong(1);
+        return NUMBER_FromLong(1);
     } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
-        return PyLong_FromLong(0);
+        return NUMBER_FromLong(0);
     }
 
     makeDBError(err);
@@ -2912,14 +3125,9 @@
         return NULL;
     }
 
-    if (CHECK_DBFLAG(self, DB_THREAD)) {
-        key.flags = DB_DBT_REALLOC;
-        data.flags = DB_DBT_REALLOC;
-    }
-
     while (1) { /* use the cursor to traverse the DB, collecting items */
         MYDB_BEGIN_ALLOW_THREADS;
-        err = cursor->c_get(cursor, &key, &data, DB_NEXT);
+        err = _DBC_get(cursor, &key, &data, DB_NEXT);
         MYDB_END_ALLOW_THREADS;
 
         if (err) {
@@ -2933,17 +3141,17 @@
             case DB_BTREE:
             case DB_HASH:
             default:
-                item = PyBytes_FromStringAndSize((char*)key.data, key.size);
+                item = Build_PyString(key.data, key.size);
                 break;
             case DB_RECNO:
             case DB_QUEUE:
-                item = PyLong_FromLong(*((db_recno_t*)key.data));
+                item = NUMBER_FromLong(*((db_recno_t*)key.data));
                 break;
             }
             break;
 
         case _VALUES_LIST:
-            item = PyBytes_FromStringAndSize((char*)data.data, data.size);
+            item = Build_PyString(data.data, data.size);
             break;
 
         case _ITEMS_LIST:
@@ -2951,13 +3159,11 @@
             case DB_BTREE:
             case DB_HASH:
             default:
-                item = Py_BuildValue("y#y#", key.data, key.size, data.data,
-                                     data.size);
+                item = BuildValue_SS(key.data, key.size, data.data, data.size);
                 break;
             case DB_RECNO:
             case DB_QUEUE:
-                item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
-                                     data.data, data.size);
+                item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
                 break;
             }
             break;
@@ -2971,7 +3177,12 @@
             list = NULL;
             goto done;
         }
-        PyList_Append(list, item);
+        if (PyList_Append(list, item)) {
+            Py_DECREF(list);
+            Py_DECREF(item);
+            list = NULL;
+            goto done;
+        }
         Py_DECREF(item);
     }
 
@@ -2982,10 +3193,8 @@
     }
 
  done:
-    free_dbt(&key);
-    free_dbt(&data);
     MYDB_BEGIN_ALLOW_THREADS;
-    cursor->c_close(cursor);
+    _DBC_close(cursor);
     MYDB_END_ALLOW_THREADS;
     return list;
 }
@@ -3037,23 +3246,32 @@
 
 
 static PyObject*
-DBC_close(DBCursorObject* self, PyObject* args)
+DBC_close_internal(DBCursorObject* self)
 {
     int err = 0;
 
-    if (!PyArg_ParseTuple(args, ":close"))
-        return NULL;
-
     if (self->dbc != NULL) {
+        EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+        if (self->txn) {
+            EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
+            self->txn=NULL;
+        }
+
         MYDB_BEGIN_ALLOW_THREADS;
-        err = self->dbc->c_close(self->dbc);
-        self->dbc = NULL;
+        err = _DBC_close(self->dbc);
         MYDB_END_ALLOW_THREADS;
+        self->dbc = NULL;
     }
     RETURN_IF_ERR();
     RETURN_NONE();
 }
 
+static PyObject*
+DBC_close(DBCursorObject* self)
+{
+    return DBC_close_internal(self);
+}
+
 
 static PyObject*
 DBC_count(DBCursorObject* self, PyObject* args)
@@ -3068,11 +3286,11 @@
     CHECK_CURSOR_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_count(self->dbc, &count, flags);
+    err = _DBC_count(self->dbc, &count, flags);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
-    return PyLong_FromLong(count);
+    return NUMBER_FromLong(count);
 }
 
 
@@ -3094,7 +3312,7 @@
     CHECK_CURSOR_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_del(self->dbc, flags);
+    err = _DBC_del(self->dbc, flags);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
@@ -3115,11 +3333,11 @@
     CHECK_CURSOR_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_dup(self->dbc, &dbc, flags);
+    err = _DBC_dup(self->dbc, &dbc, flags);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
-    return (PyObject*) newDBCursorObject(dbc, self->mydb);
+    return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
 }
 
 static PyObject*
@@ -3136,8 +3354,6 @@
     PyObject* keyobj = NULL;
     PyObject* dataobj = NULL;
     PyObject* retval = NULL;
-    Py_buffer* data_buf_view = NULL;
-    Py_buffer* key_buf_view = NULL;
     int dlen = -1;
     int doff = -1;
     DBT key, data;
@@ -3151,7 +3367,7 @@
     {
         PyErr_Clear();
         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
-                                         &kwnames[1], 
+                                         &kwnames[1],
 					 &keyobj, &flags, &dlen, &doff))
         {
             PyErr_Clear();
@@ -3166,25 +3382,17 @@
 
     CHECK_CURSOR_NOT_CLOSED(self);
 
-    if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
+    if ( (dataobj && !make_dbt(dataobj, &data)) ||
          (!add_partial_dbt(&data, dlen, doff)) )
     {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
-        free_buf_view(dataobj, data_buf_view);
+        FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
         return NULL;
     }
 
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        data.flags = DB_DBT_MALLOC;
-        if (!(key.flags & DB_DBT_REALLOC)) {
-            key.flags |= DB_DBT_MALLOC;
-        }
-    }
-
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags);
+    err = _DBC_get(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
@@ -3203,23 +3411,18 @@
         case DB_BTREE:
         case DB_HASH:
         default:
-            retval = Py_BuildValue("y#y#", key.data, key.size,
-                                   data.data, data.size);
+            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
             break;
         case DB_RECNO:
         case DB_QUEUE:
-            retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
-                                   data.data, data.size);
+            retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
             break;
         }
-        free_dbt(&data);
     }
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
-    free_buf_view(dataobj, data_buf_view);
+    FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     return retval;
 }
 
-#if (DBVER >= 33)
 static PyObject*
 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
 {
@@ -3227,8 +3430,6 @@
     PyObject* keyobj = NULL;
     PyObject* dataobj = NULL;
     PyObject* retval = NULL;
-    Py_buffer* data_buf_view = NULL;
-    Py_buffer* key_buf_view = NULL;
     int dlen = -1;
     int doff = -1;
     DBT key, pkey, data;
@@ -3257,27 +3458,19 @@
 
     CHECK_CURSOR_NOT_CLOSED(self);
 
-    if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
+    if ( (dataobj && !make_dbt(dataobj, &data)) ||
          (!add_partial_dbt(&data, dlen, doff)) ) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
-        free_buf_view(dataobj, data_buf_view);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
         return NULL;
     }
 
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        data.flags = DB_DBT_MALLOC;
-        if (!(key.flags & DB_DBT_REALLOC)) {
-            key.flags |= DB_DBT_MALLOC;
-        }
-    }
-
     CLEAR_DBT(pkey);
     pkey.flags = DB_DBT_MALLOC;
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
+    err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
     MYDB_END_ALLOW_THREADS;
 
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
@@ -3291,76 +3484,71 @@
     else {
         PyObject *pkeyObj;
         PyObject *dataObj;
-        dataObj = PyBytes_FromStringAndSize(data.data, data.size);
+        dataObj = Build_PyString(data.data, data.size);
 
         if (self->mydb->primaryDBType == DB_RECNO ||
             self->mydb->primaryDBType == DB_QUEUE)
-            pkeyObj = PyLong_FromLong(*(int *)pkey.data);
+            pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
         else
-            pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
+            pkeyObj = Build_PyString(pkey.data, pkey.size);
 
         if (key.data && key.size) /* return key, pkey and data */
         {
             PyObject *keyObj;
             int type = _DB_get_type(self->mydb);
             if (type == DB_RECNO || type == DB_QUEUE)
-                keyObj = PyLong_FromLong(*(int *)key.data);
+                keyObj = NUMBER_FromLong(*(int *)key.data);
             else
-                keyObj = PyBytes_FromStringAndSize(key.data, key.size);
+                keyObj = Build_PyString(key.data, key.size);
+#if (PY_VERSION_HEX >= 0x02040000)
             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
+#else
+            retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
+#endif
             Py_DECREF(keyObj);
+            FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
         }
         else /* return just the pkey and data */
         {
+#if (PY_VERSION_HEX >= 0x02040000)
             retval = PyTuple_Pack(2, pkeyObj, dataObj);
+#else
+            retval = Py_BuildValue("OO", pkeyObj, dataObj);
+#endif
         }
         Py_DECREF(dataObj);
         Py_DECREF(pkeyObj);
-        free_dbt(&pkey);
-        free_dbt(&data);
+        FREE_DBT(pkey);
     }
     /* the only time REALLOC should be set is if we used an integer
      * key that make_key_dbt malloc'd for us.  always free these. */
-    if (key.flags & DB_DBT_REALLOC) {
-        free_dbt(&key);
+    if (key.flags & DB_DBT_REALLOC) {  /* 'make_key_dbt' could do a 'malloc' */
+        FREE_DBT(key);
     }
-    free_buf_view(keyobj, key_buf_view);
-    free_buf_view(dataobj, data_buf_view);
     return retval;
 }
-#endif
 
 
 static PyObject*
-DBC_get_recno(DBCursorObject* self, PyObject* args)
+DBC_get_recno(DBCursorObject* self)
 {
     int err;
     db_recno_t recno;
     DBT key;
     DBT data;
 
-    if (!PyArg_ParseTuple(args, ":get_recno"))
-        return NULL;
-
     CHECK_CURSOR_NOT_CLOSED(self);
 
     CLEAR_DBT(key);
     CLEAR_DBT(data);
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        data.flags = DB_DBT_MALLOC;
-        key.flags = DB_DBT_MALLOC;
-    }
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
+    err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
     recno = *((db_recno_t*)data.data);
-    free_dbt(&key);
-    free_dbt(&data);
-    return PyLong_FromLong(recno);
+    return NUMBER_FromLong(recno);
 }
 
 
@@ -3389,9 +3577,7 @@
 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
 {
     int err, flags = 0;
-    PyObject *keyobj, *dataobj;
-    Py_buffer *data_buf_view = NULL;
-    Py_buffer *key_buf_view = NULL;
+    PyObject* keyobj, *dataobj;
     DBT key, data;
     static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
                                      NULL };
@@ -3404,21 +3590,19 @@
 
     CHECK_CURSOR_NOT_CLOSED(self);
 
-    if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if (!make_dbt(dataobj, &data, &data_buf_view) ||
+    if (!make_dbt(dataobj, &data) ||
         !add_partial_dbt(&data, dlen, doff) )
     {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
-        free_buf_view(dataobj, data_buf_view);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
         return NULL;
     }
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_put(self->dbc, &key, &data, flags);
+    err = _DBC_put(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
-    free_buf_view(dataobj, data_buf_view);
+    FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     RETURN_IF_ERR();
     self->mydb->haveStat = 0;
     RETURN_NONE();
@@ -3430,8 +3614,7 @@
 {
     int err, flags = 0;
     DBT key, data;
-    PyObject *retval, *keyobj;
-    Py_buffer *key_buf_view = NULL;
+    PyObject* retval, *keyobj;
     static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
     int dlen = -1;
     int doff = -1;
@@ -3442,21 +3625,17 @@
 
     CHECK_CURSOR_NOT_CLOSED(self);
 
-    if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
 
     CLEAR_DBT(data);
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        data.flags = DB_DBT_MALLOC;
-    }
     if (!add_partial_dbt(&data, dlen, doff)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
         return NULL;
     }
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
+    err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
     MYDB_END_ALLOW_THREADS;
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 	    && self->mydb->moduleFlags.cursorSetReturnsNone) {
@@ -3474,24 +3653,20 @@
         case DB_BTREE:
         case DB_HASH:
         default:
-            retval = Py_BuildValue("y#y#", key.data, key.size,
-                                   data.data, data.size);
+            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
             break;
         case DB_RECNO:
         case DB_QUEUE:
-            retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
-                                   data.data, data.size);
+            retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
             break;
         }
-        free_dbt(&data);
-        free_dbt(&key);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     }
     /* the only time REALLOC should be set is if we used an integer
      * key that make_key_dbt malloc'd for us.  always free these. */
     if (key.flags & DB_DBT_REALLOC) {
-        free_dbt(&key);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     }
-    free_buf_view(keyobj, key_buf_view);
 
     return retval;
 }
@@ -3502,8 +3677,7 @@
 {
     int err, flags = 0;
     DBT key, data;
-    PyObject *retval, *keyobj;
-    Py_buffer *key_buf_view = NULL;
+    PyObject* retval, *keyobj;
     static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
     int dlen = -1;
     int doff = -1;
@@ -3514,24 +3688,16 @@
 
     CHECK_CURSOR_NOT_CLOSED(self);
 
-    if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
 
     CLEAR_DBT(data);
     if (!add_partial_dbt(&data, dlen, doff)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
         return NULL;
     }
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        data.flags |= DB_DBT_MALLOC;
-        /* only BTREE databases will return anything in the key */
-        if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
-            key.flags |= DB_DBT_MALLOC;
-        }
-    }
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
+    err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
     MYDB_END_ALLOW_THREADS;
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 	    && self->mydb->moduleFlags.cursorSetReturnsNone) {
@@ -3549,24 +3715,20 @@
         case DB_BTREE:
         case DB_HASH:
         default:
-            retval = Py_BuildValue("y#y#", key.data, key.size,
-                                   data.data, data.size);
+            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
             break;
         case DB_RECNO:
         case DB_QUEUE:
-            retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
-                                   data.data, data.size);
+            retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
             break;
         }
-        free_dbt(&key);
-        free_dbt(&data);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     }
     /* the only time REALLOC should be set is if we used an integer
      * key that make_key_dbt malloc'd for us.  always free these. */
     if (key.flags & DB_DBT_REALLOC) {
-        free_dbt(&key);
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     }
-    free_buf_view(keyobj, key_buf_view);
 
     return retval;
 }
@@ -3577,20 +3739,18 @@
 {
     int err;
     DBT key, data;
-    PyObject *retval;
-    Py_buffer *data_buf_view = NULL;
-    Py_buffer *key_buf_view = NULL;
+    PyObject* retval;
 
     /* the caller did this:  CHECK_CURSOR_NOT_CLOSED(self); */
-    if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
-    if (!make_dbt(dataobj, &data, &data_buf_view)) {
-        FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    if (!make_dbt(dataobj, &data)) {
+        FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
         return NULL;
     }
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
+    err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
     MYDB_END_ALLOW_THREADS;
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
         Py_INCREF(Py_None);
@@ -3607,19 +3767,16 @@
         case DB_BTREE:
         case DB_HASH:
         default:
-            retval = Py_BuildValue("y#y#", key.data, key.size,
-                                   data.data, data.size);
+            retval = BuildValue_SS(key.data, key.size, data.data, data.size);
             break;
         case DB_RECNO:
         case DB_QUEUE:
-            retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
-                                   data.data, data.size);
+            retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
             break;
         }
     }
 
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
-    free_buf_view(dataobj, data_buf_view);
+    FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
     return retval;
 }
 
@@ -3641,14 +3798,12 @@
 
 /* Return size of entry */
 static PyObject*
-DBC_get_current_size(DBCursorObject* self, PyObject* args)
+DBC_get_current_size(DBCursorObject* self)
 {
     int err, flags=DB_CURRENT;
     PyObject* retval = NULL;
     DBT key, data;
 
-    if (!PyArg_ParseTuple(args, ":get_current_size"))
-        return NULL;
     CHECK_CURSOR_NOT_CLOSED(self);
     CLEAR_DBT(key);
     CLEAR_DBT(data);
@@ -3658,16 +3813,14 @@
     data.flags = DB_DBT_USERMEM;
     data.ulen = 0;
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags);
+    err = _DBC_get(self->dbc, &key, &data, flags);
     MYDB_END_ALLOW_THREADS;
     if (err == DB_BUFFER_SMALL || !err) {
         /* DB_BUFFER_SMALL means positive size, !err means zero length value */
-        retval = PyLong_FromLong((long)data.size);
+        retval = NUMBER_FromLong((long)data.size);
         err = 0;
     }
 
-    free_dbt(&key);
-    free_dbt(&data);
     RETURN_IF_ERR();
     return retval;
 }
@@ -3721,17 +3874,13 @@
     key.flags = DB_DBT_REALLOC;
 
     CLEAR_DBT(data);
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        data.flags = DB_DBT_MALLOC;
-    }
     if (!add_partial_dbt(&data, dlen, doff)) {
-        free_dbt(&key);
+        FREE_DBT(key);
         return NULL;
     }
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
+    err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
     MYDB_END_ALLOW_THREADS;
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 	    && self->mydb->moduleFlags.cursorSetReturnsNone) {
@@ -3742,11 +3891,9 @@
         retval = NULL;
     }
     else {  /* Can only be used for BTrees, so no need to return int key */
-        retval = Py_BuildValue("y#y#", key.data, key.size,
-                               data.data, data.size);
-        free_dbt(&data);
+        retval = BuildValue_SS(key.data, key.size, data.data, data.size);
     }
-    free_dbt(&key);
+    FREE_DBT(key);
 
     return retval;
 }
@@ -3794,13 +3941,9 @@
 
     CLEAR_DBT(key);
     CLEAR_DBT(data);
-    if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
-        /* Tell BerkeleyDB to malloc the return value (thread safe) */
-        key.flags = DB_DBT_MALLOC;
-    }
 
     MYDB_BEGIN_ALLOW_THREADS;
-    err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
+    err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
     MYDB_END_ALLOW_THREADS;
     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 	    && self->mydb->moduleFlags.getReturnsNone) {
@@ -3811,8 +3954,7 @@
         retval = NULL;
     }
     else {
-        retval = Py_BuildValue("y#", key.data, key.size);
-        free_dbt(&key);
+        retval = BuildValue_S(key.data, key.size);
     }
 
     return retval;
@@ -3825,18 +3967,26 @@
 
 
 static PyObject*
-DBEnv_close(DBEnvObject* self, PyObject* args)
+DBEnv_close_internal(DBEnvObject* self, int flags)
 {
-    int err, flags = 0;
+    PyObject *dummy;
+    int err;
 
-    if (!PyArg_ParseTuple(args, "|i:close", &flags))
-        return NULL;
     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);
+        }
+        while(self->children_dbs) {
+          dummy=DB_close_internal(self->children_dbs,0);
+          Py_XDECREF(dummy);
+        }
+
         MYDB_BEGIN_ALLOW_THREADS;
         err = self->db_env->close(self->db_env, flags);
         MYDB_END_ALLOW_THREADS;
         /* after calling DBEnv->close, regardless of error, this DBEnv
-         * may not be accessed again (BerkeleyDB docs). */
+         * may not be accessed again (Berkeley DB docs). */
         self->closed = 1;
         self->db_env = NULL;
         RETURN_IF_ERR();
@@ -3844,6 +3994,16 @@
     RETURN_NONE();
 }
 
+static PyObject*
+DBEnv_close(DBEnvObject* self, PyObject* args)
+{
+    int flags = 0;
+
+    if (!PyArg_ParseTuple(args, "|i:close", &flags))
+        return NULL;
+    return DBEnv_close_internal(self,flags);
+}
+
 
 static PyObject*
 DBEnv_open(DBEnvObject* self, PyObject* args)
@@ -3961,7 +4121,6 @@
 }
 #endif /* DBVER >= 41 */
 
-#if (DBVER >= 40)
 static PyObject*
 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
 {
@@ -3982,7 +4141,6 @@
     RETURN_IF_ERR();
     RETURN_NONE();
 }
-#endif /* DBVER >= 40 */
 
 static PyObject*
 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
@@ -4035,6 +4193,26 @@
 }
 
 
+#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();
+}
+#endif /* DBVER >= 47 */
+
+
 static PyObject*
 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
 {
@@ -4103,8 +4281,24 @@
     RETURN_NONE();
 }
 
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lg_max(DBEnvObject* self)
+{
+    int err;
+    u_int32_t lg_max;
 
-#if (DBVER >= 33)
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->get_lg_max(self->db_env, &lg_max);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(lg_max);
+}
+#endif
+
+
 static PyObject*
 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
 {
@@ -4120,7 +4314,6 @@
     RETURN_IF_ERR();
     RETURN_NONE();
 }
-#endif
 
 
 static PyObject*
@@ -4247,6 +4440,79 @@
 
 
 static PyObject*
+DBEnv_txn_recover(DBEnvObject* self)
+{
+    int flags = DB_FIRST;
+    int err, i;
+    PyObject *list, *tuple, *gid;
+    DBTxnObject *txn;
+#define PREPLIST_LEN 16
+    DB_PREPLIST preplist[PREPLIST_LEN];
+    long retp;
+
+    CHECK_ENV_NOT_CLOSED(self);
+
+    list=PyList_New(0);
+    if (!list)
+        return NULL;
+    while (!0) {
+        MYDB_BEGIN_ALLOW_THREADS
+        err=self->db_env->txn_recover(self->db_env,
+                        preplist, PREPLIST_LEN, &retp, flags);
+#undef PREPLIST_LEN
+        MYDB_END_ALLOW_THREADS
+        if (err) {
+            Py_DECREF(list);
+            RETURN_IF_ERR();
+        }
+        if (!retp) break;
+        flags=DB_NEXT;  /* Prepare for next loop pass */
+        for (i=0; i<retp; i++) {
+            gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
+                                DB_XIDDATASIZE);
+            if (!gid) {
+                Py_DECREF(list);
+                return NULL;
+            }
+            txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
+            if (!txn) {
+                Py_DECREF(list);
+                Py_DECREF(gid);
+                return NULL;
+            }
+            txn->flag_prepare=1;  /* Recover state */
+            tuple=PyTuple_New(2);
+            if (!tuple) {
+                Py_DECREF(list);
+                Py_DECREF(gid);
+                Py_DECREF(txn);
+                return NULL;
+            }
+            if (PyTuple_SetItem(tuple, 0, gid)) {
+                Py_DECREF(list);
+                Py_DECREF(gid);
+                Py_DECREF(txn);
+                Py_DECREF(tuple);
+                return NULL;
+            }
+            if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
+                Py_DECREF(list);
+                Py_DECREF(txn);
+                Py_DECREF(tuple); /* This delete the "gid" also */
+                return NULL;
+            }
+            if (PyList_Append(list, tuple)) {
+                Py_DECREF(list);
+                Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
+                return NULL;
+            }
+            Py_DECREF(tuple);
+        }
+    }
+    return list;
+}
+
+static PyObject*
 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
 {
     int flags = 0;
@@ -4262,7 +4528,7 @@
         return NULL;
     CHECK_ENV_NOT_CLOSED(self);
 
-    return (PyObject*)newDBTxnObject(self, txn, flags);
+    return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
 }
 
 
@@ -4276,11 +4542,7 @@
     CHECK_ENV_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
-#else
-    err = txn_checkpoint(self->db_env, kbyte, min, flags);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
     RETURN_NONE();
@@ -4330,14 +4592,10 @@
     CHECK_ENV_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
-#else
-    err = lock_detect(self->db_env, flags, atype, &aborted);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
-    return PyLong_FromLong(aborted);
+    return NUMBER_FromLong(aborted);
 }
 
 
@@ -4347,44 +4605,34 @@
     int flags=0;
     int locker, lock_mode;
     DBT obj;
-    PyObject *objobj, *retval;
-    Py_buffer *obj_buf_view = NULL;
+    PyObject* objobj;
 
     if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
         return NULL;
 
-    if (!make_dbt(objobj, &obj, &obj_buf_view))
+
+    if (!make_dbt(objobj, &obj))
         return NULL;
 
-    retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
-    free_buf_view(objobj, obj_buf_view);
-    return retval;
+    return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
 }
 
 
 static PyObject*
-DBEnv_lock_id(DBEnvObject* self, PyObject* args)
+DBEnv_lock_id(DBEnvObject* self)
 {
     int err;
     u_int32_t theID;
 
-    if (!PyArg_ParseTuple(args, ":lock_id"))
-        return NULL;
-
     CHECK_ENV_NOT_CLOSED(self);
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->lock_id(self->db_env, &theID);
-#else
-    err = lock_id(self->db_env, &theID);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
-    return PyLong_FromLong((long)theID);
+    return NUMBER_FromLong((long)theID);
 }
 
-#if (DBVER >= 40)
 static PyObject*
 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
 {
@@ -4401,7 +4649,6 @@
     RETURN_IF_ERR();
     RETURN_NONE();
 }
-#endif
 
 static PyObject*
 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
@@ -4414,11 +4661,7 @@
 
     CHECK_ENV_NOT_CLOSED(self);
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
-#else
-    err = lock_put(self->db_env, &dblockobj->lock);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
     RETURN_NONE();
@@ -4446,7 +4689,6 @@
 }
 #endif /* DBVER >= 4.4 */
 
-#if (DBVER >= 40)
 static PyObject*
 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
 {
@@ -4482,7 +4724,7 @@
     MAKE_ENTRY(lg_size);
     MAKE_ENTRY(record);
 #endif
-#if (DBVER <= 40)
+#if (DBVER < 41)
     MAKE_ENTRY(lg_max);
 #endif
     MAKE_ENTRY(w_mbytes);
@@ -4509,7 +4751,6 @@
     free(statp);
     return d;
 } /* DBEnv_log_stat */
-#endif /* DBVER >= 4.0 for log_stat method */
 
 
 static PyObject*
@@ -4525,15 +4766,7 @@
     CHECK_ENV_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->lock_stat(self->db_env, &sp, flags);
-#else
-#if (DBVER >= 33)
-    err = lock_stat(self->db_env, &sp);
-#else
-    err = lock_stat(self->db_env, &sp, NULL);
-#endif
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
@@ -4549,6 +4782,10 @@
 #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);
@@ -4561,6 +4798,10 @@
     MAKE_ENTRY(maxnobjects);
     MAKE_ENTRY(nrequests);
     MAKE_ENTRY(nreleases);
+#if (DBVER >= 44)
+    MAKE_ENTRY(nupgrade);
+    MAKE_ENTRY(ndowngrade);
+#endif
 #if (DBVER < 44)
     MAKE_ENTRY(nnowaits);       /* these were renamed in 4.4 */
     MAKE_ENTRY(nconflicts);
@@ -4569,6 +4810,26 @@
     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)
+    MAKE_ENTRY(objs_wait);
+    MAKE_ENTRY(objs_nowait);
+    MAKE_ENTRY(lockers_wait);
+    MAKE_ENTRY(lockers_nowait);
+#if (DBVER >= 47)
+    MAKE_ENTRY(lock_wait);
+    MAKE_ENTRY(lock_nowait);
+#else
+    MAKE_ENTRY(locks_wait);
+    MAKE_ENTRY(locks_nowait);
+#endif
+    MAKE_ENTRY(hash_len);
+#endif
     MAKE_ENTRY(regsize);
     MAKE_ENTRY(region_wait);
     MAKE_ENTRY(region_nowait);
@@ -4578,6 +4839,20 @@
     return d;
 }
 
+static PyObject*
+DBEnv_log_flush(DBEnvObject* self)
+{
+    int err;
+
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS
+    err = self->db_env->log_flush(self->db_env, NULL);
+    MYDB_END_ALLOW_THREADS
+
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
 
 static PyObject*
 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
@@ -4593,13 +4868,7 @@
 
     CHECK_ENV_NOT_CLOSED(self);
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->log_archive(self->db_env, &log_list, flags);
-#elif (DBVER == 33)
-    err = log_archive(self->db_env, &log_list, flags);
-#else
-    err = log_archive(self->db_env, &log_list, flags, NULL);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
@@ -4613,13 +4882,18 @@
     if (log_list) {
         char **log_list_start;
         for (log_list_start = log_list; *log_list != NULL; ++log_list) {
-            item = PyUnicode_FromString (*log_list);
+            item = PyBytes_FromString (*log_list);
             if (item == NULL) {
                 Py_DECREF(list);
                 list = NULL;
                 break;
             }
-            PyList_Append(list, item);
+            if (PyList_Append(list, item)) {
+                Py_DECREF(list);
+                list = NULL;
+                Py_DECREF(item);
+                break;
+            }
             Py_DECREF(item);
         }
         free(log_list_start);
@@ -4641,13 +4915,7 @@
     CHECK_ENV_NOT_CLOSED(self);
 
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->db_env->txn_stat(self->db_env, &sp, flags);
-#elif (DBVER == 33)
-    err = txn_stat(self->db_env, &sp);
-#else
-    err = txn_stat(self->db_env, &sp, NULL);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
 
@@ -4658,21 +4926,29 @@
         return NULL;
     }
 
-#define MAKE_ENTRY(name)  _addIntToDict(d, #name, sp->st_##name)
-#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
+#define MAKE_ENTRY(name)        _addIntToDict(d, #name, sp->st_##name)
+#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
+#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
 
+    MAKE_DB_LSN_ENTRY(last_ckp);
     MAKE_TIME_T_ENTRY(time_ckp);
     MAKE_ENTRY(last_txnid);
     MAKE_ENTRY(maxtxns);
     MAKE_ENTRY(nactive);
     MAKE_ENTRY(maxnactive);
+#if (DBVER >= 45)
+    MAKE_ENTRY(nsnapshot);
+    MAKE_ENTRY(maxnsnapshot);
+#endif
     MAKE_ENTRY(nbegins);
     MAKE_ENTRY(naborts);
     MAKE_ENTRY(ncommits);
+    MAKE_ENTRY(nrestores);
     MAKE_ENTRY(regsize);
     MAKE_ENTRY(region_wait);
     MAKE_ENTRY(region_nowait);
 
+#undef MAKE_DB_LSN_ENTRY
 #undef MAKE_ENTRY
 #undef MAKE_TIME_T_ENTRY
     free(sp);
@@ -4696,14 +4972,881 @@
         ++oldValue;
     self->moduleFlags.getReturnsNone = (flags >= 1);
     self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
-    return PyLong_FromLong(oldValue);
+    return NUMBER_FromLong(oldValue);
 }
 
+static PyObject*
+DBEnv_get_private(DBEnvObject* self)
+{
+    /* We can give out the private field even if dbenv is closed */
+    Py_INCREF(self->private_obj);
+    return self->private_obj;
+}
+
+static PyObject*
+DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
+{
+    /* We can set the private field even if dbenv is closed */
+    Py_DECREF(self->private_obj);
+    Py_INCREF(private_obj);
+    self->private_obj = private_obj;
+    RETURN_NONE();
+}
+
+
+static PyObject*
+DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+    int err;
+    char *host;
+    long cl_timeout=0, sv_timeout=0;
+
+    static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
+                                     &host, &cl_timeout, &sv_timeout))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
+            sv_timeout, 0);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int which, onoff;
+
+    if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->set_verbose(self->db_env, which, onoff);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int which;
+    int verbose;
+
+    if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->get_verbose(self->db_env, which, &verbose);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return PyBool_FromLong(verbose);
+}
+#endif
+
+#if (DBVER >= 45)
+static void
+_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
+{
+    DBEnvObject *dbenv;
+    PyObject* callback;
+    PyObject* args;
+    PyObject* result = NULL;
+
+    MYDB_BEGIN_BLOCK_THREADS;
+    dbenv = (DBEnvObject *)db_env->app_private;
+    callback = dbenv->event_notifyCallback;
+    if (callback) {
+        if (event == DB_EVENT_REP_NEWMASTER) {
+            args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
+        } else {
+            args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
+        }
+        if (args) {
+            result = PyEval_CallObject(callback, args);
+        }
+        if ((!args) || (!result)) {
+            PyErr_Print();
+        }
+        Py_XDECREF(args);
+        Py_XDECREF(result);
+    }
+    MYDB_END_BLOCK_THREADS;
+}
+#endif
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
+{
+    int err;
+
+    CHECK_ENV_NOT_CLOSED(self);
+
+    if (!PyCallable_Check(notifyFunc)) {
+	    makeTypeError("Callable", notifyFunc);
+	    return NULL;
+    }
+
+    Py_XDECREF(self->event_notifyCallback);
+    Py_INCREF(notifyFunc);
+    self->event_notifyCallback = notifyFunc;
+
+    /* This is to workaround a problem with un-initialized threads (see
+       comment in DB_associate) */
+#ifdef WITH_THREAD
+    PyEval_InitThreads();
+#endif
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
+    MYDB_END_ALLOW_THREADS;
+
+    if (err) {
+	    Py_DECREF(notifyFunc);
+	    self->event_notifyCallback = NULL;
+    }
+
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* REPLICATION METHODS: Base Replication */
+
+
+static PyObject*
+DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    PyObject *control_py, *rec_py;
+    DBT control, rec;
+    int envid;
+#if (DBVER >= 42)
+    DB_LSN lsn;
+#endif
+
+    if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
+                &rec_py, &envid))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+
+    if (!make_dbt(control_py, &control))
+        return NULL;
+    if (!make_dbt(rec_py, &rec))
+        return NULL;
+
+    MYDB_BEGIN_ALLOW_THREADS;
+#if (DBVER >= 46)
+    err = self->db_env->rep_process_message(self->db_env, &control, &rec,
+            envid, &lsn);
+#else
+#if (DBVER >= 42)
+    err = self->db_env->rep_process_message(self->db_env, &control, &rec,
+            &envid, &lsn);
+#else
+    err = self->db_env->rep_process_message(self->db_env, &control, &rec,
+            &envid);
+#endif
+#endif
+    MYDB_END_ALLOW_THREADS;
+    switch (err) {
+        case DB_REP_NEWMASTER :
+          return Py_BuildValue("(iO)", envid, Py_None);
+          break;
+
+        case DB_REP_DUPMASTER :
+        case DB_REP_HOLDELECTION :
+#if (DBVER >= 44)
+        case DB_REP_IGNORE :
+        case DB_REP_JOIN_FAILURE :
+#endif
+            return Py_BuildValue("(iO)", err, Py_None);
+            break;
+        case DB_REP_NEWSITE :
+            {
+                PyObject *tmp, *r;
+
+                if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
+                    return NULL;
+                }
+
+                r = Py_BuildValue("(iO)", err, tmp);
+                Py_DECREF(tmp);
+                return r;
+                break;
+            }
+#if (DBVER >= 42)
+        case DB_REP_NOTPERM :
+        case DB_REP_ISPERM :
+            return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
+            break;
+#endif
+    }
+    RETURN_IF_ERR();
+    return Py_BuildValue("(OO)", Py_None, Py_None);
+}
+
+static int
+_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
+        const DB_LSN *lsn, int envid, u_int32_t flags)
+{
+    DBEnvObject *dbenv;
+    PyObject* rep_transport;
+    PyObject* args;
+    PyObject *a, *b;
+    PyObject* result = NULL;
+    int ret=0;
+
+    MYDB_BEGIN_BLOCK_THREADS;
+    dbenv = (DBEnvObject *)db_env->app_private;
+    rep_transport = dbenv->rep_transport;
+
+    /*
+    ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
+    */
+    a = PyBytes_FromStringAndSize(control->data, control->size);
+    b = PyBytes_FromStringAndSize(rec->data, rec->size);
+
+    args = Py_BuildValue(
+#if (PY_VERSION_HEX >= 0x02040000)
+            "(OOO(ll)iI)",
+#else
+            "(OOO(ll)ii)",
+#endif
+            dbenv,
+            a, b,
+            lsn->file, lsn->offset, envid, flags);
+    if (args) {
+        result = PyEval_CallObject(rep_transport, args);
+    }
+
+    if ((!args) || (!result)) {
+        PyErr_Print();
+        ret = -1;
+    }
+    Py_XDECREF(a);
+    Py_XDECREF(b);
+    Py_XDECREF(args);
+    Py_XDECREF(result);
+    MYDB_END_BLOCK_THREADS;
+    return ret;
+}
+
+#if (DBVER <= 41)
+static int
+_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
+        int envid, u_int32_t flags)
+{
+    DB_LSN lsn;
+
+    lsn.file = -1;  /* Dummy values */
+    lsn.offset = -1;
+    return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
+            flags);
+}
+#endif
+
+static PyObject*
+DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int envid;
+    PyObject *rep_transport;
+
+    if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+    if (!PyCallable_Check(rep_transport)) {
+        makeTypeError("Callable", rep_transport);
+        return NULL;
+    }
+
+    MYDB_BEGIN_ALLOW_THREADS;
+#if (DBVER >=45)
+    err = self->db_env->rep_set_transport(self->db_env, envid,
+            &_DBEnv_rep_transportCallback);
+#else
+#if (DBVER >= 42)
+    err = self->db_env->set_rep_transport(self->db_env, envid,
+            &_DBEnv_rep_transportCallback);
+#else
+    err = self->db_env->set_rep_transport(self->db_env, envid,
+            &_DBEnv_rep_transportCallbackOLD);
+#endif
+#endif
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+
+    Py_DECREF(self->rep_transport);
+    Py_INCREF(rep_transport);
+    self->rep_transport = rep_transport;
+    RETURN_NONE();
+}
+
+#if (DBVER >= 47)
+static PyObject*
+DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    unsigned int minimum, maximum;
+
+    if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_request(DBEnvObject* self)
+{
+    int err;
+    u_int32_t minimum, maximum;
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+#if (PY_VERSION_HEX >= 0x02040000)
+    return Py_BuildValue("II", minimum, maximum);
+#else
+    return Py_BuildValue("ii", minimum, maximum);
+#endif
+}
+#endif
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int limit;
+
+    if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_set_limit(self->db_env, 0, limit);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_limit(DBEnvObject* self)
+{
+    int err;
+    u_int32_t gbytes, bytes;
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(bytes);
+}
+#endif
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int which;
+    int onoff;
+
+    if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
+        return NULL;
+    CHECK_ENV_NOT_CLOSED(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_set_config(self->db_env, which, onoff);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int which;
+    int onoff;
+
+    if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_get_config(self->db_env, which, &onoff);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return PyBool_FromLong(onoff);
+}
+#endif
+
+#if (DBVER >= 46)
+static PyObject*
+DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    u_int32_t nsites, nvotes;
+
+    if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+#endif
+
+static PyObject*
+DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+    int err;
+    PyObject *cdata_py = Py_None;
+    DBT cdata;
+    int flags;
+    static char* kwnames[] = {"flags","cdata", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                "i|O:rep_start", kwnames, &flags, &cdata_py))
+    {
+	    return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+
+    if (!make_dbt(cdata_py, &cdata))
+        return NULL;
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
+            flags);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_rep_sync(DBEnvObject* self)
+{
+    int err;
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_sync(self->db_env, 0);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+#endif
+
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int nsites;
+
+    if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_set_nsites(self->db_env, nsites);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_nsites(DBEnvObject* self)
+{
+    int err;
+#if (DBVER >= 47)
+    u_int32_t nsites;
+#else
+    int nsites;
+#endif
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_get_nsites(self->db_env, &nsites);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(nsites);
+}
+
+static PyObject*
+DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int priority;
+
+    if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_set_priority(self->db_env, priority);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_priority(DBEnvObject* self)
+{
+    int err;
+#if (DBVER >= 47)
+    u_int32_t priority;
+#else
+    int priority;
+#endif
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_get_priority(self->db_env, &priority);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(priority);
+}
+
+static PyObject*
+DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int which, timeout;
+
+    if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int which;
+    u_int32_t timeout;
+
+    if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(timeout);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+/* REPLICATION METHODS: Replication Manager */
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
+        kwargs)
+{
+    int err;
+    int nthreads, flags;
+    static char* kwnames[] = {"nthreads","flags", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                "ii:repmgr_start", kwnames, &nthreads, &flags))
+    {
+	    return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
+        kwargs)
+{
+    int err;
+    char *host;
+    int port;
+    int flags = 0;
+    static char* kwnames[] = {"host", "port", "flags", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
+    {
+	    return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
+        kwargs)
+{
+    int err;
+    char *host;
+    int port;
+    int flags = 0;
+    int eidp;
+    static char* kwnames[] = {"host", "port", "flags", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+                "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
+    {
+	    return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(eidp);
+}
+
+static PyObject*
+DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
+{
+    int err;
+    int ack_policy;
+
+    if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
+    {
+	    return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
+{
+    int err;
+    int ack_policy;
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    return NUMBER_FromLong(ack_policy);
+}
+
+static PyObject*
+DBEnv_repmgr_site_list(DBEnvObject* self)
+{
+    int err;
+    unsigned int countp;
+    DB_REPMGR_SITE *listp;
+    PyObject *stats, *key, *tuple;
+
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+
+    stats=PyDict_New();
+    if (stats == NULL) {
+        free(listp);
+        return NULL;
+    }
+
+    for(;countp--;) {
+        key=NUMBER_FromLong(listp[countp].eid);
+        if(!key) {
+            Py_DECREF(stats);
+            free(listp);
+            return NULL;
+        }
+#if (PY_VERSION_HEX >= 0x02040000)
+        tuple=Py_BuildValue("(sII)", listp[countp].host,
+                listp[countp].port, listp[countp].status);
+#else
+        tuple=Py_BuildValue("(sii)", listp[countp].host,
+                listp[countp].port, listp[countp].status);
+#endif
+        if(!tuple) {
+            Py_DECREF(key);
+            Py_DECREF(stats);
+            free(listp);
+            return NULL;
+        }
+        if(PyDict_SetItem(stats, key, tuple)) {
+            Py_DECREF(key);
+            Py_DECREF(tuple);
+            Py_DECREF(stats);
+            free(listp);
+            return NULL;
+        }
+    }
+    free(listp);
+    return stats;
+}
+#endif
+
+#if (DBVER >= 46)
+static PyObject*
+DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+    int err;
+    int flags=0;
+    static char* kwnames[] = { "flags", NULL };
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
+                kwnames, &flags))
+    {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_stat_print(self->db_env, flags);
+    MYDB_END_ALLOW_THREADS;
+    RETURN_IF_ERR();
+    RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+    int err;
+    int flags=0;
+    DB_REPMGR_STAT *statp;
+    PyObject *stats;
+    static char* kwnames[] = { "flags", NULL };
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
+                kwnames, &flags))
+    {
+        return NULL;
+    }
+    CHECK_ENV_NOT_CLOSED(self);
+    MYDB_BEGIN_ALLOW_THREADS;
+    err = self->db_env->repmgr_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)
+
+    MAKE_ENTRY(perm_failed);
+    MAKE_ENTRY(msgs_queued);
+    MAKE_ENTRY(msgs_dropped);
+    MAKE_ENTRY(connection_drop);
+    MAKE_ENTRY(connect_fail);
+
+#undef MAKE_ENTRY
+
+    free(statp);
+    return stats;
+}
+#endif
+
 
 /* --------------------------------------------------------------------- */
 /* DBTxn methods */
 
 
+static void _close_transaction_cursors(DBTxnObject* txn)
+{
+    PyObject *dummy;
+
+    while(txn->children_cursors) {
+        PyErr_Warn(PyExc_RuntimeWarning,
+            "Must close cursors before resolving a transaction.");
+        dummy=DBC_close_internal(txn->children_cursors);
+        Py_XDECREF(dummy);
+    }
+}
+
+static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
+{
+    DBObject *db;
+#if (DBVER >= 43)
+    DBSequenceObject *dbs;
+#endif
+
+    while (txn->children_dbs) {
+        db=txn->children_dbs;
+        EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
+        if (txn->parent_txn) {
+            INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
+            db->txn=txn->parent_txn;
+        } else {
+            /* The db is already linked to its environment,
+            ** so nothing to do.
+            */
+            db->txn=NULL; 
+        }
+    }
+
+#if (DBVER >= 43)
+    while (txn->children_sequences) {
+        dbs=txn->children_sequences;
+        EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
+        if (txn->parent_txn) {
+            INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
+            dbs->txn=txn->parent_txn;
+        } else {
+            /* The sequence is already linked to its
+            ** parent db. Nothing to do.
+            */
+            dbs->txn=NULL;
+        }
+    }
+#endif
+}
+
+
 static PyObject*
 DBTxn_commit(DBTxnObject* self, PyObject* args)
 {
@@ -4713,22 +5856,30 @@
     if (!PyArg_ParseTuple(args, "|i:commit", &flags))
         return NULL;
 
+    _close_transaction_cursors(self);
+
     if (!self->txn) {
         PyObject *t =  Py_BuildValue("(is)", 0, "DBTxn must not be used "
-                                     "after txn_commit or txn_abort");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+                                     "after txn_commit, txn_abort "
+                                     "or txn_discard");
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         return NULL;
     }
+    self->flag_prepare=0;
     txn = self->txn;
     self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
+
+    EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = txn->commit(txn, flags);
-#else
-    err = txn_commit(txn, flags);
-#endif
     MYDB_END_ALLOW_THREADS;
+
+    _promote_transaction_dbs_and_sequences(self);
+
     RETURN_IF_ERR();
     RETURN_NONE();
 }
@@ -4736,12 +5887,11 @@
 static PyObject*
 DBTxn_prepare(DBTxnObject* self, PyObject* args)
 {
-#if (DBVER >= 33)
     int err;
     char* gid=NULL;
     int   gid_size=0;
 
-    if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
+    if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
         return NULL;
 
     if (gid_size != DB_XIDDATASIZE) {
@@ -4752,95 +5902,113 @@
 
     if (!self->txn) {
         PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
-                                    "after txn_commit or txn_abort");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+                                    "after txn_commit, txn_abort "
+                                    "or txn_discard");
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         return NULL;
     }
+    self->flag_prepare=1;  /* Prepare state */
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     err = self->txn->prepare(self->txn, (u_int8_t*)gid);
-#else
-    err = txn_prepare(self->txn, (u_int8_t*)gid);
-#endif
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
     RETURN_NONE();
-#else
-    int err;
-
-    if (!PyArg_ParseTuple(args, ":prepare"))
-        return NULL;
-
-    if (!self->txn) {
-        PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
-                                    "after txn_commit or txn_abort");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
-        return NULL;
-    }
-    MYDB_BEGIN_ALLOW_THREADS;
-    err = txn_prepare(self->txn);
-    MYDB_END_ALLOW_THREADS;
-    RETURN_IF_ERR();
-    RETURN_NONE();
-#endif
 }
 
 
 static PyObject*
-DBTxn_abort(DBTxnObject* self, PyObject* args)
+DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
 {
-    int err;
+    PyObject *dummy;
+    int err=0;
     DB_TXN *txn;
 
-    if (!PyArg_ParseTuple(args, ":abort"))
-        return NULL;
-
     if (!self->txn) {
         PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
-                                    "after txn_commit or txn_abort");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+                                    "after txn_commit, txn_abort "
+                                    "or txn_discard");
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         return NULL;
     }
     txn = self->txn;
     self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
-    MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
-    err = txn->abort(txn);
-#else
-    err = txn_abort(txn);
+
+    _close_transaction_cursors(self);
+#if (DBVER >= 43)
+    while (self->children_sequences) {
+        dummy=DBSequence_close_internal(self->children_sequences,0,0);
+        Py_XDECREF(dummy);
+    }
 #endif
+    while (self->children_dbs) {
+        dummy=DB_close_internal(self->children_dbs,0);
+        Py_XDECREF(dummy);
+    }
+
+    EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+
+    MYDB_BEGIN_ALLOW_THREADS;
+    if (discard) {
+        assert(!self->flag_prepare);
+        err = txn->discard(txn,0);
+    } else {
+        /*
+        ** If the transaction is in the "prepare" or "recover" state,
+        ** we better do not implicitly abort it.
+        */
+        if (!self->flag_prepare) {
+            err = txn->abort(txn);
+        }
+    }
     MYDB_END_ALLOW_THREADS;
     RETURN_IF_ERR();
     RETURN_NONE();
 }
 
+static PyObject*
+DBTxn_abort(DBTxnObject* self)
+{
+    self->flag_prepare=0;
+    _close_transaction_cursors(self);
+
+    return DBTxn_abort_discard_internal(self,0);
+}
 
 static PyObject*
-DBTxn_id(DBTxnObject* self, PyObject* args)
+DBTxn_discard(DBTxnObject* self)
+{
+    self->flag_prepare=0;
+    _close_transaction_cursors(self);
+
+    return DBTxn_abort_discard_internal(self,1);
+}
+
+
+static PyObject*
+DBTxn_id(DBTxnObject* self)
 {
     int id;
 
-    if (!PyArg_ParseTuple(args, ":id"))
-        return NULL;
-
     if (!self->txn) {
         PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
-                                    "after txn_commit or txn_abort");
-        PyErr_SetObject(DBError, t);
-        Py_DECREF(t);
+                                    "after txn_commit, txn_abort "
+                                    "or txn_discard");
+        if (t) {
+            PyErr_SetObject(DBError, t);
+            Py_DECREF(t);
+        }
         return NULL;
     }
     MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
     id = self->txn->id(self->txn);
-#else
-    id = txn_id(self->txn);
-#endif
     MYDB_END_ALLOW_THREADS;
-    return PyLong_FromLong(id);
+    return NUMBER_FromLong(id);
 }
 
 #if (DBVER >= 43)
@@ -4849,24 +6017,41 @@
 
 
 static PyObject*
-DBSequence_close(DBSequenceObject* self, PyObject* args)
+DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
 {
-    int err, flags=0;
-    if (!PyArg_ParseTuple(args,"|i:close", &flags))
-        return NULL;
-    CHECK_SEQUENCE_NOT_CLOSED(self)
+    int err=0;
 
-    MYDB_BEGIN_ALLOW_THREADS
-    err = self->sequence->close(self->sequence, flags);
-    self->sequence = NULL;
-    MYDB_END_ALLOW_THREADS
+    if (self->sequence!=NULL) {
+        EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+        if (self->txn) {
+            EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
+            self->txn=NULL;
+        }
 
-    RETURN_IF_ERR();
+        if (!do_not_close) {
+            MYDB_BEGIN_ALLOW_THREADS
+            err = self->sequence->close(self->sequence, flags);
+            MYDB_END_ALLOW_THREADS
+        }
+        self->sequence = NULL;
+
+        RETURN_IF_ERR();
+    }
 
     RETURN_NONE();
 }
 
 static PyObject*
+DBSequence_close(DBSequenceObject* self, PyObject* args)
+{
+    int flags=0;
+    if (!PyArg_ParseTuple(args,"|i:close", &flags))
+        return NULL;
+
+    return DBSequence_close_internal(self,flags,0);
+}
+
+static PyObject*
 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
 {
     int err, flags = 0;
@@ -4888,25 +6073,23 @@
 
     RETURN_IF_ERR();
     return PyLong_FromLongLong(value);
-
 }
 
 static PyObject*
-DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
+DBSequence_get_dbp(DBSequenceObject* self)
 {
-    if (!PyArg_ParseTuple(args,":get_dbp"))
-        return NULL;
     CHECK_SEQUENCE_NOT_CLOSED(self)
     Py_INCREF(self->mydb);
     return (PyObject* )self->mydb;
 }
 
 static PyObject*
-DBSequence_get_key(DBSequenceObject* self, PyObject* args)
+DBSequence_get_key(DBSequenceObject* self)
 {
     int err;
     DBT key;
     PyObject *retval = NULL;
+
     key.flags = DB_DBT_MALLOC;
     CHECK_SEQUENCE_NOT_CLOSED(self)
     MYDB_BEGIN_ALLOW_THREADS
@@ -4914,9 +6097,9 @@
     MYDB_END_ALLOW_THREADS
 
     if (!err)
-        retval = PyBytes_FromStringAndSize(key.data, key.size);
+        retval = Build_PyString(key.data, key.size);
 
-    free_dbt(&key);
+    FREE_DBT(key);
     RETURN_IF_ERR();
 
     return retval;
@@ -4926,13 +6109,15 @@
 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
 {
     int err;
-    db_seq_t value;
+    PY_LONG_LONG value;
+    db_seq_t value2;
     if (!PyArg_ParseTuple(args,"L:init_value", &value))
         return NULL;
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
+    value2=value; /* If truncation, compiler should show a warning */
     MYDB_BEGIN_ALLOW_THREADS
-    err = self->sequence->initial_value(self->sequence, value);
+    err = self->sequence->initial_value(self->sequence, value2);
     MYDB_END_ALLOW_THREADS
 
     RETURN_IF_ERR();
@@ -4944,8 +6129,7 @@
 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
 {
     int err, flags = 0;
-    PyObject *keyobj;
-    Py_buffer *key_buf_view = NULL;
+    PyObject* keyobj;
     PyObject *txnobj = NULL;
     DB_TXN *txn = NULL;
     DBT key;
@@ -4957,22 +6141,28 @@
     if (!checkTxnObj(txnobj, &txn))
         return NULL;
 
-    if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+    if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
         return NULL;
 
     MYDB_BEGIN_ALLOW_THREADS
     err = self->sequence->open(self->sequence, txn, &key, flags);
     MYDB_END_ALLOW_THREADS
 
-    FREE_DBT_VIEW(key, keyobj, key_buf_view);
+    CLEAR_DBT(key);
     RETURN_IF_ERR();
 
+    if (txn) {
+        INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
+        self->txn=(DBTxnObject *)txnobj;
+    }
+
     RETURN_NONE();
 }
 
 static PyObject*
 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
 {
+    PyObject *dummy;
     int err, flags = 0;
     PyObject *txnobj = NULL;
     DB_TXN *txn = NULL;
@@ -4990,6 +6180,9 @@
     err = self->sequence->remove(self->sequence, txn, flags);
     MYDB_END_ALLOW_THREADS
 
+    dummy=DBSequence_close_internal(self,flags,1);
+    Py_XDECREF(dummy);
+
     RETURN_IF_ERR();
     RETURN_NONE();
 }
@@ -5011,11 +6204,10 @@
 }
 
 static PyObject*
-DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
+DBSequence_get_cachesize(DBSequenceObject* self)
 {
     int err, size;
-    if (!PyArg_ParseTuple(args,":get_cachesize"))
-        return NULL;
+
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
     MYDB_BEGIN_ALLOW_THREADS
@@ -5023,7 +6215,7 @@
     MYDB_END_ALLOW_THREADS
 
     RETURN_IF_ERR();
-    return PyLong_FromLong(size);
+    return NUMBER_FromLong(size);
 }
 
 static PyObject*
@@ -5040,16 +6232,14 @@
 
     RETURN_IF_ERR();
     RETURN_NONE();
-
 }
 
 static PyObject*
-DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
+DBSequence_get_flags(DBSequenceObject* self)
 {
     unsigned int flags;
     int err;
-    if (!PyArg_ParseTuple(args,":get_flags"))
-        return NULL;
+
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
     MYDB_BEGIN_ALLOW_THREADS
@@ -5057,20 +6247,23 @@
     MYDB_END_ALLOW_THREADS
 
     RETURN_IF_ERR();
-    return PyLong_FromLong((int)flags);
+    return NUMBER_FromLong((int)flags);
 }
 
 static PyObject*
 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
 {
     int err;
-    db_seq_t min, max;
+    PY_LONG_LONG min, max;
+    db_seq_t min2, max2;
     if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
         return NULL;
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
+    min2=min;  /* If truncation, compiler should show a warning */
+    max2=max;
     MYDB_BEGIN_ALLOW_THREADS
-    err = self->sequence->set_range(self->sequence, min, max);
+    err = self->sequence->set_range(self->sequence, min2, max2);
     MYDB_END_ALLOW_THREADS
 
     RETURN_IF_ERR();
@@ -5078,19 +6271,21 @@
 }
 
 static PyObject*
-DBSequence_get_range(DBSequenceObject* self, PyObject* args)
+DBSequence_get_range(DBSequenceObject* self)
 {
     int err;
-    db_seq_t min, max;
-    if (!PyArg_ParseTuple(args,":get_range"))
-        return NULL;
+    PY_LONG_LONG min, max;
+    db_seq_t min2, max2;
+
     CHECK_SEQUENCE_NOT_CLOSED(self)
 
     MYDB_BEGIN_ALLOW_THREADS
-    err = self->sequence->get_range(self->sequence, &min, &max);
+    err = self->sequence->get_range(self->sequence, &min2, &max2);
     MYDB_END_ALLOW_THREADS
 
     RETURN_IF_ERR();
+    min=min2;  /* If truncation, compiler should show a warning */
+    max=max2;
     return Py_BuildValue("(LL)", min, max);
 }
 
@@ -5142,27 +6337,23 @@
 /* Method definition tables and type objects */
 
 static PyMethodDef DB_methods[] = {
-    {"append",          (PyCFunction)DB_append,         METH_VARARGS},
-#if (DBVER >= 33)
+    {"append",          (PyCFunction)DB_append,         METH_VARARGS|METH_KEYWORDS},
     {"associate",       (PyCFunction)DB_associate,      METH_VARARGS|METH_KEYWORDS},
-#endif
     {"close",           (PyCFunction)DB_close,          METH_VARARGS},
     {"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_VARARGS},
+    {"fd",              (PyCFunction)DB_fd,             METH_NOARGS},
     {"get",             (PyCFunction)DB_get,            METH_VARARGS|METH_KEYWORDS},
-#if (DBVER >= 33)
     {"pget",            (PyCFunction)DB_pget,           METH_VARARGS|METH_KEYWORDS},
-#endif
     {"get_both",        (PyCFunction)DB_get_both,       METH_VARARGS|METH_KEYWORDS},
-    {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
+    {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
     {"get_size",        (PyCFunction)DB_get_size,       METH_VARARGS|METH_KEYWORDS},
-    {"get_type",        (PyCFunction)DB_get_type,       METH_VARARGS},
+    {"get_type",        (PyCFunction)DB_get_type,       METH_NOARGS},
     {"join",            (PyCFunction)DB_join,           METH_VARARGS},
     {"key_range",       (PyCFunction)DB_key_range,      METH_VARARGS|METH_KEYWORDS},
-    {"has_key",         (PyCFunction)DB_has_key,        METH_VARARGS},
+    {"has_key",         (PyCFunction)DB_has_key,        METH_VARARGS|METH_KEYWORDS},
     {"items",           (PyCFunction)DB_items,          METH_VARARGS},
     {"keys",            (PyCFunction)DB_keys,           METH_VARARGS},
     {"open",            (PyCFunction)DB_open,           METH_VARARGS|METH_KEYWORDS},
@@ -5170,9 +6361,7 @@
     {"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 >= 33)
-    {"set_bt_compare",  (PyCFunction)DB_set_bt_compare, METH_VARARGS},
-#endif
+    {"set_bt_compare",  (PyCFunction)DB_set_bt_compare, METH_O},
     {"set_cachesize",   (PyCFunction)DB_set_cachesize,  METH_VARARGS},
 #if (DBVER >= 41)
     {"set_encrypt",     (PyCFunction)DB_set_encrypt,    METH_VARARGS|METH_KEYWORDS},
@@ -5186,13 +6375,13 @@
     {"set_re_len",      (PyCFunction)DB_set_re_len,     METH_VARARGS},
     {"set_re_pad",      (PyCFunction)DB_set_re_pad,     METH_VARARGS},
     {"set_re_source",   (PyCFunction)DB_set_re_source,  METH_VARARGS},
-    {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
+    {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
+    {"set_private",     (PyCFunction)DB_set_private,    METH_O},
+    {"get_private",     (PyCFunction)DB_get_private,    METH_NOARGS},
     {"stat",            (PyCFunction)DB_stat,           METH_VARARGS|METH_KEYWORDS},
     {"sync",            (PyCFunction)DB_sync,           METH_VARARGS},
-#if (DBVER >= 33)
     {"truncate",        (PyCFunction)DB_truncate,       METH_VARARGS|METH_KEYWORDS},
-#endif
-    {"type",            (PyCFunction)DB_get_type,       METH_VARARGS},
+    {"type",            (PyCFunction)DB_get_type,       METH_NOARGS},
     {"upgrade",         (PyCFunction)DB_upgrade,        METH_VARARGS},
     {"values",          (PyCFunction)DB_values,         METH_VARARGS},
     {"verify",          (PyCFunction)DB_verify,         METH_VARARGS|METH_KEYWORDS},
@@ -5209,17 +6398,15 @@
 
 
 static PyMethodDef DBCursor_methods[] = {
-    {"close",           (PyCFunction)DBC_close,         METH_VARARGS},
+    {"close",           (PyCFunction)DBC_close,         METH_NOARGS},
     {"count",           (PyCFunction)DBC_count,         METH_VARARGS},
     {"current",         (PyCFunction)DBC_current,       METH_VARARGS|METH_KEYWORDS},
     {"delete",          (PyCFunction)DBC_delete,        METH_VARARGS},
     {"dup",             (PyCFunction)DBC_dup,           METH_VARARGS},
     {"first",           (PyCFunction)DBC_first,         METH_VARARGS|METH_KEYWORDS},
     {"get",             (PyCFunction)DBC_get,           METH_VARARGS|METH_KEYWORDS},
-#if (DBVER >= 33)
     {"pget",            (PyCFunction)DBC_pget,          METH_VARARGS|METH_KEYWORDS},
-#endif
-    {"get_recno",       (PyCFunction)DBC_get_recno,     METH_VARARGS},
+    {"get_recno",       (PyCFunction)DBC_get_recno,     METH_NOARGS},
     {"last",            (PyCFunction)DBC_last,          METH_VARARGS|METH_KEYWORDS},
     {"next",            (PyCFunction)DBC_next,          METH_VARARGS|METH_KEYWORDS},
     {"prev",            (PyCFunction)DBC_prev,          METH_VARARGS|METH_KEYWORDS},
@@ -5227,7 +6414,7 @@
     {"set",             (PyCFunction)DBC_set,           METH_VARARGS|METH_KEYWORDS},
     {"set_range",       (PyCFunction)DBC_set_range,     METH_VARARGS|METH_KEYWORDS},
     {"get_both",        (PyCFunction)DBC_get_both,      METH_VARARGS},
-    {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
+    {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
     {"set_both",        (PyCFunction)DBC_set_both,      METH_VARARGS},
     {"set_recno",       (PyCFunction)DBC_set_recno,     METH_VARARGS|METH_KEYWORDS},
     {"consume",         (PyCFunction)DBC_consume,       METH_VARARGS|METH_KEYWORDS},
@@ -5248,19 +6435,21 @@
     {"dbrename",        (PyCFunction)DBEnv_dbrename,         METH_VARARGS|METH_KEYWORDS},
     {"set_encrypt",     (PyCFunction)DBEnv_set_encrypt,      METH_VARARGS|METH_KEYWORDS},
 #endif
-#if (DBVER >= 40)
     {"set_timeout",     (PyCFunction)DBEnv_set_timeout,      METH_VARARGS|METH_KEYWORDS},
-#endif
     {"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},
+#if (DBVER >= 47)
+    {"log_set_config",  (PyCFunction)DBEnv_log_set_config,   METH_VARARGS},
+#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},
-#if (DBVER >= 33)
-    {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
+#if (DBVER >= 42)
+    {"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 < 45)
     {"set_lk_max",      (PyCFunction)DBEnv_set_lk_max,       METH_VARARGS},
@@ -5277,20 +6466,78 @@
     {"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_VARARGS},
-#if (DBVER >= 40)
+    {"lock_id",         (PyCFunction)DBEnv_lock_id,          METH_NOARGS},
     {"lock_id_free",    (PyCFunction)DBEnv_lock_id_free,     METH_VARARGS},
-#endif
     {"lock_put",        (PyCFunction)DBEnv_lock_put,         METH_VARARGS},
     {"lock_stat",       (PyCFunction)DBEnv_lock_stat,        METH_VARARGS},
     {"log_archive",     (PyCFunction)DBEnv_log_archive,      METH_VARARGS},
-#if (DBVER >= 40)
+    {"log_flush",       (PyCFunction)DBEnv_log_flush,        METH_NOARGS},
     {"log_stat",        (PyCFunction)DBEnv_log_stat,         METH_VARARGS},
-#endif
 #if (DBVER >= 44)
     {"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},
+    {"set_rpc_server",  (PyCFunction)DBEnv_set_rpc_server,
+        METH_VARARGS||METH_KEYWORDS},
+    {"set_verbose",     (PyCFunction)DBEnv_set_verbose,       METH_VARARGS},
+#if (DBVER >= 42)
+    {"get_verbose",     (PyCFunction)DBEnv_get_verbose,       METH_VARARGS},
+#endif
+    {"set_private",     (PyCFunction)DBEnv_set_private,       METH_O},
+    {"get_private",     (PyCFunction)DBEnv_get_private,       METH_NOARGS},
+    {"rep_start",       (PyCFunction)DBEnv_rep_start,
+        METH_VARARGS|METH_KEYWORDS},
+    {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
+    {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
+        METH_VARARGS},
+#if (DBVER >= 46)
+    {"rep_elect",       (PyCFunction)DBEnv_rep_elect,         METH_VARARGS},
+#endif
+#if (DBVER >= 44)
+    {"rep_set_config",  (PyCFunction)DBEnv_rep_set_config,    METH_VARARGS},
+    {"rep_get_config",  (PyCFunction)DBEnv_rep_get_config,    METH_VARARGS},
+    {"rep_sync",        (PyCFunction)DBEnv_rep_sync,          METH_NOARGS},
+#endif
+#if (DBVER >= 45)
+    {"rep_set_limit",   (PyCFunction)DBEnv_rep_set_limit,     METH_VARARGS},
+    {"rep_get_limit",   (PyCFunction)DBEnv_rep_get_limit,     METH_NOARGS},
+#endif
+#if (DBVER >= 47)
+    {"rep_set_request", (PyCFunction)DBEnv_rep_set_request,   METH_VARARGS},
+    {"rep_get_request", (PyCFunction)DBEnv_rep_get_request,   METH_NOARGS},
+#endif
+#if (DBVER >= 45)
+    {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
+#endif
+#if (DBVER >= 45)
+    {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
+    {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
+    {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
+    {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
+    {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
+    {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
+#endif
+#if (DBVER >= 45)
+    {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
+        METH_VARARGS|METH_KEYWORDS},
+    {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
+        METH_VARARGS|METH_KEYWORDS},
+    {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
+        METH_VARARGS|METH_KEYWORDS},
+    {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
+        METH_VARARGS},
+    {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
+        METH_NOARGS},
+    {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
+        METH_NOARGS},
+#endif
+#if (DBVER >= 46)
+    {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
+        METH_VARARGS|METH_KEYWORDS},
+    {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
+        METH_VARARGS|METH_KEYWORDS},
+#endif
     {NULL,      NULL}       /* sentinel */
 };
 
@@ -5298,8 +6545,9 @@
 static PyMethodDef DBTxn_methods[] = {
     {"commit",          (PyCFunction)DBTxn_commit,      METH_VARARGS},
     {"prepare",         (PyCFunction)DBTxn_prepare,     METH_VARARGS},
-    {"abort",           (PyCFunction)DBTxn_abort,       METH_VARARGS},
-    {"id",              (PyCFunction)DBTxn_id,          METH_VARARGS},
+    {"discard",         (PyCFunction)DBTxn_discard,     METH_NOARGS},
+    {"abort",           (PyCFunction)DBTxn_abort,       METH_NOARGS},
+    {"id",              (PyCFunction)DBTxn_id,          METH_NOARGS},
     {NULL,      NULL}       /* sentinel */
 };
 
@@ -5308,30 +6556,40 @@
 static PyMethodDef DBSequence_methods[] = {
     {"close",           (PyCFunction)DBSequence_close,          METH_VARARGS},
     {"get",             (PyCFunction)DBSequence_get,            METH_VARARGS|METH_KEYWORDS},
-    {"get_dbp",         (PyCFunction)DBSequence_get_dbp,        METH_VARARGS},
-    {"get_key",         (PyCFunction)DBSequence_get_key,        METH_VARARGS},
+    {"get_dbp",         (PyCFunction)DBSequence_get_dbp,        METH_NOARGS},
+    {"get_key",         (PyCFunction)DBSequence_get_key,        METH_NOARGS},
     {"init_value",      (PyCFunction)DBSequence_init_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},
-    {"get_cachesize",   (PyCFunction)DBSequence_get_cachesize,  METH_VARARGS},
+    {"get_cachesize",   (PyCFunction)DBSequence_get_cachesize,  METH_NOARGS},
     {"set_flags",       (PyCFunction)DBSequence_set_flags,      METH_VARARGS},
-    {"get_flags",       (PyCFunction)DBSequence_get_flags,      METH_VARARGS},
+    {"get_flags",       (PyCFunction)DBSequence_get_flags,      METH_NOARGS},
     {"set_range",       (PyCFunction)DBSequence_set_range,      METH_VARARGS},
-    {"get_range",       (PyCFunction)DBSequence_get_range,      METH_VARARGS},
+    {"get_range",       (PyCFunction)DBSequence_get_range,      METH_NOARGS},
     {"stat",            (PyCFunction)DBSequence_stat,           METH_VARARGS|METH_KEYWORDS},
     {NULL,      NULL}       /* sentinel */
 };
 #endif
 
+
 static PyObject*
 DBEnv_db_home_get(DBEnvObject* self)
 {
+    const char *home = NULL;
+
     CHECK_ENV_NOT_CLOSED(self);
-    if (self->db_env->db_home == NULL) {
+
+#if (DBVER >= 42)
+    self->db_env->get_home(self->db_env, &home);
+#else
+    home=self->db_env->db_home;
+#endif
+
+    if (home == NULL) {
         RETURN_NONE();
     }
-    return PyUnicode_FromString(self->db_env->db_home);
+    return PyBytes_FromString(home);
 }
 
 static PyGetSetDef DBEnv_getsets[] = {
@@ -5340,16 +6598,21 @@
 };
 
 
-static PyTypeObject DB_Type = {
+statichere PyTypeObject DB_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+    PyObject_HEAD_INIT(NULL)
+    0,                  /*ob_size*/
+#else
     PyVarObject_HEAD_INIT(NULL, 0)
+#endif
     "DB",               /*tp_name*/
     sizeof(DBObject),   /*tp_basicsize*/
     0,                  /*tp_itemsize*/
     /* methods */
     (destructor)DB_dealloc, /*tp_dealloc*/
-    0,                  /*tp_print*/
-    0,                  /*tp_getattr*/
-    0,                  /*tp_setattr*/
+    0,          /*tp_print*/
+    0,          /*tp_getattr*/
+    0,          /*tp_setattr*/
     0,          /*tp_compare*/
     0,          /*tp_repr*/
     0,          /*tp_as_number*/
@@ -5359,55 +6622,75 @@
     0,			/* tp_call */
     0,			/* tp_str */
     0,  		/* tp_getattro */
-    0,                  /* tp_setattro */
+    0,          /* tp_setattro */
     0,			/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT, /* tp_flags */
-    0,                  /* tp_doc */
-    0,		        /* tp_traverse */
+#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(DBObject, in_weakreflist),   /* tp_weaklistoffset */
-    0,			/* tp_iter */
-    0,			/* tp_iternext */
-    DB_methods,		/* tp_methods */
+    0,          /*tp_iter*/
+    0,          /*tp_iternext*/
+    DB_methods, /*tp_methods*/
+    0, /*tp_members*/
 };
 
 
-static PyTypeObject DBCursor_Type = {
+statichere PyTypeObject DBCursor_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+    PyObject_HEAD_INIT(NULL)
+    0,                  /*ob_size*/
+#else
     PyVarObject_HEAD_INIT(NULL, 0)
+#endif
     "DBCursor",         /*tp_name*/
     sizeof(DBCursorObject),  /*tp_basicsize*/
-    0,                  /*tp_itemsize*/
+    0,          /*tp_itemsize*/
     /* methods */
     (destructor)DBCursor_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 */
-    Py_TPFLAGS_DEFAULT, /* tp_flags */
-    0,                  /* tp_doc */
-    0,		        /* tp_traverse */
-    0,			/* tp_clear */
-    0,			/* tp_richcompare */
+    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(DBCursorObject, in_weakreflist),   /* tp_weaklistoffset */
-    0,			/* tp_iter */
-    0,			/* tp_iternext */
-    DBCursor_methods,	/* tp_methods */
+    0,          /*tp_iter*/
+    0,          /*tp_iternext*/
+    DBCursor_methods, /*tp_methods*/
+    0,          /*tp_members*/
 };
 
 
-static PyTypeObject DBEnv_Type = {
+statichere PyTypeObject DBEnv_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+    PyObject_HEAD_INIT(NULL)
+    0,                  /*ob_size*/
+#else
     PyVarObject_HEAD_INIT(NULL, 0)
+#endif
     "DBEnv",            /*tp_name*/
     sizeof(DBEnvObject),    /*tp_basicsize*/
     0,          /*tp_itemsize*/
@@ -5425,23 +6708,32 @@
     0,			/* tp_call */
     0,			/* tp_str */
     0,  		/* tp_getattro */
-    0,                  /* tp_setattro */
+    0,          /* tp_setattro */
     0,			/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT, /* tp_flags */
-    0,                  /* tp_doc */
-    0,		        /* tp_traverse */
+#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(DBEnvObject, in_weakreflist),   /* tp_weaklistoffset */
-    0,                  /* tp_iter */
-    0,                  /* tp_iternext */
+    0,          /* tp_iter */
+    0,          /* tp_iternext */
     DBEnv_methods,      /* tp_methods */
-    0,                  /* tp_members */
+    0,          /* tp_members */
     DBEnv_getsets,      /* tp_getsets */
 };
 
-static PyTypeObject DBTxn_Type = {
+statichere PyTypeObject DBTxn_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+    PyObject_HEAD_INIT(NULL)
+    0,                  /*ob_size*/
+#else
     PyVarObject_HEAD_INIT(NULL, 0)
+#endif
     "DBTxn",    /*tp_name*/
     sizeof(DBTxnObject),  /*tp_basicsize*/
     0,          /*tp_itemsize*/
@@ -5459,22 +6751,32 @@
     0,			/* tp_call */
     0,			/* tp_str */
     0,  		/* tp_getattro */
-    0,                  /* tp_setattro */
+    0,          /* tp_setattro */
     0,			/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT, /* tp_flags */
-    0,                  /* tp_doc */
-    0,		        /* tp_traverse */
+#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(DBTxnObject, in_weakreflist),   /* tp_weaklistoffset */
-    0,			/* tp_iter */
-    0,			/* tp_iternext */
-    DBTxn_methods,	/* tp_methods */
+    0,          /*tp_iter*/
+    0,          /*tp_iternext*/
+    DBTxn_methods, /*tp_methods*/
+    0,          /*tp_members*/
 };
 
 
-static PyTypeObject DBLock_Type = {
+statichere PyTypeObject DBLock_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+    PyObject_HEAD_INIT(NULL)
+    0,                  /*ob_size*/
+#else
     PyVarObject_HEAD_INIT(NULL, 0)
+#endif
     "DBLock",   /*tp_name*/
     sizeof(DBLockObject),  /*tp_basicsize*/
     0,          /*tp_itemsize*/
@@ -5492,19 +6794,28 @@
     0,			/* tp_call */
     0,			/* tp_str */
     0,  		/* tp_getattro */
-    0,                  /* tp_setattro */
+    0,          /* tp_setattro */
     0,			/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT, /* tp_flags */
-    0,                  /* tp_doc */
-    0,		        /* tp_traverse */
+#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(DBLockObject, in_weakreflist),   /* tp_weaklistoffset */
 };
 
 #if (DBVER >= 43)
-static PyTypeObject DBSequence_Type = {
+statichere PyTypeObject DBSequence_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+    PyObject_HEAD_INIT(NULL)
+    0,                  /*ob_size*/
+#else
     PyVarObject_HEAD_INIT(NULL, 0)
+#endif
     "DBSequence",                   /*tp_name*/
     sizeof(DBSequenceObject),       /*tp_basicsize*/
     0,          /*tp_itemsize*/
@@ -5524,15 +6835,20 @@
     0,  		/* tp_getattro */
     0,          /* tp_setattro */
     0,			/* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT, /* tp_flags */
+#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(DBSequenceObject, in_weakreflist),   /* tp_weaklistoffset */
-    0,			/* tp_iter */
-    0,			/* tp_iternext */
-    DBSequence_methods,	/* tp_methods */
+    0,          /*tp_iter*/
+    0,          /*tp_iternext*/
+    DBSequence_methods, /*tp_methods*/
+    0,          /*tp_members*/
 };
 #endif
 
@@ -5591,29 +6907,27 @@
 underlying DB library.";
 
 static PyObject*
-bsddb_version(PyObject* self, PyObject* args)
+bsddb_version(PyObject* self)
 {
     int major, minor, patch;
 
-        if (!PyArg_ParseTuple(args, ":version"))
-        return NULL;
-        db_version(&major, &minor, &patch);
-        return Py_BuildValue("(iii)", major, minor, patch);
+    db_version(&major, &minor, &patch);
+    return Py_BuildValue("(iii)", major, minor, patch);
 }
 
 
 /* List of functions defined in the module */
-
 static PyMethodDef bsddb_methods[] = {
     {"DB",          (PyCFunction)DB_construct,          METH_VARARGS | METH_KEYWORDS },
     {"DBEnv",       (PyCFunction)DBEnv_construct,       METH_VARARGS},
-#if (DBVER >= 43)    
+#if (DBVER >= 43)
     {"DBSequence",  (PyCFunction)DBSequence_construct,  METH_VARARGS | METH_KEYWORDS },
-#endif    
-    {"version",     (PyCFunction)bsddb_version,         METH_VARARGS, bsddb_version_doc},
+#endif
+    {"version",     (PyCFunction)bsddb_version,         METH_NOARGS, bsddb_version_doc},
     {NULL,      NULL}       /* sentinel */
 };
 
+
 /* API structure */
 static BSDDB_api bsddb_api;
 
@@ -5630,44 +6944,51 @@
 #define MODULE_NAME_MAX_LEN     11
 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
 
-
-static struct PyModuleDef _bsddbmodule = {
-	PyModuleDef_HEAD_INIT,
-	_bsddbModuleName,
-	NULL,
-	-1,
-	bsddb_methods,
-	NULL,
-	NULL,
-	NULL,
-	NULL
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef bsddbmodule = {
+    PyModuleDef_HEAD_INIT,
+    _bsddbModuleName,   /* Name of module */
+    NULL,               /* module documentation, may be NULL */
+    -1,                 /* size of per-interpreter state of the module,
+                            or -1 if the module keeps state in global variables. */
+    bsddb_methods,
+    NULL,   /* Reload */
+    NULL,   /* Traverse */
+    NULL,   /* Clear */
+    NULL    /* Free */
 };
+#endif
 
-PyMODINIT_FUNC PyInit__bsddb(void)
+
+#if (PY_VERSION_HEX < 0x03000000)
+DL_EXPORT(void) init_bsddb(void)
+#else
+PyMODINIT_FUNC  PyInit__bsddb(void)    /* Note the two underscores */
+#endif
 {
     PyObject* m;
     PyObject* d;
-    PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
-    PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
-    PyObject* svnid_s = PyUnicode_FromString(svn_id);
+    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;
 
     /* Initialize object types */
-    if (PyType_Ready(&DB_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&DBCursor_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&DBEnv_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&DBTxn_Type) < 0)
-        return NULL;
-    if (PyType_Ready(&DBLock_Type) < 0)
-        return NULL;
+    if ((PyType_Ready(&DB_Type) < 0)
+        || (PyType_Ready(&DBCursor_Type) < 0)
+        || (PyType_Ready(&DBEnv_Type) < 0)
+        || (PyType_Ready(&DBTxn_Type) < 0)
+        || (PyType_Ready(&DBLock_Type) < 0)
 #if (DBVER >= 43)
-    if (PyType_Ready(&DBSequence_Type) < 0)
+        || (PyType_Ready(&DBSequence_Type) < 0)
+#endif
+        ) {
+#if (PY_VERSION_HEX < 0x03000000)
+        return;
+#else
         return NULL;
 #endif
-
+    }
 
 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
     /* Save the current interpreter, so callbacks can do the right thing. */
@@ -5675,19 +6996,28 @@
 #endif
 
     /* Create the module and add the functions */
-    m = PyModule_Create(&_bsddbmodule);
-    if (m == NULL)
+#if (PY_VERSION_HEX < 0x03000000)
+    m = Py_InitModule(_bsddbModuleName, bsddb_methods);
+#else
+    m=PyModule_Create(&bsddbmodule);
+#endif
+    if (m == NULL) {
+#if (PY_VERSION_HEX < 0x03000000)
+        return;
+#else
     	return NULL;
+#endif
+    }
 
     /* Add some symbolic constants to the module */
     d = PyModule_GetDict(m);
     PyDict_SetItemString(d, "__version__", pybsddb_version_s);
-    PyDict_SetItemString(d, "cvsid", svnid_s);
+    PyDict_SetItemString(d, "cvsid", cvsid_s);
     PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
     Py_DECREF(pybsddb_version_s);
     pybsddb_version_s = NULL;
-    Py_DECREF(svnid_s);
-    svnid_s = NULL;
+    Py_DECREF(cvsid_s);
+    cvsid_s = NULL;
     Py_DECREF(db_version_s);
     db_version_s = NULL;
 
@@ -5702,7 +7032,7 @@
     ADD_INT(d, DB_RPCCLIENT);
 #else
     ADD_INT(d, DB_CLIENT);
-    /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
+    /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
     _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
 #endif
     ADD_INT(d, DB_XA_CREATE);
@@ -5710,6 +7040,9 @@
     ADD_INT(d, DB_CREATE);
     ADD_INT(d, DB_NOMMAP);
     ADD_INT(d, DB_THREAD);
+#if (DBVER >= 45)
+    ADD_INT(d, DB_MULTIVERSION);
+#endif
 
     ADD_INT(d, DB_FORCE);
     ADD_INT(d, DB_INIT_CDB);
@@ -5719,6 +7052,8 @@
     ADD_INT(d, DB_INIT_TXN);
     ADD_INT(d, DB_JOINENV);
 
+    ADD_INT(d, DB_XIDDATASIZE);
+
     ADD_INT(d, DB_RECOVER);
     ADD_INT(d, DB_RECOVER_FATAL);
     ADD_INT(d, DB_TXN_NOSYNC);
@@ -5747,10 +7082,7 @@
     ADD_INT(d, DB_NOORDERCHK);
     ADD_INT(d, DB_ORDERCHKONLY);
     ADD_INT(d, DB_PR_PAGE);
-#if ! (DBVER >= 33)
-    ADD_INT(d, DB_VRFY_FLAGMASK);
-    ADD_INT(d, DB_PR_HEADERS);
-#endif
+
     ADD_INT(d, DB_PR_RECOVERYTEST);
     ADD_INT(d, DB_SALVAGE);
 
@@ -5759,19 +7091,16 @@
     ADD_INT(d, DB_LOCK_OLDEST);
     ADD_INT(d, DB_LOCK_RANDOM);
     ADD_INT(d, DB_LOCK_YOUNGEST);
-#if (DBVER >= 33)
     ADD_INT(d, DB_LOCK_MAXLOCKS);
     ADD_INT(d, DB_LOCK_MINLOCKS);
     ADD_INT(d, DB_LOCK_MINWRITE);
+
+    ADD_INT(d, DB_LOCK_EXPIRE);
+#if (DBVER >= 43)
+    ADD_INT(d, DB_LOCK_MAXWRITE);
 #endif
 
-
-#if (DBVER >= 33)
-    /* docs say to use zero instead */
     _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
-#else
-    ADD_INT(d, DB_LOCK_CONFLICT);
-#endif
 
     ADD_INT(d, DB_LOCK_DUMP);
     ADD_INT(d, DB_LOCK_GET);
@@ -5788,39 +7117,31 @@
     ADD_INT(d, DB_LOCK_IWRITE);
     ADD_INT(d, DB_LOCK_IREAD);
     ADD_INT(d, DB_LOCK_IWR);
-#if (DBVER >= 33)
 #if (DBVER < 44)
     ADD_INT(d, DB_LOCK_DIRTY);
 #else
     ADD_INT(d, DB_LOCK_READ_UNCOMMITTED);  /* renamed in 4.4 */
 #endif
     ADD_INT(d, DB_LOCK_WWRITE);
-#endif
 
     ADD_INT(d, DB_LOCK_RECORD);
     ADD_INT(d, DB_LOCK_UPGRADE);
     ADD_INT(d, DB_LOCK_SWITCH);
-#if (DBVER >= 33)
     ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
-#endif
 
     ADD_INT(d, DB_LOCK_NOWAIT);
     ADD_INT(d, DB_LOCK_RECORD);
     ADD_INT(d, DB_LOCK_UPGRADE);
 
-#if (DBVER >= 33)
     ADD_INT(d, DB_LSTAT_ABORTED);
 #if (DBVER < 43)
     ADD_INT(d, DB_LSTAT_ERR);
 #endif
     ADD_INT(d, DB_LSTAT_FREE);
     ADD_INT(d, DB_LSTAT_HELD);
-#if (DBVER == 33)
-    ADD_INT(d, DB_LSTAT_NOGRANT);
-#endif
+
     ADD_INT(d, DB_LSTAT_PENDING);
     ADD_INT(d, DB_LSTAT_WAITING);
-#endif
 
     ADD_INT(d, DB_ARCH_ABS);
     ADD_INT(d, DB_ARCH_DATA);
@@ -5850,21 +7171,20 @@
 #if (DBVER < 45)
     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 >= 33) && (DBVER <= 41))
+#if (DBVER <= 41)
     ADD_INT(d, DB_COMMIT);
 #endif
     ADD_INT(d, DB_CONSUME);
     ADD_INT(d, DB_CONSUME_WAIT);
     ADD_INT(d, DB_CURRENT);
-#if (DBVER >= 33)
     ADD_INT(d, DB_FAST_STAT);
-#endif
     ADD_INT(d, DB_FIRST);
     ADD_INT(d, DB_FLUSH);
     ADD_INT(d, DB_GET_BOTH);
@@ -5892,21 +7212,16 @@
 
     ADD_INT(d, DB_OPFLAGS_MASK);
     ADD_INT(d, DB_RMW);
-#if (DBVER >= 33)
     ADD_INT(d, DB_DIRTY_READ);
     ADD_INT(d, DB_MULTIPLE);
     ADD_INT(d, DB_MULTIPLE_KEY);
-#endif
 
 #if (DBVER >= 44)
     ADD_INT(d, DB_READ_UNCOMMITTED);    /* replaces DB_DIRTY_READ in 4.4 */
     ADD_INT(d, DB_READ_COMMITTED);
 #endif
 
-#if (DBVER >= 33)
     ADD_INT(d, DB_DONOTINDEX);
-    ADD_INT(d, DB_XIDDATASIZE);
-#endif
 
 #if (DBVER >= 41)
     _addIntToDict(d, "DB_INCOMPLETE", 0);
@@ -5924,17 +7239,17 @@
     ADD_INT(d, DB_OLD_VERSION);
     ADD_INT(d, DB_RUNRECOVERY);
     ADD_INT(d, DB_VERIFY_BAD);
-#if (DBVER >= 33)
     ADD_INT(d, DB_PAGE_NOTFOUND);
     ADD_INT(d, DB_SECONDARY_BAD);
-#endif
-#if (DBVER >= 40)
     ADD_INT(d, DB_STAT_CLEAR);
     ADD_INT(d, DB_REGION_INIT);
     ADD_INT(d, DB_NOLOCKING);
     ADD_INT(d, DB_YIELDCPU);
     ADD_INT(d, DB_PANIC_ENVIRONMENT);
     ADD_INT(d, DB_NOPANIC);
+
+#if (DBVER >= 41)
+    ADD_INT(d, DB_OVERWRITE);
 #endif
 
 #ifdef DB_REGISTER
@@ -5945,27 +7260,118 @@
     ADD_INT(d, DB_TIME_NOTGRANTED);
     ADD_INT(d, DB_TXN_NOT_DURABLE);
     ADD_INT(d, DB_TXN_WRITE_NOSYNC);
-    ADD_INT(d, DB_LOG_AUTOREMOVE);
-    ADD_INT(d, DB_DIRECT_LOG);
     ADD_INT(d, DB_DIRECT_DB);
     ADD_INT(d, DB_INIT_REP);
     ADD_INT(d, DB_ENCRYPT);
     ADD_INT(d, DB_CHKSUM);
 #endif
 
+#if (DBVER >= 42) && (DBVER < 47)
+    ADD_INT(d, DB_LOG_AUTOREMOVE);
+    ADD_INT(d, DB_DIRECT_LOG);
+#endif
+
+#if (DBVER >= 47)
+    ADD_INT(d, DB_LOG_DIRECT);
+    ADD_INT(d, DB_LOG_DSYNC);
+    ADD_INT(d, DB_LOG_IN_MEMORY);
+    ADD_INT(d, DB_LOG_AUTO_REMOVE);
+    ADD_INT(d, DB_LOG_ZERO);
+#endif
+
+#if (DBVER >= 44)
+    ADD_INT(d, DB_DSYNC_DB);
+#endif
+
+#if (DBVER >= 45)
+    ADD_INT(d, DB_TXN_SNAPSHOT);
+#endif
+
+    ADD_INT(d, DB_VERB_DEADLOCK);
+#if (DBVER >= 46)
+    ADD_INT(d, DB_VERB_FILEOPS);
+    ADD_INT(d, DB_VERB_FILEOPS_ALL);
+#endif
+    ADD_INT(d, DB_VERB_RECOVERY);
+#if (DBVER >= 44)
+    ADD_INT(d, DB_VERB_REGISTER);
+#endif
+    ADD_INT(d, DB_VERB_REPLICATION);
+    ADD_INT(d, DB_VERB_WAITSFOR);
+
+#if (DBVER >= 45)
+    ADD_INT(d, DB_EVENT_PANIC);
+    ADD_INT(d, DB_EVENT_REP_CLIENT);
+#if (DBVER >= 46)
+    ADD_INT(d, DB_EVENT_REP_ELECTED);
+#endif
+    ADD_INT(d, DB_EVENT_REP_MASTER);
+    ADD_INT(d, DB_EVENT_REP_NEWMASTER);
+#if (DBVER >= 46)
+    ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
+#endif
+    ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
+    ADD_INT(d, DB_EVENT_WRITE_FAILED);
+#endif
+
+    ADD_INT(d, DB_REP_DUPMASTER);
+    ADD_INT(d, DB_REP_HOLDELECTION);
+#if (DBVER >= 44)
+    ADD_INT(d, DB_REP_IGNORE);
+    ADD_INT(d, DB_REP_JOIN_FAILURE);
+#endif
+#if (DBVER >= 42)
+    ADD_INT(d, DB_REP_ISPERM);
+    ADD_INT(d, DB_REP_NOTPERM);
+#endif
+    ADD_INT(d, DB_REP_NEWSITE);
+
+    ADD_INT(d, DB_REP_MASTER);
+    ADD_INT(d, DB_REP_CLIENT);
+#if (DBVER >= 45)
+    ADD_INT(d, DB_REP_ELECTION);
+
+    ADD_INT(d, DB_REP_ACK_TIMEOUT);
+    ADD_INT(d, DB_REP_CONNECTION_RETRY);
+    ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
+    ADD_INT(d, DB_REP_ELECTION_RETRY);
+#endif
+#if (DBVER >= 46)
+    ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
+    ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
+#endif
+
+#if (DBVER >= 45)
+    ADD_INT(d, DB_REPMGR_PEER);
+    ADD_INT(d, DB_REPMGR_ACKS_ALL);
+    ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
+    ADD_INT(d, DB_REPMGR_ACKS_NONE);
+    ADD_INT(d, DB_REPMGR_ACKS_ONE);
+    ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
+    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
+
 #if (DBVER >= 43)
-    ADD_INT(d, DB_LOG_INMEMORY);
     ADD_INT(d, DB_BUFFER_SMALL);
     ADD_INT(d, DB_SEQ_DEC);
     ADD_INT(d, DB_SEQ_INC);
     ADD_INT(d, DB_SEQ_WRAP);
 #endif
 
+#if (DBVER >= 43) && (DBVER < 47)
+    ADD_INT(d, DB_LOG_INMEMORY);
+    ADD_INT(d, DB_DSYNC_LOG);
+#endif
+
 #if (DBVER >= 41)
     ADD_INT(d, DB_ENCRYPT_AES);
     ADD_INT(d, DB_AUTO_COMMIT);
 #else
-    /* allow berkeleydb 4.1 aware apps to run on older versions */
+    /* allow Berkeley DB 4.1 aware apps to run on older versions */
     _addIntToDict(d, "DB_AUTO_COMMIT", 0);
 #endif
 
@@ -5979,10 +7385,8 @@
     ADD_INT(d, ENOENT);
     ADD_INT(d, EPERM);
 
-#if (DBVER >= 40)
     ADD_INT(d, DB_SET_LOCK_TIMEOUT);
     ADD_INT(d, DB_SET_TXN_TIMEOUT);
-#endif
 
     /* The exception name must be correct for pickled exception *
      * objects to unpickle properly.                            */
@@ -6000,20 +7404,37 @@
     DBError = NULL;     /* used in MAKE_EX so that it derives from nothing */
     MAKE_EX(DBError);
 
+#if (PY_VERSION_HEX < 0x03000000)
     /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
      * from both DBError and KeyError, since the API only supports
      * using one base class. */
     PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
-    { 
-	    PyObject *builtin_mod = PyImport_ImportModule("builtins");
-	    PyDict_SetItemString(d, "__builtins__", builtin_mod);
-    }
     PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
 	         "class DBKeyEmptyError(DBError, KeyError): pass",
                  Py_file_input, d, d);
     DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
     DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
     PyDict_DelItemString(d, "KeyError");
+#else
+    /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
+    ** derive from several classes. We use this new API only for Python 3.0,
+    ** though.
+    */
+    {
+        PyObject* bases;
+
+        bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
+
+#define MAKE_EX2(name)   name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
+                         PyDict_SetItemString(d, #name, name)
+        MAKE_EX2(DBNotFoundError);
+        MAKE_EX2(DBKeyEmptyError);
+
+#undef MAKE_EX2
+
+        Py_XDECREF(bases);
+    }
+#endif
 
 
 #if !INCOMPLETE_IS_WARNING
@@ -6030,10 +7451,8 @@
     MAKE_EX(DBNoServerError);
     MAKE_EX(DBNoServerHomeError);
     MAKE_EX(DBNoServerIDError);
-#if (DBVER >= 33)
     MAKE_EX(DBPageNotFoundError);
     MAKE_EX(DBSecondaryBadError);
-#endif
 
     MAKE_EX(DBInvalidArgError);
     MAKE_EX(DBAccessError);
@@ -6045,6 +7464,12 @@
     MAKE_EX(DBNoSuchFileError);
     MAKE_EX(DBPermissionsError);
 
+#if (DBVER >= 42)
+    MAKE_EX(DBRepHandleDeadError);
+#endif
+
+    MAKE_EX(DBRepUnavailError);
+
 #undef MAKE_EX
 
     /* Initiliase the C API structure and add it to the module */
@@ -6065,18 +7490,31 @@
     /* Check for errors */
     if (PyErr_Occurred()) {
         PyErr_Print();
-        Py_FatalError("can't initialize module _bsddb");
-	Py_DECREF(m);
-	m = NULL;
+        Py_FatalError("can't initialize module _bsddb/_pybsddb");
+        Py_DECREF(m);
+        m = NULL;
     }
+#if (PY_VERSION_HEX < 0x03000000)
+    return;
+#else
     return m;
+#endif
 }
 
 /* allow this module to be named _pybsddb so that it can be installed
  * and imported on top of python >= 2.3 that includes its own older
  * copy of the library named _bsddb without importing the old version. */
-PyMODINIT_FUNC init_pybsddb(void)
+#if (PY_VERSION_HEX < 0x03000000)
+DL_EXPORT(void) init_pybsddb(void)
+#else
+PyMODINIT_FUNC PyInit__pybsddb(void)  /* Note the two underscores */
+#endif
 {
     strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
-    return PyInit__bsddb();
+#if (PY_VERSION_HEX < 0x03000000)
+    init_bsddb();
+#else
+    return PyInit__bsddb();   /* Note the two underscores */
+#endif
 }
+