Home | History | Annotate | Download | only in Modules
      1 /*----------------------------------------------------------------------
      2   Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
      3   and Andrew Kuchling. All rights reserved.
      4 
      5   Redistribution and use in source and binary forms, with or without
      6   modification, are permitted provided that the following conditions are
      7   met:
      8 
      9     o Redistributions of source code must retain the above copyright
     10       notice, this list of conditions, and the disclaimer that follows.
     11 
     12     o Redistributions in binary form must reproduce the above copyright
     13       notice, this list of conditions, and the following disclaimer in
     14       the documentation and/or other materials provided with the
     15       distribution.
     16 
     17     o Neither the name of Digital Creations nor the names of its
     18       contributors may be used to endorse or promote products derived
     19       from this software without specific prior written permission.
     20 
     21   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
     22   IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23   TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     24   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL
     25   CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     26   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     27   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     28   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     29   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     30   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
     31   USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     32   DAMAGE.
     33 ------------------------------------------------------------------------*/
     34 
     35 
     36 /*
     37  * Handwritten code to wrap version 3.x of the Berkeley DB library,
     38  * written to replace a SWIG-generated file.  It has since been updated
     39  * to compile with Berkeley DB versions 3.2 through 4.2.
     40  *
     41  * This module was started by Andrew Kuchling to remove the dependency
     42  * on SWIG in a package by Gregory P. Smith who based his work on a
     43  * similar package by Robin Dunn <robin (at) alldunn.com> which wrapped
     44  * Berkeley DB 2.7.x.
     45  *
     46  * Development of this module then returned full circle back to Robin Dunn
     47  * who worked on behalf of Digital Creations to complete the wrapping of
     48  * the DB 3.x API and to build a solid unit test suite.  Robin has
     49  * since gone onto other projects (wxPython).
     50  *
     51  * Gregory P. Smith <greg (at) krypto.org> was once again the maintainer.
     52  *
     53  * Since January 2008, new maintainer is Jesus Cea <jcea (at) jcea.es>.
     54  * Jesus Cea licenses this code to PSF under a Contributor Agreement.
     55  *
     56  * Use the pybsddb-users (at) lists.sf.net mailing list for all questions.
     57  * Things can change faster than the header of this file is updated.  This
     58  * file is shared with the PyBSDDB project at SourceForge:
     59  *
     60  * http://pybsddb.sf.net
     61  *
     62  * This file should remain backward compatible with Python 2.1, but see PEP
     63  * 291 for the most current backward compatibility requirements:
     64  *
     65  * http://www.python.org/peps/pep-0291.html
     66  *
     67  * This module contains 7 types:
     68  *
     69  * DB           (Database)
     70  * DBCursor     (Database Cursor)
     71  * DBEnv        (database environment)
     72  * DBTxn        (An explicit database transaction)
     73  * DBLock       (A lock handle)
     74  * DBSequence   (Sequence)
     75  * DBSite       (Site)
     76  *
     77  * More datatypes added:
     78  *
     79  * DBLogCursor  (Log Cursor)
     80  *
     81  */
     82 
     83 /* --------------------------------------------------------------------- */
     84 
     85 /*
     86  * Portions of this module, associated unit tests and build scripts are the
     87  * result of a contract with The Written Word (http://thewrittenword.com/)
     88  * Many thanks go out to them for causing me to raise the bar on quality and
     89  * functionality, resulting in a better bsddb3 package for all of us to use.
     90  *
     91  * --Robin
     92  */
     93 
     94 /* --------------------------------------------------------------------- */
     95 
     96 #include <stddef.h>   /* for offsetof() */
     97 #include <Python.h>
     98 
     99 #define COMPILING_BSDDB_C
    100 #include "bsddb.h"
    101 #undef COMPILING_BSDDB_C
    102 
    103 static char *rcs_id = "$Id$";
    104 
    105 /* --------------------------------------------------------------------- */
    106 /* Various macro definitions */
    107 
    108 #if (PY_VERSION_HEX < 0x02050000)
    109 typedef int Py_ssize_t;
    110 #endif
    111 
    112 #if (PY_VERSION_HEX < 0x02060000)  /* really: before python trunk r63675 */
    113 /* This code now uses PyBytes* API function names instead of PyString*.
    114  * These #defines map to their equivalent on earlier python versions.    */
    115 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
    116 #define PyBytes_FromString PyString_FromString
    117 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
    118 #define PyBytes_Check PyString_Check
    119 #define PyBytes_GET_SIZE PyString_GET_SIZE
    120 #define PyBytes_AS_STRING PyString_AS_STRING
    121 #endif
    122 
    123 #if (PY_VERSION_HEX >= 0x03000000)
    124 #define NUMBER_Check    PyLong_Check
    125 #define NUMBER_AsLong   PyLong_AsLong
    126 #define NUMBER_FromLong PyLong_FromLong
    127 #else
    128 #define NUMBER_Check    PyInt_Check
    129 #define NUMBER_AsLong   PyInt_AsLong
    130 #define NUMBER_FromLong PyInt_FromLong
    131 #endif
    132 
    133 #ifdef WITH_THREAD
    134 
    135 /* These are for when calling Python --> C */
    136 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
    137 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
    138 
    139 /* and these are for calling C --> Python */
    140 #define MYDB_BEGIN_BLOCK_THREADS \
    141                 PyGILState_STATE __savestate = PyGILState_Ensure();
    142 #define MYDB_END_BLOCK_THREADS \
    143                 PyGILState_Release(__savestate);
    144 
    145 #else
    146 /* Compiled without threads - avoid all this cruft */
    147 #define MYDB_BEGIN_ALLOW_THREADS
    148 #define MYDB_END_ALLOW_THREADS
    149 #define MYDB_BEGIN_BLOCK_THREADS
    150 #define MYDB_END_BLOCK_THREADS
    151 
    152 #endif
    153 
    154 /* --------------------------------------------------------------------- */
    155 /* Exceptions */
    156 
    157 static PyObject* DBError;               /* Base class, all others derive from this */
    158 static PyObject* DBCursorClosedError;   /* raised when trying to use a closed cursor object */
    159 static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY: also derives from KeyError */
    160 static PyObject* DBKeyExistError;       /* DB_KEYEXIST */
    161 static PyObject* DBLockDeadlockError;   /* DB_LOCK_DEADLOCK */
    162 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
    163 static PyObject* DBNotFoundError;       /* DB_NOTFOUND: also derives from KeyError */
    164 static PyObject* DBOldVersionError;     /* DB_OLD_VERSION */
    165 static PyObject* DBRunRecoveryError;    /* DB_RUNRECOVERY */
    166 static PyObject* DBVerifyBadError;      /* DB_VERIFY_BAD */
    167 static PyObject* DBNoServerError;       /* DB_NOSERVER */
    168 #if (DBVER < 52)
    169 static PyObject* DBNoServerHomeError;   /* DB_NOSERVER_HOME */
    170 static PyObject* DBNoServerIDError;     /* DB_NOSERVER_ID */
    171 #endif
    172 static PyObject* DBPageNotFoundError;   /* DB_PAGE_NOTFOUND */
    173 static PyObject* DBSecondaryBadError;   /* DB_SECONDARY_BAD */
    174 
    175 static PyObject* DBInvalidArgError;     /* EINVAL */
    176 static PyObject* DBAccessError;         /* EACCES */
    177 static PyObject* DBNoSpaceError;        /* ENOSPC */
    178 static PyObject* DBNoMemoryError;       /* DB_BUFFER_SMALL */
    179 static PyObject* DBAgainError;          /* EAGAIN */
    180 static PyObject* DBBusyError;           /* EBUSY  */
    181 static PyObject* DBFileExistsError;     /* EEXIST */
    182 static PyObject* DBNoSuchFileError;     /* ENOENT */
    183 static PyObject* DBPermissionsError;    /* EPERM  */
    184 
    185 static PyObject* DBRepHandleDeadError;  /* DB_REP_HANDLE_DEAD */
    186 #if (DBVER >= 44)
    187 static PyObject* DBRepLockoutError;     /* DB_REP_LOCKOUT */
    188 #endif
    189 
    190 #if (DBVER >= 46)
    191 static PyObject* DBRepLeaseExpiredError; /* DB_REP_LEASE_EXPIRED */
    192 #endif
    193 
    194 #if (DBVER >= 47)
    195 static PyObject* DBForeignConflictError; /* DB_FOREIGN_CONFLICT */
    196 #endif
    197 
    198 
    199 static PyObject* DBRepUnavailError;     /* DB_REP_UNAVAIL */
    200 
    201 #if (DBVER < 48)
    202 #define DB_GID_SIZE DB_XIDDATASIZE
    203 #endif
    204 
    205 
    206 /* --------------------------------------------------------------------- */
    207 /* Structure definitions */
    208 
    209 #if PYTHON_API_VERSION < 1010
    210 #error "Python 2.1 or later required"
    211 #endif
    212 
    213 
    214 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
    215 #define DEFAULT_GET_RETURNS_NONE                1
    216 #define DEFAULT_CURSOR_SET_RETURNS_NONE         1   /* 0 in pybsddb < 4.2, python < 2.4 */
    217 
    218 
    219 /* See comment in Python 2.6 "object.h" */
    220 #ifndef staticforward
    221 #define staticforward static
    222 #endif
    223 #ifndef statichere
    224 #define statichere static
    225 #endif
    226 
    227 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
    228               DBLock_Type, DBLogCursor_Type;
    229 staticforward PyTypeObject DBSequence_Type;
    230 #if (DBVER >= 52)
    231 staticforward PyTypeObject DBSite_Type;
    232 #endif
    233 
    234 #ifndef Py_TYPE
    235 /* for compatibility with Python 2.5 and earlier */
    236 #define Py_TYPE(ob)              (((PyObject*)(ob))->ob_type)
    237 #endif
    238 
    239 #define DBObject_Check(v)           (Py_TYPE(v) == &DB_Type)
    240 #define DBCursorObject_Check(v)     (Py_TYPE(v) == &DBCursor_Type)
    241 #define DBLogCursorObject_Check(v)  (Py_TYPE(v) == &DBLogCursor_Type)
    242 #define DBEnvObject_Check(v)        (Py_TYPE(v) == &DBEnv_Type)
    243 #define DBTxnObject_Check(v)        (Py_TYPE(v) == &DBTxn_Type)
    244 #define DBLockObject_Check(v)       (Py_TYPE(v) == &DBLock_Type)
    245 #define DBSequenceObject_Check(v)   (Py_TYPE(v) == &DBSequence_Type)
    246 #if (DBVER >= 52)
    247 #define DBSiteObject_Check(v)       (Py_TYPE(v) == &DBSite_Type)
    248 #endif
    249 
    250 #if (DBVER < 46)
    251   #define _DBC_close(dbc)           dbc->c_close(dbc)
    252   #define _DBC_count(dbc,a,b)       dbc->c_count(dbc,a,b)
    253   #define _DBC_del(dbc,a)           dbc->c_del(dbc,a)
    254   #define _DBC_dup(dbc,a,b)         dbc->c_dup(dbc,a,b)
    255   #define _DBC_get(dbc,a,b,c)       dbc->c_get(dbc,a,b,c)
    256   #define _DBC_pget(dbc,a,b,c,d)    dbc->c_pget(dbc,a,b,c,d)
    257   #define _DBC_put(dbc,a,b,c)       dbc->c_put(dbc,a,b,c)
    258 #else
    259   #define _DBC_close(dbc)           dbc->close(dbc)
    260   #define _DBC_count(dbc,a,b)       dbc->count(dbc,a,b)
    261   #define _DBC_del(dbc,a)           dbc->del(dbc,a)
    262   #define _DBC_dup(dbc,a,b)         dbc->dup(dbc,a,b)
    263   #define _DBC_get(dbc,a,b,c)       dbc->get(dbc,a,b,c)
    264   #define _DBC_pget(dbc,a,b,c,d)    dbc->pget(dbc,a,b,c,d)
    265   #define _DBC_put(dbc,a,b,c)       dbc->put(dbc,a,b,c)
    266 #endif
    267 
    268 
    269 /* --------------------------------------------------------------------- */
    270 /* Utility macros and functions */
    271 
    272 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object)                   \
    273     {                                                                   \
    274         object->sibling_next=backlink;                                  \
    275         object->sibling_prev_p=&(backlink);                             \
    276         backlink=object;                                                \
    277         if (object->sibling_next) {                                     \
    278           object->sibling_next->sibling_prev_p=&(object->sibling_next); \
    279         }                                                               \
    280     }
    281 
    282 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object)                          \
    283     {                                                                    \
    284         if (object->sibling_next) {                                      \
    285             object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
    286         }                                                                \
    287         *(object->sibling_prev_p)=object->sibling_next;                  \
    288     }
    289 
    290 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object)               \
    291     {                                                                    \
    292         if (object->sibling_next) {                                      \
    293             object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
    294         }                                                                \
    295         if (object->sibling_prev_p) {                                    \
    296             *(object->sibling_prev_p)=object->sibling_next;              \
    297         }                                                                \
    298     }
    299 
    300 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object)  \
    301     {                                                      \
    302         object->sibling_next_txn=backlink;                 \
    303         object->sibling_prev_p_txn=&(backlink);            \
    304         backlink=object;                                   \
    305         if (object->sibling_next_txn) {                    \
    306             object->sibling_next_txn->sibling_prev_p_txn=  \
    307                 &(object->sibling_next_txn);               \
    308         }                                                  \
    309     }
    310 
    311 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object)             \
    312     {                                                           \
    313         if (object->sibling_next_txn) {                         \
    314             object->sibling_next_txn->sibling_prev_p_txn=       \
    315                 object->sibling_prev_p_txn;                     \
    316         }                                                       \
    317         *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
    318     }
    319 
    320 
    321 #define RETURN_IF_ERR()          \
    322     if (makeDBError(err)) {      \
    323         return NULL;             \
    324     }
    325 
    326 #define RETURN_NONE()  Py_INCREF(Py_None); return Py_None;
    327 
    328 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
    329     if ((nonNull) == NULL) {          \
    330         PyObject *errTuple = NULL;    \
    331         errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
    332         if (errTuple) { \
    333             PyErr_SetObject((pyErrObj), errTuple);  \
    334             Py_DECREF(errTuple);          \
    335         } \
    336         return NULL;                  \
    337     }
    338 
    339 #define CHECK_DB_NOT_CLOSED(dbobj) \
    340         _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
    341 
    342 #define CHECK_ENV_NOT_CLOSED(env) \
    343         _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
    344 
    345 #define CHECK_CURSOR_NOT_CLOSED(curs) \
    346         _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
    347 
    348 #define CHECK_LOGCURSOR_NOT_CLOSED(logcurs) \
    349         _CHECK_OBJECT_NOT_CLOSED(logcurs->logc, DBCursorClosedError, DBLogCursor)
    350 
    351 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
    352         _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
    353 
    354 #if (DBVER >= 52)
    355 #define CHECK_SITE_NOT_CLOSED(db_site) \
    356          _CHECK_OBJECT_NOT_CLOSED(db_site->site, DBError, DBSite)
    357 #endif
    358 
    359 #define CHECK_DBFLAG(mydb, flag)    (((mydb)->flags & (flag)) || \
    360                                      (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
    361 
    362 #define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
    363 
    364 #define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
    365                                          dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
    366 
    367 
    368 static int makeDBError(int err);
    369 
    370 
    371 /* Return the access method type of the DBObject */
    372 static int _DB_get_type(DBObject* self)
    373 {
    374     DBTYPE type;
    375     int err;
    376 
    377     err = self->db->get_type(self->db, &type);
    378     if (makeDBError(err)) {
    379         return -1;
    380     }
    381     return type;
    382 }
    383 
    384 
    385 /* Create a DBT structure (containing key and data values) from Python
    386    strings.  Returns 1 on success, 0 on an error. */
    387 static int make_dbt(PyObject* obj, DBT* dbt)
    388 {
    389     CLEAR_DBT(*dbt);
    390     if (obj == Py_None) {
    391         /* no need to do anything, the structure has already been zeroed */
    392     }
    393     else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
    394         PyErr_SetString(PyExc_TypeError,
    395 #if (PY_VERSION_HEX < 0x03000000)
    396                         "Data values must be of type string or None.");
    397 #else
    398                         "Data values must be of type bytes or None.");
    399 #endif
    400         return 0;
    401     }
    402     return 1;
    403 }
    404 
    405 
    406 /* Recno and Queue DBs can have integer keys.  This function figures out
    407    what's been given, verifies that it's allowed, and then makes the DBT.
    408 
    409    Caller MUST call FREE_DBT(key) when done. */
    410 static int
    411 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
    412 {
    413     db_recno_t recno;
    414     int type;
    415 
    416     CLEAR_DBT(*key);
    417     if (keyobj == Py_None) {
    418         type = _DB_get_type(self);
    419         if (type == -1)
    420             return 0;
    421         if (type == DB_RECNO || type == DB_QUEUE) {
    422             PyErr_SetString(
    423                 PyExc_TypeError,
    424                 "None keys not allowed for Recno and Queue DB's");
    425             return 0;
    426         }
    427         /* no need to do anything, the structure has already been zeroed */
    428     }
    429 
    430     else if (PyBytes_Check(keyobj)) {
    431         /* verify access method type */
    432         type = _DB_get_type(self);
    433         if (type == -1)
    434             return 0;
    435         if (type == DB_RECNO || type == DB_QUEUE) {
    436             PyErr_SetString(
    437                 PyExc_TypeError,
    438 #if (PY_VERSION_HEX < 0x03000000)
    439                 "String keys not allowed for Recno and Queue DB's");
    440 #else
    441                 "Bytes keys not allowed for Recno and Queue DB's");
    442 #endif
    443             return 0;
    444         }
    445 
    446         /*
    447          * NOTE(gps): I don't like doing a data copy here, it seems
    448          * wasteful.  But without a clean way to tell FREE_DBT if it
    449          * should free key->data or not we have to.  Other places in
    450          * the code check for DB_THREAD and forceably set DBT_MALLOC
    451          * when we otherwise would leave flags 0 to indicate that.
    452          */
    453         key->data = malloc(PyBytes_GET_SIZE(keyobj));
    454         if (key->data == NULL) {
    455             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
    456             return 0;
    457         }
    458         memcpy(key->data, PyBytes_AS_STRING(keyobj),
    459                PyBytes_GET_SIZE(keyobj));
    460         key->flags = DB_DBT_REALLOC;
    461         key->size = PyBytes_GET_SIZE(keyobj);
    462     }
    463 
    464     else if (NUMBER_Check(keyobj)) {
    465         /* verify access method type */
    466         type = _DB_get_type(self);
    467         if (type == -1)
    468             return 0;
    469         if (type == DB_BTREE && pflags != NULL) {
    470             /* if BTREE then an Integer key is allowed with the
    471              * DB_SET_RECNO flag */
    472             *pflags |= DB_SET_RECNO;
    473         }
    474         else if (type != DB_RECNO && type != DB_QUEUE) {
    475             PyErr_SetString(
    476                 PyExc_TypeError,
    477                 "Integer keys only allowed for Recno and Queue DB's");
    478             return 0;
    479         }
    480 
    481         /* Make a key out of the requested recno, use allocated space so DB
    482          * will be able to realloc room for the real key if needed. */
    483         recno = NUMBER_AsLong(keyobj);
    484         key->data = malloc(sizeof(db_recno_t));
    485         if (key->data == NULL) {
    486             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
    487             return 0;
    488         }
    489         key->ulen = key->size = sizeof(db_recno_t);
    490         memcpy(key->data, &recno, sizeof(db_recno_t));
    491         key->flags = DB_DBT_REALLOC;
    492     }
    493     else {
    494         PyErr_Format(PyExc_TypeError,
    495 #if (PY_VERSION_HEX < 0x03000000)
    496                      "String or Integer object expected for key, %s found",
    497 #else
    498                      "Bytes or Integer object expected for key, %s found",
    499 #endif
    500                      Py_TYPE(keyobj)->tp_name);
    501         return 0;
    502     }
    503 
    504     return 1;
    505 }
    506 
    507 
    508 /* Add partial record access to an existing DBT data struct.
    509    If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
    510    and the data storage/retrieval will be done using dlen and doff. */
    511 static int add_partial_dbt(DBT* d, int dlen, int doff) {
    512     /* if neither were set we do nothing (-1 is the default value) */
    513     if ((dlen == -1) && (doff == -1)) {
    514         return 1;
    515     }
    516 
    517     if ((dlen < 0) || (doff < 0)) {
    518         PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
    519         return 0;
    520     }
    521 
    522     d->flags = d->flags | DB_DBT_PARTIAL;
    523     d->dlen = (unsigned int) dlen;
    524     d->doff = (unsigned int) doff;
    525     return 1;
    526 }
    527 
    528 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
    529 /* TODO: make this use the native libc strlcpy() when available (BSD)      */
    530 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
    531 {
    532     unsigned int srclen, copylen;
    533 
    534     srclen = strlen(src);
    535     if (n <= 0)
    536         return srclen;
    537     copylen = (srclen > n-1) ? n-1 : srclen;
    538     /* populate dest[0] thru dest[copylen-1] */
    539     memcpy(dest, src, copylen);
    540     /* guarantee null termination */
    541     dest[copylen] = 0;
    542 
    543     return srclen;
    544 }
    545 
    546 /* Callback used to save away more information about errors from the DB
    547  * library. */
    548 static char _db_errmsg[1024];
    549 static void _db_errorCallback(const DB_ENV *db_env,
    550         const char* prefix, const char* msg)
    551 {
    552     our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
    553 }
    554 
    555 
    556 /*
    557 ** We need these functions because some results
    558 ** are undefined if pointer is NULL. Some other
    559 ** give None instead of "".
    560 **
    561 ** This functions are static and will be
    562 ** -I hope- inlined.
    563 */
    564 static const char *DummyString = "This string is a simple placeholder";
    565 static PyObject *Build_PyString(const char *p,int s)
    566 {
    567   if (!p) {
    568     p=DummyString;
    569     assert(s==0);
    570   }
    571   return PyBytes_FromStringAndSize(p,s);
    572 }
    573 
    574 static PyObject *BuildValue_S(const void *p,int s)
    575 {
    576   if (!p) {
    577     p=DummyString;
    578     assert(s==0);
    579   }
    580   return PyBytes_FromStringAndSize(p, s);
    581 }
    582 
    583 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
    584 {
    585 PyObject *a, *b, *r;
    586 
    587   if (!p1) {
    588     p1=DummyString;
    589     assert(s1==0);
    590   }
    591   if (!p2) {
    592     p2=DummyString;
    593     assert(s2==0);
    594   }
    595 
    596   if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
    597       return NULL;
    598   }
    599   if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
    600       Py_DECREF(a);
    601       return NULL;
    602   }
    603 
    604   r = PyTuple_Pack(2, a, b) ;
    605   Py_DECREF(a);
    606   Py_DECREF(b);
    607   return r;
    608 }
    609 
    610 static PyObject *BuildValue_IS(int i,const void *p,int s)
    611 {
    612   PyObject *a, *r;
    613 
    614   if (!p) {
    615     p=DummyString;
    616     assert(s==0);
    617   }
    618 
    619   if (!(a = PyBytes_FromStringAndSize(p, s))) {
    620       return NULL;
    621   }
    622 
    623   r = Py_BuildValue("iO", i, a);
    624   Py_DECREF(a);
    625   return r;
    626 }
    627 
    628 static PyObject *BuildValue_LS(long l,const void *p,int s)
    629 {
    630   PyObject *a, *r;
    631 
    632   if (!p) {
    633     p=DummyString;
    634     assert(s==0);
    635   }
    636 
    637   if (!(a = PyBytes_FromStringAndSize(p, s))) {
    638       return NULL;
    639   }
    640 
    641   r = Py_BuildValue("lO", l, a);
    642   Py_DECREF(a);
    643   return r;
    644 }
    645 
    646 
    647 
    648 /* make a nice exception object to raise for errors. */
    649 static int makeDBError(int err)
    650 {
    651     char errTxt[2048];  /* really big, just in case... */
    652     PyObject *errObj = NULL;
    653     PyObject *errTuple = NULL;
    654     int exceptionRaised = 0;
    655     unsigned int bytes_left;
    656 
    657     switch (err) {
    658         case 0:                     /* successful, no error */
    659             return 0;
    660 
    661         case DB_KEYEMPTY:           errObj = DBKeyEmptyError;       break;
    662         case DB_KEYEXIST:           errObj = DBKeyExistError;       break;
    663         case DB_LOCK_DEADLOCK:      errObj = DBLockDeadlockError;   break;
    664         case DB_LOCK_NOTGRANTED:    errObj = DBLockNotGrantedError; break;
    665         case DB_NOTFOUND:           errObj = DBNotFoundError;       break;
    666         case DB_OLD_VERSION:        errObj = DBOldVersionError;     break;
    667         case DB_RUNRECOVERY:        errObj = DBRunRecoveryError;    break;
    668         case DB_VERIFY_BAD:         errObj = DBVerifyBadError;      break;
    669         case DB_NOSERVER:           errObj = DBNoServerError;       break;
    670 #if (DBVER < 52)
    671         case DB_NOSERVER_HOME:      errObj = DBNoServerHomeError;   break;
    672         case DB_NOSERVER_ID:        errObj = DBNoServerIDError;     break;
    673 #endif
    674         case DB_PAGE_NOTFOUND:      errObj = DBPageNotFoundError;   break;
    675         case DB_SECONDARY_BAD:      errObj = DBSecondaryBadError;   break;
    676         case DB_BUFFER_SMALL:       errObj = DBNoMemoryError;       break;
    677 
    678         case ENOMEM:  errObj = PyExc_MemoryError;   break;
    679         case EINVAL:  errObj = DBInvalidArgError;   break;
    680         case EACCES:  errObj = DBAccessError;       break;
    681         case ENOSPC:  errObj = DBNoSpaceError;      break;
    682         case EAGAIN:  errObj = DBAgainError;        break;
    683         case EBUSY :  errObj = DBBusyError;         break;
    684         case EEXIST:  errObj = DBFileExistsError;   break;
    685         case ENOENT:  errObj = DBNoSuchFileError;   break;
    686         case EPERM :  errObj = DBPermissionsError;  break;
    687 
    688         case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
    689 #if (DBVER >= 44)
    690         case DB_REP_LOCKOUT : errObj = DBRepLockoutError; break;
    691 #endif
    692 
    693 #if (DBVER >= 46)
    694         case DB_REP_LEASE_EXPIRED : errObj = DBRepLeaseExpiredError; break;
    695 #endif
    696 
    697 #if (DBVER >= 47)
    698         case DB_FOREIGN_CONFLICT : errObj = DBForeignConflictError; break;
    699 #endif
    700 
    701         case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
    702 
    703         default:      errObj = DBError;             break;
    704     }
    705 
    706     if (errObj != NULL) {
    707         bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
    708         /* Ensure that bytes_left never goes negative */
    709         if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
    710             bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
    711             assert(bytes_left >= 0);
    712             strcat(errTxt, " -- ");
    713             strncat(errTxt, _db_errmsg, bytes_left);
    714         }
    715         _db_errmsg[0] = 0;
    716 
    717         errTuple = Py_BuildValue("(is)", err, errTxt);
    718         if (errTuple == NULL) {
    719             Py_DECREF(errObj);
    720             return !0;
    721         }
    722         PyErr_SetObject(errObj, errTuple);
    723         Py_DECREF(errTuple);
    724     }
    725 
    726     return ((errObj != NULL) || exceptionRaised);
    727 }
    728 
    729 
    730 
    731 /* set a type exception */
    732 static void makeTypeError(char* expected, PyObject* found)
    733 {
    734     PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
    735                  expected, Py_TYPE(found)->tp_name);
    736 }
    737 
    738 
    739 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
    740 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
    741 {
    742     if (txnobj == Py_None || txnobj == NULL) {
    743         *txn = NULL;
    744         return 1;
    745     }
    746     if (DBTxnObject_Check(txnobj)) {
    747         *txn = ((DBTxnObject*)txnobj)->txn;
    748         return 1;
    749     }
    750     else
    751         makeTypeError("DBTxn", txnobj);
    752     return 0;
    753 }
    754 
    755 
    756 /* Delete a key from a database
    757   Returns 0 on success, -1 on an error.  */
    758 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
    759 {
    760     int err;
    761 
    762     MYDB_BEGIN_ALLOW_THREADS;
    763     err = self->db->del(self->db, txn, key, 0);
    764     MYDB_END_ALLOW_THREADS;
    765     if (makeDBError(err)) {
    766         return -1;
    767     }
    768     return 0;
    769 }
    770 
    771 
    772 /* Store a key into a database
    773    Returns 0 on success, -1 on an error.  */
    774 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
    775 {
    776     int err;
    777 
    778     MYDB_BEGIN_ALLOW_THREADS;
    779     err = self->db->put(self->db, txn, key, data, flags);
    780     MYDB_END_ALLOW_THREADS;
    781     if (makeDBError(err)) {
    782         return -1;
    783     }
    784     return 0;
    785 }
    786 
    787 /* Get a key/data pair from a cursor */
    788 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
    789                                PyObject *args, PyObject *kwargs, char *format)
    790 {
    791     int err;
    792     PyObject* retval = NULL;
    793     DBT key, data;
    794     int dlen = -1;
    795     int doff = -1;
    796     int flags = 0;
    797     static char* kwnames[] = { "flags", "dlen", "doff", NULL };
    798 
    799     if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
    800                                      &flags, &dlen, &doff))
    801       return NULL;
    802 
    803     CHECK_CURSOR_NOT_CLOSED(self);
    804 
    805     flags |= extra_flags;
    806     CLEAR_DBT(key);
    807     CLEAR_DBT(data);
    808     if (!add_partial_dbt(&data, dlen, doff))
    809         return NULL;
    810 
    811     MYDB_BEGIN_ALLOW_THREADS;
    812     err = _DBC_get(self->dbc, &key, &data, flags);
    813     MYDB_END_ALLOW_THREADS;
    814 
    815     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
    816             && self->mydb->moduleFlags.getReturnsNone) {
    817         Py_INCREF(Py_None);
    818         retval = Py_None;
    819     }
    820     else if (makeDBError(err)) {
    821         retval = NULL;
    822     }
    823     else {  /* otherwise, success! */
    824 
    825         /* if Recno or Queue, return the key as an Int */
    826         switch (_DB_get_type(self->mydb)) {
    827         case -1:
    828             retval = NULL;
    829             break;
    830 
    831         case DB_RECNO:
    832         case DB_QUEUE:
    833             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
    834             break;
    835         case DB_HASH:
    836         case DB_BTREE:
    837         default:
    838             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
    839             break;
    840         }
    841     }
    842     return retval;
    843 }
    844 
    845 
    846 /* add an integer to a dictionary using the given name as a key */
    847 static void _addIntToDict(PyObject* dict, char *name, int value)
    848 {
    849     PyObject* v = NUMBER_FromLong((long) value);
    850     if (!v || PyDict_SetItemString(dict, name, v))
    851         PyErr_Clear();
    852 
    853     Py_XDECREF(v);
    854 }
    855 
    856 /* The same, when the value is a time_t */
    857 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
    858 {
    859     PyObject* v;
    860         /* if the value fits in regular int, use that. */
    861 #ifdef PY_LONG_LONG
    862         if (sizeof(time_t) > sizeof(long))
    863                 v = PyLong_FromLongLong((PY_LONG_LONG) value);
    864         else
    865 #endif
    866                 v = NUMBER_FromLong((long) value);
    867     if (!v || PyDict_SetItemString(dict, name, v))
    868         PyErr_Clear();
    869 
    870     Py_XDECREF(v);
    871 }
    872 
    873 /* add an db_seq_t to a dictionary using the given name as a key */
    874 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
    875 {
    876     PyObject* v = PyLong_FromLongLong(value);
    877     if (!v || PyDict_SetItemString(dict, name, v))
    878         PyErr_Clear();
    879 
    880     Py_XDECREF(v);
    881 }
    882 
    883 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
    884 {
    885     PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
    886     if (!v || PyDict_SetItemString(dict, name, v))
    887         PyErr_Clear();
    888 
    889     Py_XDECREF(v);
    890 }
    891 
    892 /* --------------------------------------------------------------------- */
    893 /* Allocators and deallocators */
    894 
    895 static DBObject*
    896 newDBObject(DBEnvObject* arg, int flags)
    897 {
    898     DBObject* self;
    899     DB_ENV* db_env = NULL;
    900     int err;
    901 
    902     self = PyObject_New(DBObject, &DB_Type);
    903     if (self == NULL)
    904         return NULL;
    905 
    906     self->flags = 0;
    907     self->setflags = 0;
    908     self->myenvobj = NULL;
    909     self->db = NULL;
    910     self->children_cursors = NULL;
    911     self->children_sequences = NULL;
    912     self->associateCallback = NULL;
    913     self->btCompareCallback = NULL;
    914     self->dupCompareCallback = NULL;
    915     self->primaryDBType = 0;
    916     Py_INCREF(Py_None);
    917     self->private_obj = Py_None;
    918     self->in_weakreflist = NULL;
    919 
    920     /* keep a reference to our python DBEnv object */
    921     if (arg) {
    922         Py_INCREF(arg);
    923         self->myenvobj = arg;
    924         db_env = arg->db_env;
    925         INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
    926     } else {
    927       self->sibling_prev_p=NULL;
    928       self->sibling_next=NULL;
    929     }
    930     self->txn=NULL;
    931     self->sibling_prev_p_txn=NULL;
    932     self->sibling_next_txn=NULL;
    933 
    934     if (self->myenvobj)
    935         self->moduleFlags = self->myenvobj->moduleFlags;
    936     else
    937         self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
    938         self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
    939 
    940     MYDB_BEGIN_ALLOW_THREADS;
    941     err = db_create(&self->db, db_env, flags);
    942     if (self->db != NULL) {
    943         self->db->set_errcall(self->db, _db_errorCallback);
    944         self->db->app_private = (void*)self;
    945     }
    946     MYDB_END_ALLOW_THREADS;
    947     /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
    948      * list so that a DBEnv can refuse to close without aborting any open
    949      * DBTxns and closing any open DBs first. */
    950     if (makeDBError(err)) {
    951         if (self->myenvobj) {
    952             Py_CLEAR(self->myenvobj);
    953         }
    954         Py_DECREF(self);
    955         self = NULL;
    956     }
    957     return self;
    958 }
    959 
    960 
    961 /* Forward declaration */
    962 static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
    963 
    964 static void
    965 DB_dealloc(DBObject* self)
    966 {
    967   PyObject *dummy;
    968 
    969     if (self->db != NULL) {
    970         dummy=DB_close_internal(self, 0, 0);
    971         /*
    972         ** Raising exceptions while doing
    973         ** garbage collection is a fatal error.
    974         */
    975         if (dummy)
    976             Py_DECREF(dummy);
    977         else
    978             PyErr_Clear();
    979     }
    980     if (self->in_weakreflist != NULL) {
    981         PyObject_ClearWeakRefs((PyObject *) self);
    982     }
    983     if (self->myenvobj) {
    984         Py_CLEAR(self->myenvobj);
    985     }
    986     if (self->associateCallback != NULL) {
    987         Py_CLEAR(self->associateCallback);
    988     }
    989     if (self->btCompareCallback != NULL) {
    990         Py_CLEAR(self->btCompareCallback);
    991     }
    992     if (self->dupCompareCallback != NULL) {
    993         Py_CLEAR(self->dupCompareCallback);
    994     }
    995     Py_DECREF(self->private_obj);
    996     PyObject_Del(self);
    997 }
    998 
    999 static DBCursorObject*
   1000 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
   1001 {
   1002     DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
   1003     if (self == NULL)
   1004         return NULL;
   1005 
   1006     self->dbc = dbc;
   1007     self->mydb = db;
   1008 
   1009     INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
   1010     if (txn && ((PyObject *)txn!=Py_None)) {
   1011             INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
   1012             self->txn=txn;
   1013     } else {
   1014             self->txn=NULL;
   1015     }
   1016 
   1017     self->in_weakreflist = NULL;
   1018     Py_INCREF(self->mydb);
   1019     return self;
   1020 }
   1021 
   1022 
   1023 /* Forward declaration */
   1024 static PyObject *DBC_close_internal(DBCursorObject* self);
   1025 
   1026 static void
   1027 DBCursor_dealloc(DBCursorObject* self)
   1028 {
   1029     PyObject *dummy;
   1030 
   1031     if (self->dbc != NULL) {
   1032         dummy=DBC_close_internal(self);
   1033         /*
   1034         ** Raising exceptions while doing
   1035         ** garbage collection is a fatal error.
   1036         */
   1037         if (dummy)
   1038             Py_DECREF(dummy);
   1039         else
   1040             PyErr_Clear();
   1041     }
   1042     if (self->in_weakreflist != NULL) {
   1043         PyObject_ClearWeakRefs((PyObject *) self);
   1044     }
   1045     Py_DECREF(self->mydb);
   1046     PyObject_Del(self);
   1047 }
   1048 
   1049 
   1050 static DBLogCursorObject*
   1051 newDBLogCursorObject(DB_LOGC* dblogc, DBEnvObject* env)
   1052 {
   1053     DBLogCursorObject* self;
   1054 
   1055     self = PyObject_New(DBLogCursorObject, &DBLogCursor_Type);
   1056 
   1057     if (self == NULL)
   1058         return NULL;
   1059 
   1060     self->logc = dblogc;
   1061     self->env = env;
   1062 
   1063     INSERT_IN_DOUBLE_LINKED_LIST(self->env->children_logcursors, self);
   1064 
   1065     self->in_weakreflist = NULL;
   1066     Py_INCREF(self->env);
   1067     return self;
   1068 }
   1069 
   1070 
   1071 /* Forward declaration */
   1072 static PyObject *DBLogCursor_close_internal(DBLogCursorObject* self);
   1073 
   1074 static void
   1075 DBLogCursor_dealloc(DBLogCursorObject* self)
   1076 {
   1077     PyObject *dummy;
   1078 
   1079     if (self->logc != NULL) {
   1080         dummy = DBLogCursor_close_internal(self);
   1081         /*
   1082         ** Raising exceptions while doing
   1083         ** garbage collection is a fatal error.
   1084         */
   1085         if (dummy)
   1086             Py_DECREF(dummy);
   1087         else
   1088             PyErr_Clear();
   1089     }
   1090     if (self->in_weakreflist != NULL) {
   1091         PyObject_ClearWeakRefs((PyObject *) self);
   1092     }
   1093     Py_DECREF(self->env);
   1094     PyObject_Del(self);
   1095 }
   1096 
   1097 
   1098 static DBEnvObject*
   1099 newDBEnvObject(int flags)
   1100 {
   1101     int err;
   1102     DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
   1103     if (self == NULL)
   1104         return NULL;
   1105 
   1106     self->db_env = NULL;
   1107     self->closed = 1;
   1108     self->flags = flags;
   1109     self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
   1110     self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
   1111     self->children_dbs = NULL;
   1112     self->children_txns = NULL;
   1113     self->children_logcursors = NULL ;
   1114 #if (DBVER >= 52)
   1115     self->children_sites = NULL;
   1116 #endif
   1117     Py_INCREF(Py_None);
   1118     self->private_obj = Py_None;
   1119     Py_INCREF(Py_None);
   1120     self->rep_transport = Py_None;
   1121     self->in_weakreflist = NULL;
   1122     self->event_notifyCallback = NULL;
   1123 
   1124     MYDB_BEGIN_ALLOW_THREADS;
   1125     err = db_env_create(&self->db_env, flags);
   1126     MYDB_END_ALLOW_THREADS;
   1127     if (makeDBError(err)) {
   1128         Py_DECREF(self);
   1129         self = NULL;
   1130     }
   1131     else {
   1132         self->db_env->set_errcall(self->db_env, _db_errorCallback);
   1133         self->db_env->app_private = self;
   1134     }
   1135     return self;
   1136 }
   1137 
   1138 /* Forward declaration */
   1139 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
   1140 
   1141 static void
   1142 DBEnv_dealloc(DBEnvObject* self)
   1143 {
   1144   PyObject *dummy;
   1145 
   1146     if (self->db_env) {
   1147         dummy=DBEnv_close_internal(self, 0);
   1148         /*
   1149         ** Raising exceptions while doing
   1150         ** garbage collection is a fatal error.
   1151         */
   1152         if (dummy)
   1153             Py_DECREF(dummy);
   1154         else
   1155             PyErr_Clear();
   1156     }
   1157 
   1158     Py_CLEAR(self->event_notifyCallback);
   1159 
   1160     if (self->in_weakreflist != NULL) {
   1161         PyObject_ClearWeakRefs((PyObject *) self);
   1162     }
   1163     Py_DECREF(self->private_obj);
   1164     Py_DECREF(self->rep_transport);
   1165     PyObject_Del(self);
   1166 }
   1167 
   1168 
   1169 static DBTxnObject*
   1170 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
   1171 {
   1172     int err;
   1173     DB_TXN *parent_txn = NULL;
   1174 
   1175     DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
   1176     if (self == NULL)
   1177         return NULL;
   1178 
   1179     self->in_weakreflist = NULL;
   1180     self->children_txns = NULL;
   1181     self->children_dbs = NULL;
   1182     self->children_cursors = NULL;
   1183     self->children_sequences = NULL;
   1184     self->flag_prepare = 0;
   1185     self->parent_txn = NULL;
   1186     self->env = NULL;
   1187     /* We initialize just in case "txn_begin" fails */
   1188     self->txn = NULL;
   1189 
   1190     if (parent && ((PyObject *)parent!=Py_None)) {
   1191         parent_txn = parent->txn;
   1192     }
   1193 
   1194     if (txn) {
   1195         self->txn = txn;
   1196     } else {
   1197         MYDB_BEGIN_ALLOW_THREADS;
   1198         err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
   1199         MYDB_END_ALLOW_THREADS;
   1200 
   1201         if (makeDBError(err)) {
   1202             /* Free object half initialized */
   1203             Py_DECREF(self);
   1204             return NULL;
   1205         }
   1206     }
   1207 
   1208     /* Can't use 'parent' because could be 'parent==Py_None' */
   1209     if (parent_txn) {
   1210         self->parent_txn = parent;
   1211         Py_INCREF(parent);
   1212         self->env = NULL;
   1213         INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
   1214     } else {
   1215         self->parent_txn = NULL;
   1216         Py_INCREF(myenv);
   1217         self->env = myenv;
   1218         INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
   1219     }
   1220 
   1221     return self;
   1222 }
   1223 
   1224 /* Forward declaration */
   1225 static PyObject *
   1226 DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
   1227 
   1228 static void
   1229 DBTxn_dealloc(DBTxnObject* self)
   1230 {
   1231   PyObject *dummy;
   1232 
   1233     if (self->txn) {
   1234         int flag_prepare = self->flag_prepare;
   1235 
   1236         dummy=DBTxn_abort_discard_internal(self, 0);
   1237         /*
   1238         ** Raising exceptions while doing
   1239         ** garbage collection is a fatal error.
   1240         */
   1241         if (dummy)
   1242             Py_DECREF(dummy);
   1243         else
   1244             PyErr_Clear();
   1245 
   1246         if (!flag_prepare) {
   1247             PyErr_Warn(PyExc_RuntimeWarning,
   1248               "DBTxn aborted in destructor.  No prior commit() or abort().");
   1249         }
   1250     }
   1251 
   1252     if (self->in_weakreflist != NULL) {
   1253         PyObject_ClearWeakRefs((PyObject *) self);
   1254     }
   1255 
   1256     if (self->env) {
   1257         Py_DECREF(self->env);
   1258     } else {
   1259         /*
   1260         ** We can have "self->env==NULL" and "self->parent_txn==NULL"
   1261         ** if something happens when creating the transaction object
   1262         ** and we abort the object while half done.
   1263         */
   1264         Py_XDECREF(self->parent_txn);
   1265     }
   1266     PyObject_Del(self);
   1267 }
   1268 
   1269 
   1270 static DBLockObject*
   1271 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
   1272                 db_lockmode_t lock_mode, int flags)
   1273 {
   1274     int err;
   1275     DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
   1276     if (self == NULL)
   1277         return NULL;
   1278     self->in_weakreflist = NULL;
   1279     self->lock_initialized = 0;  /* Just in case the call fails */
   1280 
   1281     MYDB_BEGIN_ALLOW_THREADS;
   1282     err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
   1283                                   &self->lock);
   1284     MYDB_END_ALLOW_THREADS;
   1285     if (makeDBError(err)) {
   1286         Py_DECREF(self);
   1287         self = NULL;
   1288     } else {
   1289         self->lock_initialized = 1;
   1290     }
   1291 
   1292     return self;
   1293 }
   1294 
   1295 
   1296 static void
   1297 DBLock_dealloc(DBLockObject* self)
   1298 {
   1299     if (self->in_weakreflist != NULL) {
   1300         PyObject_ClearWeakRefs((PyObject *) self);
   1301     }
   1302     /* TODO: is this lock held? should we release it? */
   1303     /* CAUTION: The lock can be not initialized if the creation has failed */
   1304 
   1305     PyObject_Del(self);
   1306 }
   1307 
   1308 
   1309 static DBSequenceObject*
   1310 newDBSequenceObject(DBObject* mydb,  int flags)
   1311 {
   1312     int err;
   1313     DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
   1314     if (self == NULL)
   1315         return NULL;
   1316     Py_INCREF(mydb);
   1317     self->mydb = mydb;
   1318 
   1319     INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
   1320     self->txn = NULL;
   1321 
   1322     self->in_weakreflist = NULL;
   1323     self->sequence = NULL;  /* Just in case the call fails */
   1324 
   1325     MYDB_BEGIN_ALLOW_THREADS;
   1326     err = db_sequence_create(&self->sequence, self->mydb->db, flags);
   1327     MYDB_END_ALLOW_THREADS;
   1328     if (makeDBError(err)) {
   1329         Py_DECREF(self);
   1330         self = NULL;
   1331     }
   1332 
   1333     return self;
   1334 }
   1335 
   1336 /* Forward declaration */
   1337 static PyObject
   1338 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
   1339 
   1340 static void
   1341 DBSequence_dealloc(DBSequenceObject* self)
   1342 {
   1343     PyObject *dummy;
   1344 
   1345     if (self->sequence != NULL) {
   1346         dummy=DBSequence_close_internal(self,0,0);
   1347         /*
   1348         ** Raising exceptions while doing
   1349         ** garbage collection is a fatal error.
   1350         */
   1351         if (dummy)
   1352             Py_DECREF(dummy);
   1353         else
   1354             PyErr_Clear();
   1355     }
   1356 
   1357     if (self->in_weakreflist != NULL) {
   1358         PyObject_ClearWeakRefs((PyObject *) self);
   1359     }
   1360 
   1361     Py_DECREF(self->mydb);
   1362     PyObject_Del(self);
   1363 }
   1364 
   1365 #if (DBVER >= 52)
   1366 static DBSiteObject*
   1367 newDBSiteObject(DB_SITE* sitep, DBEnvObject* env)
   1368 {
   1369     DBSiteObject* self;
   1370 
   1371     self = PyObject_New(DBSiteObject, &DBSite_Type);
   1372 
   1373     if (self == NULL)
   1374         return NULL;
   1375 
   1376     self->site = sitep;
   1377     self->env = env;
   1378 
   1379     INSERT_IN_DOUBLE_LINKED_LIST(self->env->children_sites, self);
   1380 
   1381     self->in_weakreflist = NULL;
   1382     Py_INCREF(self->env);
   1383     return self;
   1384 }
   1385 
   1386 /* Forward declaration */
   1387 static PyObject *DBSite_close_internal(DBSiteObject* self);
   1388 
   1389 static void
   1390 DBSite_dealloc(DBSiteObject* self)
   1391 {
   1392     PyObject *dummy;
   1393 
   1394     if (self->site != NULL) {
   1395         dummy = DBSite_close_internal(self);
   1396         /*
   1397         ** Raising exceptions while doing
   1398         ** garbage collection is a fatal error.
   1399         */
   1400         if (dummy)
   1401             Py_DECREF(dummy);
   1402         else
   1403             PyErr_Clear();
   1404     }
   1405     if (self->in_weakreflist != NULL) {
   1406         PyObject_ClearWeakRefs((PyObject *) self);
   1407     }
   1408     Py_DECREF(self->env);
   1409     PyObject_Del(self);
   1410 }
   1411 #endif
   1412 
   1413 /* --------------------------------------------------------------------- */
   1414 /* DB methods */
   1415 
   1416 static PyObject*
   1417 DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
   1418 {
   1419     PyObject* txnobj = NULL;
   1420     PyObject* dataobj;
   1421     db_recno_t recno;
   1422     DBT key, data;
   1423     DB_TXN *txn = NULL;
   1424     static char* kwnames[] = { "data", "txn", NULL };
   1425 
   1426     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
   1427                                      &dataobj, &txnobj))
   1428         return NULL;
   1429 
   1430     CHECK_DB_NOT_CLOSED(self);
   1431 
   1432     /* make a dummy key out of a recno */
   1433     recno = 0;
   1434     CLEAR_DBT(key);
   1435     key.data = &recno;
   1436     key.size = sizeof(recno);
   1437     key.ulen = key.size;
   1438     key.flags = DB_DBT_USERMEM;
   1439 
   1440     if (!make_dbt(dataobj, &data)) return NULL;
   1441     if (!checkTxnObj(txnobj, &txn)) return NULL;
   1442 
   1443     if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
   1444         return NULL;
   1445 
   1446     return NUMBER_FromLong(recno);
   1447 }
   1448 
   1449 
   1450 static int
   1451 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
   1452                       DBT* secKey)
   1453 {
   1454     int       retval = DB_DONOTINDEX;
   1455     DBObject* secondaryDB = (DBObject*)db->app_private;
   1456     PyObject* callback = secondaryDB->associateCallback;
   1457     int       type = secondaryDB->primaryDBType;
   1458     PyObject* args;
   1459     PyObject* result = NULL;
   1460 
   1461 
   1462     if (callback != NULL) {
   1463         MYDB_BEGIN_BLOCK_THREADS;
   1464 
   1465         if (type == DB_RECNO || type == DB_QUEUE)
   1466             args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
   1467         else
   1468             args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
   1469         if (args != NULL) {
   1470                 result = PyEval_CallObject(callback, args);
   1471         }
   1472         if (args == NULL || result == NULL) {
   1473             PyErr_Print();
   1474         }
   1475         else if (result == Py_None) {
   1476             retval = DB_DONOTINDEX;
   1477         }
   1478         else if (NUMBER_Check(result)) {
   1479             retval = NUMBER_AsLong(result);
   1480         }
   1481         else if (PyBytes_Check(result)) {
   1482             char* data;
   1483             Py_ssize_t size;
   1484 
   1485             CLEAR_DBT(*secKey);
   1486             PyBytes_AsStringAndSize(result, &data, &size);
   1487             secKey->flags = DB_DBT_APPMALLOC;   /* DB will free */
   1488             secKey->data = malloc(size);        /* TODO, check this */
   1489             if (secKey->data) {
   1490                 memcpy(secKey->data, data, size);
   1491                 secKey->size = size;
   1492                 retval = 0;
   1493             }
   1494             else {
   1495                 PyErr_SetString(PyExc_MemoryError,
   1496                                 "malloc failed in _db_associateCallback");
   1497                 PyErr_Print();
   1498             }
   1499         }
   1500 #if (DBVER >= 46)
   1501         else if (PyList_Check(result))
   1502         {
   1503             char* data;
   1504             Py_ssize_t size;
   1505             int i, listlen;
   1506             DBT* dbts;
   1507 
   1508             listlen = PyList_Size(result);
   1509 
   1510             dbts = (DBT *)malloc(sizeof(DBT) * listlen);
   1511 
   1512             for (i=0; i<listlen; i++)
   1513             {
   1514                 if (!PyBytes_Check(PyList_GetItem(result, i)))
   1515                 {
   1516                     PyErr_SetString(
   1517                        PyExc_TypeError,
   1518 #if (PY_VERSION_HEX < 0x03000000)
   1519 "The list returned by DB->associate callback should be a list of strings.");
   1520 #else
   1521 "The list returned by DB->associate callback should be a list of bytes.");
   1522 #endif
   1523                     PyErr_Print();
   1524                 }
   1525 
   1526                 PyBytes_AsStringAndSize(
   1527                     PyList_GetItem(result, i),
   1528                     &data, &size);
   1529 
   1530                 CLEAR_DBT(dbts[i]);
   1531                 dbts[i].data = malloc(size);          /* TODO, check this */
   1532 
   1533                 if (dbts[i].data)
   1534                 {
   1535                     memcpy(dbts[i].data, data, size);
   1536                     dbts[i].size = size;
   1537                     dbts[i].ulen = dbts[i].size;
   1538                     dbts[i].flags = DB_DBT_APPMALLOC;  /* DB will free */
   1539                 }
   1540                 else
   1541                 {
   1542                     PyErr_SetString(PyExc_MemoryError,
   1543                         "malloc failed in _db_associateCallback (list)");
   1544                     PyErr_Print();
   1545                 }
   1546             }
   1547 
   1548             CLEAR_DBT(*secKey);
   1549 
   1550             secKey->data = dbts;
   1551             secKey->size = listlen;
   1552             secKey->flags = DB_DBT_APPMALLOC | DB_DBT_MULTIPLE;
   1553             retval = 0;
   1554         }
   1555 #endif
   1556         else {
   1557             PyErr_SetString(
   1558                PyExc_TypeError,
   1559 #if (PY_VERSION_HEX < 0x03000000)
   1560 "DB associate callback should return DB_DONOTINDEX/string/list of strings.");
   1561 #else
   1562 "DB associate callback should return DB_DONOTINDEX/bytes/list of bytes.");
   1563 #endif
   1564             PyErr_Print();
   1565         }
   1566 
   1567         Py_XDECREF(args);
   1568         Py_XDECREF(result);
   1569 
   1570         MYDB_END_BLOCK_THREADS;
   1571     }
   1572     return retval;
   1573 }
   1574 
   1575 
   1576 static PyObject*
   1577 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
   1578 {
   1579     int err, flags=0;
   1580     DBObject* secondaryDB;
   1581     PyObject* callback;
   1582     PyObject *txnobj = NULL;
   1583     DB_TXN *txn = NULL;
   1584     static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
   1585                                     NULL};
   1586 
   1587     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
   1588                                      &secondaryDB, &callback, &flags,
   1589                                      &txnobj)) {
   1590         return NULL;
   1591     }
   1592 
   1593     if (!checkTxnObj(txnobj, &txn)) return NULL;
   1594 
   1595     CHECK_DB_NOT_CLOSED(self);
   1596     if (!DBObject_Check(secondaryDB)) {
   1597         makeTypeError("DB", (PyObject*)secondaryDB);
   1598         return NULL;
   1599     }
   1600     CHECK_DB_NOT_CLOSED(secondaryDB);
   1601     if (callback == Py_None) {
   1602         callback = NULL;
   1603     }
   1604     else if (!PyCallable_Check(callback)) {
   1605         makeTypeError("Callable", callback);
   1606         return NULL;
   1607     }
   1608 
   1609     /* Save a reference to the callback in the secondary DB. */
   1610     Py_XINCREF(callback);
   1611     Py_XSETREF(secondaryDB->associateCallback, callback);
   1612     secondaryDB->primaryDBType = _DB_get_type(self);
   1613 
   1614     /* PyEval_InitThreads is called here due to a quirk in python 1.5
   1615      * - 2.2.1 (at least) according to Russell Williamson <merel (at) wt.net>:
   1616      * The global interepreter lock is not initialized until the first
   1617      * thread is created using thread.start_new_thread() or fork() is
   1618      * called.  that would cause the ALLOW_THREADS here to segfault due
   1619      * to a null pointer reference if no threads or child processes
   1620      * have been created.  This works around that and is a no-op if
   1621      * threads have already been initialized.
   1622      *  (see pybsddb-users mailing list post on 2002-08-07)
   1623      */
   1624 #ifdef WITH_THREAD
   1625     PyEval_InitThreads();
   1626 #endif
   1627     MYDB_BEGIN_ALLOW_THREADS;
   1628     err = self->db->associate(self->db,
   1629                               txn,
   1630                               secondaryDB->db,
   1631                               _db_associateCallback,
   1632                               flags);
   1633     MYDB_END_ALLOW_THREADS;
   1634 
   1635     if (err) {
   1636         Py_CLEAR(secondaryDB->associateCallback);
   1637         secondaryDB->primaryDBType = 0;
   1638     }
   1639 
   1640     RETURN_IF_ERR();
   1641     RETURN_NONE();
   1642 }
   1643 
   1644 
   1645 static PyObject*
   1646 DB_close_internal(DBObject* self, int flags, int do_not_close)
   1647 {
   1648     PyObject *dummy;
   1649     int err = 0;
   1650 
   1651     if (self->db != NULL) {
   1652         /* Can be NULL if db is not in an environment */
   1653         EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
   1654 
   1655         if (self->txn) {
   1656             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
   1657             self->txn=NULL;
   1658         }
   1659 
   1660         while(self->children_cursors) {
   1661           dummy=DBC_close_internal(self->children_cursors);
   1662           Py_XDECREF(dummy);
   1663         }
   1664 
   1665         while(self->children_sequences) {
   1666             dummy=DBSequence_close_internal(self->children_sequences,0,0);
   1667             Py_XDECREF(dummy);
   1668         }
   1669 
   1670         /*
   1671         ** "do_not_close" is used to dispose all related objects in the
   1672         ** tree, without actually releasing the "root" object.
   1673         ** This is done, for example, because function calls like
   1674         ** "DB.verify()" implicitly close the underlying handle. So
   1675         ** the handle doesn't need to be closed, but related objects
   1676         ** must be cleaned up.
   1677         */
   1678         if (!do_not_close) {
   1679             MYDB_BEGIN_ALLOW_THREADS;
   1680             err = self->db->close(self->db, flags);
   1681             MYDB_END_ALLOW_THREADS;
   1682             self->db = NULL;
   1683         }
   1684         RETURN_IF_ERR();
   1685     }
   1686     RETURN_NONE();
   1687 }
   1688 
   1689 static PyObject*
   1690 DB_close(DBObject* self, PyObject* args)
   1691 {
   1692     int flags=0;
   1693     if (!PyArg_ParseTuple(args,"|i:close", &flags))
   1694         return NULL;
   1695     return DB_close_internal(self, flags, 0);
   1696 }
   1697 
   1698 
   1699 static PyObject*
   1700 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
   1701 {
   1702     int err, flags=0, type;
   1703     PyObject* txnobj = NULL;
   1704     PyObject* retval = NULL;
   1705     DBT key, data;
   1706     DB_TXN *txn = NULL;
   1707     static char* kwnames[] = { "txn", "flags", NULL };
   1708 
   1709     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
   1710                                      &txnobj, &flags))
   1711         return NULL;
   1712 
   1713     CHECK_DB_NOT_CLOSED(self);
   1714     type = _DB_get_type(self);
   1715     if (type == -1)
   1716         return NULL;
   1717     if (type != DB_QUEUE) {
   1718         PyErr_SetString(PyExc_TypeError,
   1719                         "Consume methods only allowed for Queue DB's");
   1720         return NULL;
   1721     }
   1722     if (!checkTxnObj(txnobj, &txn))
   1723         return NULL;
   1724 
   1725     CLEAR_DBT(key);
   1726     CLEAR_DBT(data);
   1727     if (CHECK_DBFLAG(self, DB_THREAD)) {
   1728         /* Tell Berkeley DB to malloc the return value (thread safe) */
   1729         data.flags = DB_DBT_MALLOC;
   1730         key.flags = DB_DBT_MALLOC;
   1731     }
   1732 
   1733     MYDB_BEGIN_ALLOW_THREADS;
   1734     err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
   1735     MYDB_END_ALLOW_THREADS;
   1736 
   1737     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   1738             && self->moduleFlags.getReturnsNone) {
   1739         err = 0;
   1740         Py_INCREF(Py_None);
   1741         retval = Py_None;
   1742     }
   1743     else if (!err) {
   1744         retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   1745         FREE_DBT(key);
   1746         FREE_DBT(data);
   1747     }
   1748 
   1749     RETURN_IF_ERR();
   1750     return retval;
   1751 }
   1752 
   1753 static PyObject*
   1754 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
   1755 {
   1756     return _DB_consume(self, args, kwargs, DB_CONSUME);
   1757 }
   1758 
   1759 static PyObject*
   1760 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
   1761                 int consume_flag)
   1762 {
   1763     return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
   1764 }
   1765 
   1766 
   1767 static PyObject*
   1768 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
   1769 {
   1770     int err, flags=0;
   1771     DBC* dbc;
   1772     PyObject* txnobj = NULL;
   1773     DB_TXN *txn = NULL;
   1774     static char* kwnames[] = { "txn", "flags", NULL };
   1775 
   1776     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
   1777                                      &txnobj, &flags))
   1778         return NULL;
   1779     CHECK_DB_NOT_CLOSED(self);
   1780     if (!checkTxnObj(txnobj, &txn))
   1781         return NULL;
   1782 
   1783     MYDB_BEGIN_ALLOW_THREADS;
   1784     err = self->db->cursor(self->db, txn, &dbc, flags);
   1785     MYDB_END_ALLOW_THREADS;
   1786     RETURN_IF_ERR();
   1787     return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
   1788 }
   1789 
   1790 
   1791 static PyObject*
   1792 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
   1793 {
   1794     PyObject* txnobj = NULL;
   1795     int flags = 0;
   1796     PyObject* keyobj;
   1797     DBT key;
   1798     DB_TXN *txn = NULL;
   1799     static char* kwnames[] = { "key", "txn", "flags", NULL };
   1800 
   1801     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
   1802                                      &keyobj, &txnobj, &flags))
   1803         return NULL;
   1804     CHECK_DB_NOT_CLOSED(self);
   1805     if (!make_key_dbt(self, keyobj, &key, NULL))
   1806         return NULL;
   1807     if (!checkTxnObj(txnobj, &txn)) {
   1808         FREE_DBT(key);
   1809         return NULL;
   1810     }
   1811 
   1812     if (-1 == _DB_delete(self, txn, &key, 0)) {
   1813         FREE_DBT(key);
   1814         return NULL;
   1815     }
   1816 
   1817     FREE_DBT(key);
   1818     RETURN_NONE();
   1819 }
   1820 
   1821 
   1822 #if (DBVER >= 47)
   1823 /*
   1824 ** This function is available since Berkeley DB 4.4,
   1825 ** but 4.6 version is so buggy that we only support
   1826 ** it from BDB 4.7 and newer.
   1827 */
   1828 static PyObject*
   1829 DB_compact(DBObject* self, PyObject* args, PyObject* kwargs)
   1830 {
   1831     PyObject* txnobj = NULL;
   1832     PyObject *startobj = NULL, *stopobj = NULL;
   1833     int flags = 0;
   1834     DB_TXN *txn = NULL;
   1835     DBT *start_p = NULL, *stop_p = NULL;
   1836     DBT start, stop;
   1837     int err;
   1838     DB_COMPACT c_data = { 0 };
   1839     static char* kwnames[] = { "txn", "start", "stop", "flags",
   1840                                "compact_fillpercent", "compact_pages",
   1841                                "compact_timeout", NULL };
   1842 
   1843 
   1844     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOiiiI:compact", kwnames,
   1845                                      &txnobj, &startobj, &stopobj, &flags,
   1846                                      &c_data.compact_fillpercent,
   1847                                      &c_data.compact_pages,
   1848                                      &c_data.compact_timeout))
   1849         return NULL;
   1850 
   1851     CHECK_DB_NOT_CLOSED(self);
   1852     if (!checkTxnObj(txnobj, &txn)) {
   1853         return NULL;
   1854     }
   1855 
   1856     if (startobj && make_key_dbt(self, startobj, &start, NULL)) {
   1857         start_p = &start;
   1858     }
   1859     if (stopobj && make_key_dbt(self, stopobj, &stop, NULL)) {
   1860         stop_p = &stop;
   1861     }
   1862 
   1863     MYDB_BEGIN_ALLOW_THREADS;
   1864     err = self->db->compact(self->db, txn, start_p, stop_p, &c_data,
   1865                             flags, NULL);
   1866     MYDB_END_ALLOW_THREADS;
   1867 
   1868     if (startobj)
   1869         FREE_DBT(start);
   1870     if (stopobj)
   1871         FREE_DBT(stop);
   1872 
   1873     RETURN_IF_ERR();
   1874 
   1875     return PyLong_FromUnsignedLong(c_data.compact_pages_truncated);
   1876 }
   1877 #endif
   1878 
   1879 
   1880 static PyObject*
   1881 DB_fd(DBObject* self)
   1882 {
   1883     int err, the_fd;
   1884 
   1885     CHECK_DB_NOT_CLOSED(self);
   1886 
   1887     MYDB_BEGIN_ALLOW_THREADS;
   1888     err = self->db->fd(self->db, &the_fd);
   1889     MYDB_END_ALLOW_THREADS;
   1890     RETURN_IF_ERR();
   1891     return NUMBER_FromLong(the_fd);
   1892 }
   1893 
   1894 
   1895 #if (DBVER >= 46)
   1896 static PyObject*
   1897 DB_exists(DBObject* self, PyObject* args, PyObject* kwargs)
   1898 {
   1899     int err, flags=0;
   1900     PyObject* txnobj = NULL;
   1901     PyObject* keyobj;
   1902     DBT key;
   1903     DB_TXN *txn;
   1904 
   1905     static char* kwnames[] = {"key", "txn", "flags", NULL};
   1906 
   1907     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:exists", kwnames,
   1908                 &keyobj, &txnobj, &flags))
   1909         return NULL;
   1910 
   1911     CHECK_DB_NOT_CLOSED(self);
   1912     if (!make_key_dbt(self, keyobj, &key, NULL))
   1913         return NULL;
   1914     if (!checkTxnObj(txnobj, &txn)) {
   1915         FREE_DBT(key);
   1916         return NULL;
   1917     }
   1918 
   1919     MYDB_BEGIN_ALLOW_THREADS;
   1920     err = self->db->exists(self->db, txn, &key, flags);
   1921     MYDB_END_ALLOW_THREADS;
   1922 
   1923     FREE_DBT(key);
   1924 
   1925     if (!err) {
   1926         Py_INCREF(Py_True);
   1927         return Py_True;
   1928     }
   1929     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)) {
   1930         Py_INCREF(Py_False);
   1931         return Py_False;
   1932     }
   1933 
   1934     /*
   1935     ** If we reach there, there was an error. The
   1936     ** "return" should be unreachable.
   1937     */
   1938     RETURN_IF_ERR();
   1939     assert(0);  /* This coude SHOULD be unreachable */
   1940     return NULL;
   1941 }
   1942 #endif
   1943 
   1944 static PyObject*
   1945 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
   1946 {
   1947     int err, flags=0;
   1948     PyObject* txnobj = NULL;
   1949     PyObject* keyobj;
   1950     PyObject* dfltobj = NULL;
   1951     PyObject* retval = NULL;
   1952     int dlen = -1;
   1953     int doff = -1;
   1954     DBT key, data;
   1955     DB_TXN *txn = NULL;
   1956     static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
   1957                                     "doff", NULL};
   1958 
   1959     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
   1960                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen,
   1961                                      &doff))
   1962         return NULL;
   1963 
   1964     CHECK_DB_NOT_CLOSED(self);
   1965     if (!make_key_dbt(self, keyobj, &key, &flags))
   1966         return NULL;
   1967     if (!checkTxnObj(txnobj, &txn)) {
   1968         FREE_DBT(key);
   1969         return NULL;
   1970     }
   1971 
   1972     CLEAR_DBT(data);
   1973     if (CHECK_DBFLAG(self, DB_THREAD)) {
   1974         /* Tell Berkeley DB to malloc the return value (thread safe) */
   1975         data.flags = DB_DBT_MALLOC;
   1976     }
   1977     if (!add_partial_dbt(&data, dlen, doff)) {
   1978         FREE_DBT(key);
   1979         return NULL;
   1980     }
   1981 
   1982     MYDB_BEGIN_ALLOW_THREADS;
   1983     err = self->db->get(self->db, txn, &key, &data, flags);
   1984     MYDB_END_ALLOW_THREADS;
   1985 
   1986     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
   1987         err = 0;
   1988         Py_INCREF(dfltobj);
   1989         retval = dfltobj;
   1990     }
   1991     else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   1992              && self->moduleFlags.getReturnsNone) {
   1993         err = 0;
   1994         Py_INCREF(Py_None);
   1995         retval = Py_None;
   1996     }
   1997     else if (!err) {
   1998         if (flags & DB_SET_RECNO) /* return both key and data */
   1999             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   2000         else /* return just the data */
   2001             retval = Build_PyString(data.data, data.size);
   2002         FREE_DBT(data);
   2003     }
   2004     FREE_DBT(key);
   2005 
   2006     RETURN_IF_ERR();
   2007     return retval;
   2008 }
   2009 
   2010 static PyObject*
   2011 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
   2012 {
   2013     int err, flags=0;
   2014     PyObject* txnobj = NULL;
   2015     PyObject* keyobj;
   2016     PyObject* dfltobj = NULL;
   2017     PyObject* retval = NULL;
   2018     int dlen = -1;
   2019     int doff = -1;
   2020     DBT key, pkey, data;
   2021     DB_TXN *txn = NULL;
   2022     static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
   2023                                     "doff", NULL};
   2024 
   2025     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
   2026                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen,
   2027                                      &doff))
   2028         return NULL;
   2029 
   2030     CHECK_DB_NOT_CLOSED(self);
   2031     if (!make_key_dbt(self, keyobj, &key, &flags))
   2032         return NULL;
   2033     if (!checkTxnObj(txnobj, &txn)) {
   2034         FREE_DBT(key);
   2035         return NULL;
   2036     }
   2037 
   2038     CLEAR_DBT(data);
   2039     if (CHECK_DBFLAG(self, DB_THREAD)) {
   2040         /* Tell Berkeley DB to malloc the return value (thread safe) */
   2041         data.flags = DB_DBT_MALLOC;
   2042     }
   2043     if (!add_partial_dbt(&data, dlen, doff)) {
   2044         FREE_DBT(key);
   2045         return NULL;
   2046     }
   2047 
   2048     CLEAR_DBT(pkey);
   2049     pkey.flags = DB_DBT_MALLOC;
   2050 
   2051     MYDB_BEGIN_ALLOW_THREADS;
   2052     err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
   2053     MYDB_END_ALLOW_THREADS;
   2054 
   2055     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
   2056         err = 0;
   2057         Py_INCREF(dfltobj);
   2058         retval = dfltobj;
   2059     }
   2060     else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   2061              && self->moduleFlags.getReturnsNone) {
   2062         err = 0;
   2063         Py_INCREF(Py_None);
   2064         retval = Py_None;
   2065     }
   2066     else if (!err) {
   2067         PyObject *pkeyObj;
   2068         PyObject *dataObj;
   2069         dataObj = Build_PyString(data.data, data.size);
   2070 
   2071         if (self->primaryDBType == DB_RECNO ||
   2072             self->primaryDBType == DB_QUEUE)
   2073             pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
   2074         else
   2075             pkeyObj = Build_PyString(pkey.data, pkey.size);
   2076 
   2077         if (flags & DB_SET_RECNO) /* return key , pkey and data */
   2078         {
   2079             PyObject *keyObj;
   2080             int type = _DB_get_type(self);
   2081             if (type == DB_RECNO || type == DB_QUEUE)
   2082                 keyObj = NUMBER_FromLong(*(int *)key.data);
   2083             else
   2084                 keyObj = Build_PyString(key.data, key.size);
   2085             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
   2086             Py_DECREF(keyObj);
   2087         }
   2088         else /* return just the pkey and data */
   2089         {
   2090             retval = PyTuple_Pack(2, pkeyObj, dataObj);
   2091         }
   2092         Py_DECREF(dataObj);
   2093         Py_DECREF(pkeyObj);
   2094         FREE_DBT(pkey);
   2095         FREE_DBT(data);
   2096     }
   2097     FREE_DBT(key);
   2098 
   2099     RETURN_IF_ERR();
   2100     return retval;
   2101 }
   2102 
   2103 
   2104 /* Return size of entry */
   2105 static PyObject*
   2106 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
   2107 {
   2108     int err, flags=0;
   2109     PyObject* txnobj = NULL;
   2110     PyObject* keyobj;
   2111     PyObject* retval = NULL;
   2112     DBT key, data;
   2113     DB_TXN *txn = NULL;
   2114     static char* kwnames[] = { "key", "txn", NULL };
   2115 
   2116     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
   2117                                      &keyobj, &txnobj))
   2118         return NULL;
   2119     CHECK_DB_NOT_CLOSED(self);
   2120     if (!make_key_dbt(self, keyobj, &key, &flags))
   2121         return NULL;
   2122     if (!checkTxnObj(txnobj, &txn)) {
   2123         FREE_DBT(key);
   2124         return NULL;
   2125     }
   2126     CLEAR_DBT(data);
   2127 
   2128     /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
   2129        thus getting the record size. */
   2130     data.flags = DB_DBT_USERMEM;
   2131     data.ulen = 0;
   2132     MYDB_BEGIN_ALLOW_THREADS;
   2133     err = self->db->get(self->db, txn, &key, &data, flags);
   2134     MYDB_END_ALLOW_THREADS;
   2135     if ((err == DB_BUFFER_SMALL) || (err == 0)) {
   2136         retval = NUMBER_FromLong((long)data.size);
   2137         err = 0;
   2138     }
   2139 
   2140     FREE_DBT(key);
   2141     FREE_DBT(data);
   2142     RETURN_IF_ERR();
   2143     return retval;
   2144 }
   2145 
   2146 
   2147 static PyObject*
   2148 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
   2149 {
   2150     int err, flags=0;
   2151     PyObject* txnobj = NULL;
   2152     PyObject* keyobj;
   2153     PyObject* dataobj;
   2154     PyObject* retval = NULL;
   2155     DBT key, data;
   2156     void *orig_data;
   2157     DB_TXN *txn = NULL;
   2158     static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
   2159 
   2160     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
   2161                                      &keyobj, &dataobj, &txnobj, &flags))
   2162         return NULL;
   2163 
   2164     CHECK_DB_NOT_CLOSED(self);
   2165     if (!make_key_dbt(self, keyobj, &key, NULL))
   2166         return NULL;
   2167     if ( !make_dbt(dataobj, &data) ||
   2168          !checkTxnObj(txnobj, &txn) )
   2169     {
   2170         FREE_DBT(key);
   2171         return NULL;
   2172     }
   2173 
   2174     flags |= DB_GET_BOTH;
   2175     orig_data = data.data;
   2176 
   2177     if (CHECK_DBFLAG(self, DB_THREAD)) {
   2178         /* Tell Berkeley DB to malloc the return value (thread safe) */
   2179         /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
   2180         data.flags = DB_DBT_MALLOC;
   2181     }
   2182 
   2183     MYDB_BEGIN_ALLOW_THREADS;
   2184     err = self->db->get(self->db, txn, &key, &data, flags);
   2185     MYDB_END_ALLOW_THREADS;
   2186 
   2187     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   2188             && self->moduleFlags.getReturnsNone) {
   2189         err = 0;
   2190         Py_INCREF(Py_None);
   2191         retval = Py_None;
   2192     }
   2193     else if (!err) {
   2194         /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
   2195         retval = Build_PyString(data.data, data.size);
   2196 
   2197         /* Even though the flags require DB_DBT_MALLOC, data is not always
   2198            allocated.  4.4: allocated, 4.5: *not* allocated. :-( */
   2199         if (data.data != orig_data)
   2200             FREE_DBT(data);
   2201     }
   2202 
   2203     FREE_DBT(key);
   2204     RETURN_IF_ERR();
   2205     return retval;
   2206 }
   2207 
   2208 
   2209 static PyObject*
   2210 DB_get_byteswapped(DBObject* self)
   2211 {
   2212     int err = 0;
   2213     int retval = -1;
   2214 
   2215     CHECK_DB_NOT_CLOSED(self);
   2216 
   2217     MYDB_BEGIN_ALLOW_THREADS;
   2218     err = self->db->get_byteswapped(self->db, &retval);
   2219     MYDB_END_ALLOW_THREADS;
   2220     RETURN_IF_ERR();
   2221     return NUMBER_FromLong(retval);
   2222 }
   2223 
   2224 
   2225 static PyObject*
   2226 DB_get_type(DBObject* self)
   2227 {
   2228     int type;
   2229 
   2230     CHECK_DB_NOT_CLOSED(self);
   2231 
   2232     type = _DB_get_type(self);
   2233     if (type == -1)
   2234         return NULL;
   2235     return NUMBER_FromLong(type);
   2236 }
   2237 
   2238 
   2239 static PyObject*
   2240 DB_join(DBObject* self, PyObject* args)
   2241 {
   2242     int err, flags=0;
   2243     int length, x;
   2244     PyObject* cursorsObj;
   2245     DBC** cursors;
   2246     DBC*  dbc;
   2247 
   2248     if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
   2249         return NULL;
   2250 
   2251     CHECK_DB_NOT_CLOSED(self);
   2252 
   2253     if (!PySequence_Check(cursorsObj)) {
   2254         PyErr_SetString(PyExc_TypeError,
   2255                         "Sequence of DBCursor objects expected");
   2256         return NULL;
   2257     }
   2258 
   2259     length = PyObject_Length(cursorsObj);
   2260     cursors = malloc((length+1) * sizeof(DBC*));
   2261     if (!cursors) {
   2262         PyErr_NoMemory();
   2263         return NULL;
   2264     }
   2265 
   2266     cursors[length] = NULL;
   2267     for (x=0; x<length; x++) {
   2268         PyObject* item = PySequence_GetItem(cursorsObj, x);
   2269         if (item == NULL) {
   2270             free(cursors);
   2271             return NULL;
   2272         }
   2273         if (!DBCursorObject_Check(item)) {
   2274             PyErr_SetString(PyExc_TypeError,
   2275                             "Sequence of DBCursor objects expected");
   2276             free(cursors);
   2277             return NULL;
   2278         }
   2279         cursors[x] = ((DBCursorObject*)item)->dbc;
   2280         Py_DECREF(item);
   2281     }
   2282 
   2283     MYDB_BEGIN_ALLOW_THREADS;
   2284     err = self->db->join(self->db, cursors, &dbc, flags);
   2285     MYDB_END_ALLOW_THREADS;
   2286     free(cursors);
   2287     RETURN_IF_ERR();
   2288 
   2289     /* FIXME: this is a buggy interface.  The returned cursor
   2290        contains internal references to the passed in cursors
   2291        but does not hold python references to them or prevent
   2292        them from being closed prematurely.  This can cause
   2293        python to crash when things are done in the wrong order. */
   2294     return (PyObject*) newDBCursorObject(dbc, NULL, self);
   2295 }
   2296 
   2297 
   2298 static PyObject*
   2299 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
   2300 {
   2301     int err, flags=0;
   2302     PyObject* txnobj = NULL;
   2303     PyObject* keyobj;
   2304     DBT key;
   2305     DB_TXN *txn = NULL;
   2306     DB_KEY_RANGE range;
   2307     static char* kwnames[] = { "key", "txn", "flags", NULL };
   2308 
   2309     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
   2310                                      &keyobj, &txnobj, &flags))
   2311         return NULL;
   2312     CHECK_DB_NOT_CLOSED(self);
   2313     if (!make_dbt(keyobj, &key))
   2314         /* BTree only, don't need to allow for an int key */
   2315         return NULL;
   2316     if (!checkTxnObj(txnobj, &txn))
   2317         return NULL;
   2318 
   2319     MYDB_BEGIN_ALLOW_THREADS;
   2320     err = self->db->key_range(self->db, txn, &key, &range, flags);
   2321     MYDB_END_ALLOW_THREADS;
   2322 
   2323     RETURN_IF_ERR();
   2324     return Py_BuildValue("ddd", range.less, range.equal, range.greater);
   2325 }
   2326 
   2327 
   2328 static PyObject*
   2329 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
   2330 {
   2331     int err, type = DB_UNKNOWN, flags=0, mode=0660;
   2332     char* filename = NULL;
   2333     char* dbname = NULL;
   2334     PyObject *txnobj = NULL;
   2335     DB_TXN *txn = NULL;
   2336     /* with dbname */
   2337     static char* kwnames[] = {
   2338         "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
   2339     /* without dbname */
   2340     static char* kwnames_basic[] = {
   2341         "filename", "dbtype", "flags", "mode", "txn", NULL};
   2342 
   2343     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
   2344                                      &filename, &dbname, &type, &flags, &mode,
   2345                                      &txnobj))
   2346     {
   2347         PyErr_Clear();
   2348         type = DB_UNKNOWN; flags = 0; mode = 0660;
   2349         filename = NULL; dbname = NULL;
   2350         if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
   2351                                          kwnames_basic,
   2352                                          &filename, &type, &flags, &mode,
   2353                                          &txnobj))
   2354             return NULL;
   2355     }
   2356 
   2357     if (!checkTxnObj(txnobj, &txn)) return NULL;
   2358 
   2359     if (NULL == self->db) {
   2360         PyObject *t = Py_BuildValue("(is)", 0,
   2361                                 "Cannot call open() twice for DB object");
   2362         if (t) {
   2363             PyErr_SetObject(DBError, t);
   2364             Py_DECREF(t);
   2365         }
   2366         return NULL;
   2367     }
   2368 
   2369     if (txn) {  /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
   2370         INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
   2371         self->txn=(DBTxnObject *)txnobj;
   2372     } else {
   2373         self->txn=NULL;
   2374     }
   2375 
   2376     MYDB_BEGIN_ALLOW_THREADS;
   2377     err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
   2378     MYDB_END_ALLOW_THREADS;
   2379 
   2380     if (makeDBError(err)) {
   2381         PyObject *dummy;
   2382 
   2383         dummy=DB_close_internal(self, 0, 0);
   2384         Py_XDECREF(dummy);
   2385         return NULL;
   2386     }
   2387 
   2388     self->db->get_flags(self->db, &self->setflags);
   2389 
   2390     self->flags = flags;
   2391 
   2392     RETURN_NONE();
   2393 }
   2394 
   2395 
   2396 static PyObject*
   2397 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
   2398 {
   2399     int flags=0;
   2400     PyObject* txnobj = NULL;
   2401     int dlen = -1;
   2402     int doff = -1;
   2403     PyObject* keyobj, *dataobj, *retval;
   2404     DBT key, data;
   2405     DB_TXN *txn = NULL;
   2406     static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
   2407                                      "doff", NULL };
   2408 
   2409     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
   2410                          &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
   2411         return NULL;
   2412 
   2413     CHECK_DB_NOT_CLOSED(self);
   2414     if (!make_key_dbt(self, keyobj, &key, NULL))
   2415         return NULL;
   2416     if ( !make_dbt(dataobj, &data) ||
   2417          !add_partial_dbt(&data, dlen, doff) ||
   2418          !checkTxnObj(txnobj, &txn) )
   2419     {
   2420         FREE_DBT(key);
   2421         return NULL;
   2422     }
   2423 
   2424     if (-1 == _DB_put(self, txn, &key, &data, flags)) {
   2425         FREE_DBT(key);
   2426         return NULL;
   2427     }
   2428 
   2429     if (flags & DB_APPEND)
   2430         retval = NUMBER_FromLong(*((db_recno_t*)key.data));
   2431     else {
   2432         retval = Py_None;
   2433         Py_INCREF(retval);
   2434     }
   2435     FREE_DBT(key);
   2436     return retval;
   2437 }
   2438 
   2439 
   2440 
   2441 static PyObject*
   2442 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
   2443 {
   2444     char* filename;
   2445     char* database = NULL;
   2446     int err, flags=0;
   2447     static char* kwnames[] = { "filename", "dbname", "flags", NULL};
   2448 
   2449     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
   2450                                      &filename, &database, &flags))
   2451         return NULL;
   2452     CHECK_DB_NOT_CLOSED(self);
   2453 
   2454     EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
   2455 
   2456     MYDB_BEGIN_ALLOW_THREADS;
   2457     err = self->db->remove(self->db, filename, database, flags);
   2458     MYDB_END_ALLOW_THREADS;
   2459 
   2460     self->db = NULL;
   2461     RETURN_IF_ERR();
   2462     RETURN_NONE();
   2463 }
   2464 
   2465 
   2466 
   2467 static PyObject*
   2468 DB_rename(DBObject* self, PyObject* args)
   2469 {
   2470     char* filename;
   2471     char* database;
   2472     char* newname;
   2473     int err, flags=0;
   2474 
   2475     if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
   2476                           &flags))
   2477         return NULL;
   2478     CHECK_DB_NOT_CLOSED(self);
   2479 
   2480     MYDB_BEGIN_ALLOW_THREADS;
   2481     err = self->db->rename(self->db, filename, database, newname, flags);
   2482     MYDB_END_ALLOW_THREADS;
   2483     RETURN_IF_ERR();
   2484     RETURN_NONE();
   2485 }
   2486 
   2487 
   2488 static PyObject*
   2489 DB_get_private(DBObject* self)
   2490 {
   2491     /* We can give out the private field even if db is closed */
   2492     Py_INCREF(self->private_obj);
   2493     return self->private_obj;
   2494 }
   2495 
   2496 static PyObject*
   2497 DB_set_private(DBObject* self, PyObject* private_obj)
   2498 {
   2499     /* We can set the private field even if db is closed */
   2500     Py_INCREF(private_obj);
   2501     Py_SETREF(self->private_obj, private_obj);
   2502     RETURN_NONE();
   2503 }
   2504 
   2505 #if (DBVER >= 46)
   2506 static PyObject*
   2507 DB_set_priority(DBObject* self, PyObject* args)
   2508 {
   2509     int err, priority;
   2510 
   2511     if (!PyArg_ParseTuple(args,"i:set_priority", &priority))
   2512         return NULL;
   2513     CHECK_DB_NOT_CLOSED(self);
   2514 
   2515     MYDB_BEGIN_ALLOW_THREADS;
   2516     err = self->db->set_priority(self->db, priority);
   2517     MYDB_END_ALLOW_THREADS;
   2518     RETURN_IF_ERR();
   2519     RETURN_NONE();
   2520 }
   2521 
   2522 static PyObject*
   2523 DB_get_priority(DBObject* self)
   2524 {
   2525     int err = 0;
   2526     DB_CACHE_PRIORITY priority;
   2527 
   2528     CHECK_DB_NOT_CLOSED(self);
   2529 
   2530     MYDB_BEGIN_ALLOW_THREADS;
   2531     err = self->db->get_priority(self->db, &priority);
   2532     MYDB_END_ALLOW_THREADS;
   2533     RETURN_IF_ERR();
   2534     return NUMBER_FromLong(priority);
   2535 }
   2536 #endif
   2537 
   2538 static PyObject*
   2539 DB_get_dbname(DBObject* self)
   2540 {
   2541     int err;
   2542     const char *filename, *dbname;
   2543 
   2544     CHECK_DB_NOT_CLOSED(self);
   2545 
   2546     MYDB_BEGIN_ALLOW_THREADS;
   2547     err = self->db->get_dbname(self->db, &filename, &dbname);
   2548     MYDB_END_ALLOW_THREADS;
   2549     RETURN_IF_ERR();
   2550     /* If "dbname==NULL", it is correctly converted to "None" */
   2551     return Py_BuildValue("(ss)", filename, dbname);
   2552 }
   2553 
   2554 static PyObject*
   2555 DB_get_open_flags(DBObject* self)
   2556 {
   2557     int err;
   2558     unsigned int flags;
   2559 
   2560     CHECK_DB_NOT_CLOSED(self);
   2561 
   2562     MYDB_BEGIN_ALLOW_THREADS;
   2563     err = self->db->get_open_flags(self->db, &flags);
   2564     MYDB_END_ALLOW_THREADS;
   2565     RETURN_IF_ERR();
   2566     return NUMBER_FromLong(flags);
   2567 }
   2568 
   2569 static PyObject*
   2570 DB_set_q_extentsize(DBObject* self, PyObject* args)
   2571 {
   2572     int err;
   2573     u_int32_t extentsize;
   2574 
   2575     if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
   2576         return NULL;
   2577     CHECK_DB_NOT_CLOSED(self);
   2578 
   2579     MYDB_BEGIN_ALLOW_THREADS;
   2580     err = self->db->set_q_extentsize(self->db, extentsize);
   2581     MYDB_END_ALLOW_THREADS;
   2582     RETURN_IF_ERR();
   2583     RETURN_NONE();
   2584 }
   2585 
   2586 static PyObject*
   2587 DB_get_q_extentsize(DBObject* self)
   2588 {
   2589     int err = 0;
   2590     u_int32_t extentsize;
   2591 
   2592     CHECK_DB_NOT_CLOSED(self);
   2593 
   2594     MYDB_BEGIN_ALLOW_THREADS;
   2595     err = self->db->get_q_extentsize(self->db, &extentsize);
   2596     MYDB_END_ALLOW_THREADS;
   2597     RETURN_IF_ERR();
   2598     return NUMBER_FromLong(extentsize);
   2599 }
   2600 
   2601 static PyObject*
   2602 DB_set_bt_minkey(DBObject* self, PyObject* args)
   2603 {
   2604     int err, minkey;
   2605 
   2606     if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey))
   2607         return NULL;
   2608     CHECK_DB_NOT_CLOSED(self);
   2609 
   2610     MYDB_BEGIN_ALLOW_THREADS;
   2611     err = self->db->set_bt_minkey(self->db, minkey);
   2612     MYDB_END_ALLOW_THREADS;
   2613     RETURN_IF_ERR();
   2614     RETURN_NONE();
   2615 }
   2616 
   2617 static PyObject*
   2618 DB_get_bt_minkey(DBObject* self)
   2619 {
   2620     int err;
   2621     u_int32_t bt_minkey;
   2622 
   2623     CHECK_DB_NOT_CLOSED(self);
   2624 
   2625     MYDB_BEGIN_ALLOW_THREADS;
   2626     err = self->db->get_bt_minkey(self->db, &bt_minkey);
   2627     MYDB_END_ALLOW_THREADS;
   2628     RETURN_IF_ERR();
   2629     return NUMBER_FromLong(bt_minkey);
   2630 }
   2631 
   2632 static int
   2633 _default_cmp(const DBT *leftKey,
   2634              const DBT *rightKey)
   2635 {
   2636   int res;
   2637   int lsize = leftKey->size, rsize = rightKey->size;
   2638 
   2639   res = memcmp(leftKey->data, rightKey->data,
   2640                lsize < rsize ? lsize : rsize);
   2641 
   2642   if (res == 0) {
   2643       if (lsize < rsize) {
   2644           res = -1;
   2645       }
   2646       else if (lsize > rsize) {
   2647           res = 1;
   2648       }
   2649   }
   2650   return res;
   2651 }
   2652 
   2653 static int
   2654 _db_compareCallback(DB* db,
   2655                     const DBT *leftKey,
   2656                     const DBT *rightKey)
   2657 {
   2658     int res = 0;
   2659     PyObject *args;
   2660     PyObject *result = NULL;
   2661     DBObject *self = (DBObject *)db->app_private;
   2662 
   2663     if (self == NULL || self->btCompareCallback == NULL) {
   2664         MYDB_BEGIN_BLOCK_THREADS;
   2665         PyErr_SetString(PyExc_TypeError,
   2666                         (self == 0
   2667                          ? "DB_bt_compare db is NULL."
   2668                          : "DB_bt_compare callback is NULL."));
   2669         /* we're in a callback within the DB code, we can't raise */
   2670         PyErr_Print();
   2671         res = _default_cmp(leftKey, rightKey);
   2672         MYDB_END_BLOCK_THREADS;
   2673     } else {
   2674         MYDB_BEGIN_BLOCK_THREADS;
   2675 
   2676         args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
   2677         if (args != NULL) {
   2678                 result = PyEval_CallObject(self->btCompareCallback, args);
   2679         }
   2680         if (args == NULL || result == NULL) {
   2681             /* we're in a callback within the DB code, we can't raise */
   2682             PyErr_Print();
   2683             res = _default_cmp(leftKey, rightKey);
   2684         } else if (NUMBER_Check(result)) {
   2685             res = NUMBER_AsLong(result);
   2686         } else {
   2687             PyErr_SetString(PyExc_TypeError,
   2688                             "DB_bt_compare callback MUST return an int.");
   2689             /* we're in a callback within the DB code, we can't raise */
   2690             PyErr_Print();
   2691             res = _default_cmp(leftKey, rightKey);
   2692         }
   2693 
   2694         Py_XDECREF(args);
   2695         Py_XDECREF(result);
   2696 
   2697         MYDB_END_BLOCK_THREADS;
   2698     }
   2699     return res;
   2700 }
   2701 
   2702 static PyObject*
   2703 DB_set_bt_compare(DBObject* self, PyObject* comparator)
   2704 {
   2705     int err;
   2706     PyObject *tuple, *result;
   2707 
   2708     CHECK_DB_NOT_CLOSED(self);
   2709 
   2710     if (!PyCallable_Check(comparator)) {
   2711         makeTypeError("Callable", comparator);
   2712         return NULL;
   2713     }
   2714 
   2715     /*
   2716      * Perform a test call of the comparator function with two empty
   2717      * string objects here.  verify that it returns an int (0).
   2718      * err if not.
   2719      */
   2720     tuple = Py_BuildValue("(ss)", "", "");
   2721     result = PyEval_CallObject(comparator, tuple);
   2722     Py_DECREF(tuple);
   2723     if (result == NULL)
   2724         return NULL;
   2725     if (!NUMBER_Check(result)) {
   2726         Py_DECREF(result);
   2727         PyErr_SetString(PyExc_TypeError,
   2728                         "callback MUST return an int");
   2729         return NULL;
   2730     } else if (NUMBER_AsLong(result) != 0) {
   2731         Py_DECREF(result);
   2732         PyErr_SetString(PyExc_TypeError,
   2733                         "callback failed to return 0 on two empty strings");
   2734         return NULL;
   2735     }
   2736     Py_DECREF(result);
   2737 
   2738     /* We don't accept multiple set_bt_compare operations, in order to
   2739      * simplify the code. This would have no real use, as one cannot
   2740      * change the function once the db is opened anyway */
   2741     if (self->btCompareCallback != NULL) {
   2742         PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
   2743         return NULL;
   2744     }
   2745 
   2746     Py_INCREF(comparator);
   2747     self->btCompareCallback = comparator;
   2748 
   2749     /* This is to workaround a problem with un-initialized threads (see
   2750        comment in DB_associate) */
   2751 #ifdef WITH_THREAD
   2752     PyEval_InitThreads();
   2753 #endif
   2754 
   2755     err = self->db->set_bt_compare(self->db, _db_compareCallback);
   2756 
   2757     if (err) {
   2758         /* restore the old state in case of error */
   2759         Py_DECREF(comparator);
   2760         self->btCompareCallback = NULL;
   2761     }
   2762 
   2763     RETURN_IF_ERR();
   2764     RETURN_NONE();
   2765 }
   2766 
   2767 static int
   2768 _db_dupCompareCallback(DB* db,
   2769 		    const DBT *leftKey,
   2770 		    const DBT *rightKey)
   2771 {
   2772     int res = 0;
   2773     PyObject *args;
   2774     PyObject *result = NULL;
   2775     DBObject *self = (DBObject *)db->app_private;
   2776 
   2777     if (self == NULL || self->dupCompareCallback == NULL) {
   2778 	MYDB_BEGIN_BLOCK_THREADS;
   2779 	PyErr_SetString(PyExc_TypeError,
   2780 			(self == 0
   2781 			 ? "DB_dup_compare db is NULL."
   2782 			 : "DB_dup_compare callback is NULL."));
   2783 	/* we're in a callback within the DB code, we can't raise */
   2784 	PyErr_Print();
   2785 	res = _default_cmp(leftKey, rightKey);
   2786 	MYDB_END_BLOCK_THREADS;
   2787     } else {
   2788 	MYDB_BEGIN_BLOCK_THREADS;
   2789 
   2790 	args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
   2791 	if (args != NULL) {
   2792 		result = PyEval_CallObject(self->dupCompareCallback, args);
   2793 	}
   2794 	if (args == NULL || result == NULL) {
   2795 	    /* we're in a callback within the DB code, we can't raise */
   2796 	    PyErr_Print();
   2797 	    res = _default_cmp(leftKey, rightKey);
   2798 	} else if (NUMBER_Check(result)) {
   2799 	    res = NUMBER_AsLong(result);
   2800 	} else {
   2801 	    PyErr_SetString(PyExc_TypeError,
   2802 			    "DB_dup_compare callback MUST return an int.");
   2803 	    /* we're in a callback within the DB code, we can't raise */
   2804 	    PyErr_Print();
   2805 	    res = _default_cmp(leftKey, rightKey);
   2806 	}
   2807 
   2808 	Py_XDECREF(args);
   2809 	Py_XDECREF(result);
   2810 
   2811 	MYDB_END_BLOCK_THREADS;
   2812     }
   2813     return res;
   2814 }
   2815 
   2816 static PyObject*
   2817 DB_set_dup_compare(DBObject* self, PyObject* comparator)
   2818 {
   2819     int err;
   2820     PyObject *tuple, *result;
   2821 
   2822     CHECK_DB_NOT_CLOSED(self);
   2823 
   2824     if (!PyCallable_Check(comparator)) {
   2825 	makeTypeError("Callable", comparator);
   2826 	return NULL;
   2827     }
   2828 
   2829     /*
   2830      * Perform a test call of the comparator function with two empty
   2831      * string objects here.  verify that it returns an int (0).
   2832      * err if not.
   2833      */
   2834     tuple = Py_BuildValue("(ss)", "", "");
   2835     result = PyEval_CallObject(comparator, tuple);
   2836     Py_DECREF(tuple);
   2837     if (result == NULL)
   2838         return NULL;
   2839     if (!NUMBER_Check(result)) {
   2840 	Py_DECREF(result);
   2841 	PyErr_SetString(PyExc_TypeError,
   2842 		        "callback MUST return an int");
   2843 	return NULL;
   2844     } else if (NUMBER_AsLong(result) != 0) {
   2845 	Py_DECREF(result);
   2846 	PyErr_SetString(PyExc_TypeError,
   2847 		        "callback failed to return 0 on two empty strings");
   2848 	return NULL;
   2849     }
   2850     Py_DECREF(result);
   2851 
   2852     /* We don't accept multiple set_dup_compare operations, in order to
   2853      * simplify the code. This would have no real use, as one cannot
   2854      * change the function once the db is opened anyway */
   2855     if (self->dupCompareCallback != NULL) {
   2856 	PyErr_SetString(PyExc_RuntimeError, "set_dup_compare() cannot be called more than once");
   2857 	return NULL;
   2858     }
   2859 
   2860     Py_INCREF(comparator);
   2861     self->dupCompareCallback = comparator;
   2862 
   2863     /* This is to workaround a problem with un-initialized threads (see
   2864        comment in DB_associate) */
   2865 #ifdef WITH_THREAD
   2866     PyEval_InitThreads();
   2867 #endif
   2868 
   2869     err = self->db->set_dup_compare(self->db, _db_dupCompareCallback);
   2870 
   2871     if (err) {
   2872 	/* restore the old state in case of error */
   2873 	Py_DECREF(comparator);
   2874 	self->dupCompareCallback = NULL;
   2875     }
   2876 
   2877     RETURN_IF_ERR();
   2878     RETURN_NONE();
   2879 }
   2880 
   2881 
   2882 static PyObject*
   2883 DB_set_cachesize(DBObject* self, PyObject* args)
   2884 {
   2885     int err;
   2886     int gbytes = 0, bytes = 0, ncache = 0;
   2887 
   2888     if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
   2889                           &gbytes,&bytes,&ncache))
   2890         return NULL;
   2891     CHECK_DB_NOT_CLOSED(self);
   2892 
   2893     MYDB_BEGIN_ALLOW_THREADS;
   2894     err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
   2895     MYDB_END_ALLOW_THREADS;
   2896     RETURN_IF_ERR();
   2897     RETURN_NONE();
   2898 }
   2899 
   2900 static PyObject*
   2901 DB_get_cachesize(DBObject* self)
   2902 {
   2903     int err;
   2904     u_int32_t gbytes, bytes;
   2905     int ncache;
   2906 
   2907     CHECK_DB_NOT_CLOSED(self);
   2908 
   2909     MYDB_BEGIN_ALLOW_THREADS;
   2910     err = self->db->get_cachesize(self->db, &gbytes, &bytes, &ncache);
   2911     MYDB_END_ALLOW_THREADS;
   2912 
   2913     RETURN_IF_ERR();
   2914 
   2915     return Py_BuildValue("(iii)", gbytes, bytes, ncache);
   2916 }
   2917 
   2918 static PyObject*
   2919 DB_set_flags(DBObject* self, PyObject* args)
   2920 {
   2921     int err, flags;
   2922 
   2923     if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
   2924         return NULL;
   2925     CHECK_DB_NOT_CLOSED(self);
   2926 
   2927     MYDB_BEGIN_ALLOW_THREADS;
   2928     err = self->db->set_flags(self->db, flags);
   2929     MYDB_END_ALLOW_THREADS;
   2930     RETURN_IF_ERR();
   2931 
   2932     self->setflags |= flags;
   2933     RETURN_NONE();
   2934 }
   2935 
   2936 static PyObject*
   2937 DB_get_flags(DBObject* self)
   2938 {
   2939     int err;
   2940     u_int32_t flags;
   2941 
   2942     CHECK_DB_NOT_CLOSED(self);
   2943 
   2944     MYDB_BEGIN_ALLOW_THREADS;
   2945     err = self->db->get_flags(self->db, &flags);
   2946     MYDB_END_ALLOW_THREADS;
   2947     RETURN_IF_ERR();
   2948     return NUMBER_FromLong(flags);
   2949 }
   2950 
   2951 static PyObject*
   2952 DB_get_transactional(DBObject* self)
   2953 {
   2954     int err;
   2955 
   2956     CHECK_DB_NOT_CLOSED(self);
   2957 
   2958     MYDB_BEGIN_ALLOW_THREADS;
   2959     err = self->db->get_transactional(self->db);
   2960     MYDB_END_ALLOW_THREADS;
   2961 
   2962     if(err == 0) {
   2963         Py_INCREF(Py_False);
   2964         return Py_False;
   2965     } else if(err == 1) {
   2966         Py_INCREF(Py_True);
   2967         return Py_True;
   2968     }
   2969 
   2970     /*
   2971     ** If we reach there, there was an error. The
   2972     ** "return" should be unreachable.
   2973     */
   2974     RETURN_IF_ERR();
   2975     assert(0);  /* This code SHOULD be unreachable */
   2976     return NULL;
   2977 }
   2978 
   2979 static PyObject*
   2980 DB_set_h_ffactor(DBObject* self, PyObject* args)
   2981 {
   2982     int err, ffactor;
   2983 
   2984     if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
   2985         return NULL;
   2986     CHECK_DB_NOT_CLOSED(self);
   2987 
   2988     MYDB_BEGIN_ALLOW_THREADS;
   2989     err = self->db->set_h_ffactor(self->db, ffactor);
   2990     MYDB_END_ALLOW_THREADS;
   2991     RETURN_IF_ERR();
   2992     RETURN_NONE();
   2993 }
   2994 
   2995 static PyObject*
   2996 DB_get_h_ffactor(DBObject* self)
   2997 {
   2998     int err;
   2999     u_int32_t ffactor;
   3000 
   3001     CHECK_DB_NOT_CLOSED(self);
   3002 
   3003     MYDB_BEGIN_ALLOW_THREADS;
   3004     err = self->db->get_h_ffactor(self->db, &ffactor);
   3005     MYDB_END_ALLOW_THREADS;
   3006     RETURN_IF_ERR();
   3007     return NUMBER_FromLong(ffactor);
   3008 }
   3009 
   3010 static PyObject*
   3011 DB_set_h_nelem(DBObject* self, PyObject* args)
   3012 {
   3013     int err, nelem;
   3014 
   3015     if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
   3016         return NULL;
   3017     CHECK_DB_NOT_CLOSED(self);
   3018 
   3019     MYDB_BEGIN_ALLOW_THREADS;
   3020     err = self->db->set_h_nelem(self->db, nelem);
   3021     MYDB_END_ALLOW_THREADS;
   3022     RETURN_IF_ERR();
   3023     RETURN_NONE();
   3024 }
   3025 
   3026 static PyObject*
   3027 DB_get_h_nelem(DBObject* self)
   3028 {
   3029     int err;
   3030     u_int32_t nelem;
   3031 
   3032     CHECK_DB_NOT_CLOSED(self);
   3033 
   3034     MYDB_BEGIN_ALLOW_THREADS;
   3035     err = self->db->get_h_nelem(self->db, &nelem);
   3036     MYDB_END_ALLOW_THREADS;
   3037     RETURN_IF_ERR();
   3038     return NUMBER_FromLong(nelem);
   3039 }
   3040 
   3041 static PyObject*
   3042 DB_set_lorder(DBObject* self, PyObject* args)
   3043 {
   3044     int err, lorder;
   3045 
   3046     if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
   3047         return NULL;
   3048     CHECK_DB_NOT_CLOSED(self);
   3049 
   3050     MYDB_BEGIN_ALLOW_THREADS;
   3051     err = self->db->set_lorder(self->db, lorder);
   3052     MYDB_END_ALLOW_THREADS;
   3053     RETURN_IF_ERR();
   3054     RETURN_NONE();
   3055 }
   3056 
   3057 static PyObject*
   3058 DB_get_lorder(DBObject* self)
   3059 {
   3060     int err;
   3061     int lorder;
   3062 
   3063     CHECK_DB_NOT_CLOSED(self);
   3064 
   3065     MYDB_BEGIN_ALLOW_THREADS;
   3066     err = self->db->get_lorder(self->db, &lorder);
   3067     MYDB_END_ALLOW_THREADS;
   3068     RETURN_IF_ERR();
   3069     return NUMBER_FromLong(lorder);
   3070 }
   3071 
   3072 static PyObject*
   3073 DB_set_pagesize(DBObject* self, PyObject* args)
   3074 {
   3075     int err, pagesize;
   3076 
   3077     if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
   3078         return NULL;
   3079     CHECK_DB_NOT_CLOSED(self);
   3080 
   3081     MYDB_BEGIN_ALLOW_THREADS;
   3082     err = self->db->set_pagesize(self->db, pagesize);
   3083     MYDB_END_ALLOW_THREADS;
   3084     RETURN_IF_ERR();
   3085     RETURN_NONE();
   3086 }
   3087 
   3088 static PyObject*
   3089 DB_get_pagesize(DBObject* self)
   3090 {
   3091     int err;
   3092     u_int32_t pagesize;
   3093 
   3094     CHECK_DB_NOT_CLOSED(self);
   3095 
   3096     MYDB_BEGIN_ALLOW_THREADS;
   3097     err = self->db->get_pagesize(self->db, &pagesize);
   3098     MYDB_END_ALLOW_THREADS;
   3099     RETURN_IF_ERR();
   3100     return NUMBER_FromLong(pagesize);
   3101 }
   3102 
   3103 static PyObject*
   3104 DB_set_re_delim(DBObject* self, PyObject* args)
   3105 {
   3106     int err;
   3107     char delim;
   3108 
   3109     if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
   3110         PyErr_Clear();
   3111         if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
   3112             return NULL;
   3113     }
   3114 
   3115     CHECK_DB_NOT_CLOSED(self);
   3116 
   3117     MYDB_BEGIN_ALLOW_THREADS;
   3118     err = self->db->set_re_delim(self->db, delim);
   3119     MYDB_END_ALLOW_THREADS;
   3120     RETURN_IF_ERR();
   3121     RETURN_NONE();
   3122 }
   3123 
   3124 static PyObject*
   3125 DB_get_re_delim(DBObject* self)
   3126 {
   3127     int err, re_delim;
   3128 
   3129     CHECK_DB_NOT_CLOSED(self);
   3130 
   3131     MYDB_BEGIN_ALLOW_THREADS;
   3132     err = self->db->get_re_delim(self->db, &re_delim);
   3133     MYDB_END_ALLOW_THREADS;
   3134     RETURN_IF_ERR();
   3135     return NUMBER_FromLong(re_delim);
   3136 }
   3137 
   3138 static PyObject*
   3139 DB_set_re_len(DBObject* self, PyObject* args)
   3140 {
   3141     int err, len;
   3142 
   3143     if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
   3144         return NULL;
   3145     CHECK_DB_NOT_CLOSED(self);
   3146 
   3147     MYDB_BEGIN_ALLOW_THREADS;
   3148     err = self->db->set_re_len(self->db, len);
   3149     MYDB_END_ALLOW_THREADS;
   3150     RETURN_IF_ERR();
   3151     RETURN_NONE();
   3152 }
   3153 
   3154 static PyObject*
   3155 DB_get_re_len(DBObject* self)
   3156 {
   3157     int err;
   3158     u_int32_t re_len;
   3159 
   3160     CHECK_DB_NOT_CLOSED(self);
   3161 
   3162     MYDB_BEGIN_ALLOW_THREADS;
   3163     err = self->db->get_re_len(self->db, &re_len);
   3164     MYDB_END_ALLOW_THREADS;
   3165     RETURN_IF_ERR();
   3166     return NUMBER_FromLong(re_len);
   3167 }
   3168 
   3169 static PyObject*
   3170 DB_set_re_pad(DBObject* self, PyObject* args)
   3171 {
   3172     int err;
   3173     char pad;
   3174 
   3175     if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
   3176         PyErr_Clear();
   3177         if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
   3178             return NULL;
   3179     }
   3180     CHECK_DB_NOT_CLOSED(self);
   3181 
   3182     MYDB_BEGIN_ALLOW_THREADS;
   3183     err = self->db->set_re_pad(self->db, pad);
   3184     MYDB_END_ALLOW_THREADS;
   3185     RETURN_IF_ERR();
   3186     RETURN_NONE();
   3187 }
   3188 
   3189 static PyObject*
   3190 DB_get_re_pad(DBObject* self)
   3191 {
   3192     int err, re_pad;
   3193 
   3194     CHECK_DB_NOT_CLOSED(self);
   3195 
   3196     MYDB_BEGIN_ALLOW_THREADS;
   3197     err = self->db->get_re_pad(self->db, &re_pad);
   3198     MYDB_END_ALLOW_THREADS;
   3199     RETURN_IF_ERR();
   3200     return NUMBER_FromLong(re_pad);
   3201 }
   3202 
   3203 static PyObject*
   3204 DB_set_re_source(DBObject* self, PyObject* args)
   3205 {
   3206     int err;
   3207     char *source;
   3208 
   3209     if (!PyArg_ParseTuple(args,"s:set_re_source", &source))
   3210         return NULL;
   3211     CHECK_DB_NOT_CLOSED(self);
   3212 
   3213     MYDB_BEGIN_ALLOW_THREADS;
   3214     err = self->db->set_re_source(self->db, source);
   3215     MYDB_END_ALLOW_THREADS;
   3216     RETURN_IF_ERR();
   3217     RETURN_NONE();
   3218 }
   3219 
   3220 static PyObject*
   3221 DB_get_re_source(DBObject* self)
   3222 {
   3223     int err;
   3224     const char *source;
   3225 
   3226     CHECK_DB_NOT_CLOSED(self);
   3227 
   3228     MYDB_BEGIN_ALLOW_THREADS;
   3229     err = self->db->get_re_source(self->db, &source);
   3230     MYDB_END_ALLOW_THREADS;
   3231     RETURN_IF_ERR();
   3232     return PyBytes_FromString(source);
   3233 }
   3234 
   3235 static PyObject*
   3236 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
   3237 {
   3238     int err, flags = 0, type;
   3239     void* sp;
   3240     PyObject* d;
   3241     PyObject* txnobj = NULL;
   3242     DB_TXN *txn = NULL;
   3243     static char* kwnames[] = { "flags", "txn", NULL };
   3244 
   3245     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
   3246                                      &flags, &txnobj))
   3247         return NULL;
   3248     if (!checkTxnObj(txnobj, &txn))
   3249         return NULL;
   3250     CHECK_DB_NOT_CLOSED(self);
   3251 
   3252     MYDB_BEGIN_ALLOW_THREADS;
   3253     err = self->db->stat(self->db, txn, &sp, flags);
   3254     MYDB_END_ALLOW_THREADS;
   3255     RETURN_IF_ERR();
   3256 
   3257     /* Turn the stat structure into a dictionary */
   3258     type = _DB_get_type(self);
   3259     if ((type == -1) || ((d = PyDict_New()) == NULL)) {
   3260         free(sp);
   3261         return NULL;
   3262     }
   3263 
   3264 #define MAKE_HASH_ENTRY(name)  _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
   3265 #define MAKE_BT_ENTRY(name)    _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
   3266 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
   3267 
   3268     switch (type) {
   3269     case DB_HASH:
   3270         MAKE_HASH_ENTRY(magic);
   3271         MAKE_HASH_ENTRY(version);
   3272         MAKE_HASH_ENTRY(nkeys);
   3273         MAKE_HASH_ENTRY(ndata);
   3274 #if (DBVER >= 46)
   3275         MAKE_HASH_ENTRY(pagecnt);
   3276 #endif
   3277         MAKE_HASH_ENTRY(pagesize);
   3278         MAKE_HASH_ENTRY(ffactor);
   3279         MAKE_HASH_ENTRY(buckets);
   3280         MAKE_HASH_ENTRY(free);
   3281         MAKE_HASH_ENTRY(bfree);
   3282         MAKE_HASH_ENTRY(bigpages);
   3283         MAKE_HASH_ENTRY(big_bfree);
   3284         MAKE_HASH_ENTRY(overflows);
   3285         MAKE_HASH_ENTRY(ovfl_free);
   3286         MAKE_HASH_ENTRY(dup);
   3287         MAKE_HASH_ENTRY(dup_free);
   3288         break;
   3289 
   3290     case DB_BTREE:
   3291     case DB_RECNO:
   3292         MAKE_BT_ENTRY(magic);
   3293         MAKE_BT_ENTRY(version);
   3294         MAKE_BT_ENTRY(nkeys);
   3295         MAKE_BT_ENTRY(ndata);
   3296 #if (DBVER >= 46)
   3297         MAKE_BT_ENTRY(pagecnt);
   3298 #endif
   3299         MAKE_BT_ENTRY(pagesize);
   3300         MAKE_BT_ENTRY(minkey);
   3301         MAKE_BT_ENTRY(re_len);
   3302         MAKE_BT_ENTRY(re_pad);
   3303         MAKE_BT_ENTRY(levels);
   3304         MAKE_BT_ENTRY(int_pg);
   3305         MAKE_BT_ENTRY(leaf_pg);
   3306         MAKE_BT_ENTRY(dup_pg);
   3307         MAKE_BT_ENTRY(over_pg);
   3308         MAKE_BT_ENTRY(empty_pg);
   3309         MAKE_BT_ENTRY(free);
   3310         MAKE_BT_ENTRY(int_pgfree);
   3311         MAKE_BT_ENTRY(leaf_pgfree);
   3312         MAKE_BT_ENTRY(dup_pgfree);
   3313         MAKE_BT_ENTRY(over_pgfree);
   3314         break;
   3315 
   3316     case DB_QUEUE:
   3317         MAKE_QUEUE_ENTRY(magic);
   3318         MAKE_QUEUE_ENTRY(version);
   3319         MAKE_QUEUE_ENTRY(nkeys);
   3320         MAKE_QUEUE_ENTRY(ndata);
   3321         MAKE_QUEUE_ENTRY(pagesize);
   3322         MAKE_QUEUE_ENTRY(extentsize);
   3323         MAKE_QUEUE_ENTRY(pages);
   3324         MAKE_QUEUE_ENTRY(re_len);
   3325         MAKE_QUEUE_ENTRY(re_pad);
   3326         MAKE_QUEUE_ENTRY(pgfree);
   3327 #if (DBVER == 31)
   3328         MAKE_QUEUE_ENTRY(start);
   3329 #endif
   3330         MAKE_QUEUE_ENTRY(first_recno);
   3331         MAKE_QUEUE_ENTRY(cur_recno);
   3332         break;
   3333 
   3334     default:
   3335         PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
   3336         Py_DECREF(d);
   3337         d = NULL;
   3338     }
   3339 
   3340 #undef MAKE_HASH_ENTRY
   3341 #undef MAKE_BT_ENTRY
   3342 #undef MAKE_QUEUE_ENTRY
   3343 
   3344     free(sp);
   3345     return d;
   3346 }
   3347 
   3348 static PyObject*
   3349 DB_stat_print(DBObject* self, PyObject* args, PyObject *kwargs)
   3350 {
   3351     int err;
   3352     int flags=0;
   3353     static char* kwnames[] = { "flags", NULL };
   3354 
   3355     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
   3356                 kwnames, &flags))
   3357     {
   3358         return NULL;
   3359     }
   3360     CHECK_DB_NOT_CLOSED(self);
   3361     MYDB_BEGIN_ALLOW_THREADS;
   3362     err = self->db->stat_print(self->db, flags);
   3363     MYDB_END_ALLOW_THREADS;
   3364     RETURN_IF_ERR();
   3365     RETURN_NONE();
   3366 }
   3367 
   3368 
   3369 static PyObject*
   3370 DB_sync(DBObject* self, PyObject* args)
   3371 {
   3372     int err;
   3373     int flags = 0;
   3374 
   3375     if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
   3376         return NULL;
   3377     CHECK_DB_NOT_CLOSED(self);
   3378 
   3379     MYDB_BEGIN_ALLOW_THREADS;
   3380     err = self->db->sync(self->db, flags);
   3381     MYDB_END_ALLOW_THREADS;
   3382     RETURN_IF_ERR();
   3383     RETURN_NONE();
   3384 }
   3385 
   3386 
   3387 static PyObject*
   3388 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
   3389 {
   3390     int err, flags=0;
   3391     u_int32_t count=0;
   3392     PyObject* txnobj = NULL;
   3393     DB_TXN *txn = NULL;
   3394     static char* kwnames[] = { "txn", "flags", NULL };
   3395 
   3396     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
   3397                                      &txnobj, &flags))
   3398         return NULL;
   3399     CHECK_DB_NOT_CLOSED(self);
   3400     if (!checkTxnObj(txnobj, &txn))
   3401         return NULL;
   3402 
   3403     MYDB_BEGIN_ALLOW_THREADS;
   3404     err = self->db->truncate(self->db, txn, &count, flags);
   3405     MYDB_END_ALLOW_THREADS;
   3406     RETURN_IF_ERR();
   3407     return NUMBER_FromLong(count);
   3408 }
   3409 
   3410 
   3411 static PyObject*
   3412 DB_upgrade(DBObject* self, PyObject* args)
   3413 {
   3414     int err, flags=0;
   3415     char *filename;
   3416 
   3417     if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
   3418         return NULL;
   3419     CHECK_DB_NOT_CLOSED(self);
   3420 
   3421     MYDB_BEGIN_ALLOW_THREADS;
   3422     err = self->db->upgrade(self->db, filename, flags);
   3423     MYDB_END_ALLOW_THREADS;
   3424     RETURN_IF_ERR();
   3425     RETURN_NONE();
   3426 }
   3427 
   3428 
   3429 static PyObject*
   3430 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
   3431 {
   3432     int err, flags=0;
   3433     char* fileName;
   3434     char* dbName=NULL;
   3435     char* outFileName=NULL;
   3436     FILE* outFile=NULL;
   3437     static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
   3438                                      NULL };
   3439 
   3440     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
   3441                                      &fileName, &dbName, &outFileName, &flags))
   3442         return NULL;
   3443 
   3444     CHECK_DB_NOT_CLOSED(self);
   3445     if (outFileName)
   3446         outFile = fopen(outFileName, "w");
   3447         /* XXX(nnorwitz): it should probably be an exception if outFile
   3448            can't be opened. */
   3449 
   3450     {  /* DB.verify acts as a DB handle destructor (like close) */
   3451         PyObject *error;
   3452 
   3453         error=DB_close_internal(self, 0, 1);
   3454         if (error) {
   3455             if (outFile)
   3456                 fclose(outFile);
   3457             return error;
   3458         }
   3459     }
   3460 
   3461     MYDB_BEGIN_ALLOW_THREADS;
   3462     err = self->db->verify(self->db, fileName, dbName, outFile, flags);
   3463     MYDB_END_ALLOW_THREADS;
   3464 
   3465     self->db = NULL;  /* Implicit close; related objects already released */
   3466 
   3467     if (outFile)
   3468         fclose(outFile);
   3469 
   3470     RETURN_IF_ERR();
   3471     RETURN_NONE();
   3472 }
   3473 
   3474 
   3475 static PyObject*
   3476 DB_set_get_returns_none(DBObject* self, PyObject* args)
   3477 {
   3478     int flags=0;
   3479     int oldValue=0;
   3480 
   3481     if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
   3482         return NULL;
   3483     CHECK_DB_NOT_CLOSED(self);
   3484 
   3485     if (self->moduleFlags.getReturnsNone)
   3486         ++oldValue;
   3487     if (self->moduleFlags.cursorSetReturnsNone)
   3488         ++oldValue;
   3489     self->moduleFlags.getReturnsNone = (flags >= 1);
   3490     self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
   3491     return NUMBER_FromLong(oldValue);
   3492 }
   3493 
   3494 static PyObject*
   3495 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
   3496 {
   3497     int err;
   3498     u_int32_t flags=0;
   3499     char *passwd = NULL;
   3500     static char* kwnames[] = { "passwd", "flags", NULL };
   3501 
   3502     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
   3503                 &passwd, &flags)) {
   3504         return NULL;
   3505     }
   3506 
   3507     MYDB_BEGIN_ALLOW_THREADS;
   3508     err = self->db->set_encrypt(self->db, passwd, flags);
   3509     MYDB_END_ALLOW_THREADS;
   3510 
   3511     RETURN_IF_ERR();
   3512     RETURN_NONE();
   3513 }
   3514 
   3515 static PyObject*
   3516 DB_get_encrypt_flags(DBObject* self)
   3517 {
   3518     int err;
   3519     u_int32_t flags;
   3520 
   3521     MYDB_BEGIN_ALLOW_THREADS;
   3522     err = self->db->get_encrypt_flags(self->db, &flags);
   3523     MYDB_END_ALLOW_THREADS;
   3524 
   3525     RETURN_IF_ERR();
   3526 
   3527     return NUMBER_FromLong(flags);
   3528 }
   3529 
   3530 
   3531 
   3532 /*-------------------------------------------------------------- */
   3533 /* Mapping and Dictionary-like access routines */
   3534 
   3535 Py_ssize_t DB_length(PyObject* _self)
   3536 {
   3537     int err;
   3538     Py_ssize_t size = 0;
   3539     void* sp;
   3540     DBObject* self = (DBObject*)_self;
   3541 
   3542     if (self->db == NULL) {
   3543         PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
   3544         if (t) {
   3545             PyErr_SetObject(DBError, t);
   3546             Py_DECREF(t);
   3547         }
   3548         return -1;
   3549     }
   3550 
   3551     MYDB_BEGIN_ALLOW_THREADS;
   3552     err = self->db->stat(self->db, /*txnid*/ NULL, &sp, 0);
   3553     MYDB_END_ALLOW_THREADS;
   3554 
   3555     /* All the stat structures have matching fields upto the ndata field,
   3556        so we can use any of them for the type cast */
   3557     size = ((DB_BTREE_STAT*)sp)->bt_ndata;
   3558 
   3559     if (err)
   3560         return -1;
   3561 
   3562     free(sp);
   3563     return size;
   3564 }
   3565 
   3566 
   3567 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
   3568 {
   3569     int err;
   3570     PyObject* retval;
   3571     DBT key;
   3572     DBT data;
   3573 
   3574     CHECK_DB_NOT_CLOSED(self);
   3575     if (!make_key_dbt(self, keyobj, &key, NULL))
   3576         return NULL;
   3577 
   3578     CLEAR_DBT(data);
   3579     if (CHECK_DBFLAG(self, DB_THREAD)) {
   3580         /* Tell Berkeley DB to malloc the return value (thread safe) */
   3581         data.flags = DB_DBT_MALLOC;
   3582     }
   3583     MYDB_BEGIN_ALLOW_THREADS;
   3584     err = self->db->get(self->db, NULL, &key, &data, 0);
   3585     MYDB_END_ALLOW_THREADS;
   3586     if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
   3587         PyErr_SetObject(PyExc_KeyError, keyobj);
   3588         retval = NULL;
   3589     }
   3590     else if (makeDBError(err)) {
   3591         retval = NULL;
   3592     }
   3593     else {
   3594         retval = Build_PyString(data.data, data.size);
   3595         FREE_DBT(data);
   3596     }
   3597 
   3598     FREE_DBT(key);
   3599     return retval;
   3600 }
   3601 
   3602 
   3603 static int
   3604 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
   3605 {
   3606     DBT key, data;
   3607     int retval;
   3608     int flags = 0;
   3609 
   3610     if (self->db == NULL) {
   3611         PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
   3612         if (t) {
   3613             PyErr_SetObject(DBError, t);
   3614             Py_DECREF(t);
   3615         }
   3616         return -1;
   3617     }
   3618 
   3619     if (!make_key_dbt(self, keyobj, &key, NULL))
   3620         return -1;
   3621 
   3622     if (dataobj != NULL) {
   3623         if (!make_dbt(dataobj, &data))
   3624             retval =  -1;
   3625         else {
   3626             if (self->setflags & (DB_DUP|DB_DUPSORT))
   3627                 /* dictionaries shouldn't have duplicate keys */
   3628                 flags = DB_NOOVERWRITE;
   3629             retval = _DB_put(self, NULL, &key, &data, flags);
   3630 
   3631             if ((retval == -1) &&  (self->setflags & (DB_DUP|DB_DUPSORT))) {
   3632                 /* try deleting any old record that matches and then PUT it
   3633                  * again... */
   3634                 _DB_delete(self, NULL, &key, 0);
   3635                 PyErr_Clear();
   3636                 retval = _DB_put(self, NULL, &key, &data, flags);
   3637             }
   3638         }
   3639     }
   3640     else {
   3641         /* dataobj == NULL, so delete the key */
   3642         retval = _DB_delete(self, NULL, &key, 0);
   3643     }
   3644     FREE_DBT(key);
   3645     return retval;
   3646 }
   3647 
   3648 
   3649 static PyObject*
   3650 _DB_has_key(DBObject* self, PyObject* keyobj, PyObject* txnobj)
   3651 {
   3652     int err;
   3653     DBT key;
   3654     DB_TXN *txn = NULL;
   3655 
   3656     CHECK_DB_NOT_CLOSED(self);
   3657     if (!make_key_dbt(self, keyobj, &key, NULL))
   3658         return NULL;
   3659     if (!checkTxnObj(txnobj, &txn)) {
   3660         FREE_DBT(key);
   3661         return NULL;
   3662     }
   3663 
   3664 #if (DBVER < 46)
   3665     /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
   3666        it has a record but can't allocate a buffer for the data.  This saves
   3667        having to deal with data we won't be using.
   3668      */
   3669     {
   3670         DBT data ;
   3671         CLEAR_DBT(data);
   3672         data.flags = DB_DBT_USERMEM;
   3673 
   3674         MYDB_BEGIN_ALLOW_THREADS;
   3675         err = self->db->get(self->db, txn, &key, &data, 0);
   3676         MYDB_END_ALLOW_THREADS;
   3677     }
   3678 #else
   3679     MYDB_BEGIN_ALLOW_THREADS;
   3680     err = self->db->exists(self->db, txn, &key, 0);
   3681     MYDB_END_ALLOW_THREADS;
   3682 #endif
   3683 
   3684     FREE_DBT(key);
   3685 
   3686     /*
   3687     ** DB_BUFFER_SMALL is only used if we use "get".
   3688     ** We can drop it when we only use "exists",
   3689     ** when we drop support for Berkeley DB < 4.6.
   3690     */
   3691     if (err == DB_BUFFER_SMALL || err == 0) {
   3692         Py_INCREF(Py_True);
   3693         return Py_True;
   3694     } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
   3695         Py_INCREF(Py_False);
   3696         return Py_False;
   3697     }
   3698 
   3699     makeDBError(err);
   3700     return NULL;
   3701 }
   3702 
   3703 static PyObject*
   3704 DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
   3705 {
   3706     PyObject* keyobj;
   3707     PyObject* txnobj = NULL;
   3708     static char* kwnames[] = {"key","txn", NULL};
   3709 
   3710     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
   3711                 &keyobj, &txnobj))
   3712         return NULL;
   3713 
   3714     return _DB_has_key(self, keyobj, txnobj);
   3715 }
   3716 
   3717 
   3718 static int DB_contains(DBObject* self, PyObject* keyobj)
   3719 {
   3720     PyObject* result;
   3721     int result2 = 0;
   3722 
   3723     result = _DB_has_key(self, keyobj, NULL) ;
   3724     if (result == NULL) {
   3725         return -1; /* Propague exception */
   3726     }
   3727     if (result != Py_False) {
   3728         result2 = 1;
   3729     }
   3730 
   3731     Py_DECREF(result);
   3732     return result2;
   3733 }
   3734 
   3735 
   3736 #define _KEYS_LIST      1
   3737 #define _VALUES_LIST    2
   3738 #define _ITEMS_LIST     3
   3739 
   3740 static PyObject*
   3741 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
   3742 {
   3743     int err, dbtype;
   3744     DBT key;
   3745     DBT data;
   3746     DBC *cursor;
   3747     PyObject* list;
   3748     PyObject* item = NULL;
   3749 
   3750     CHECK_DB_NOT_CLOSED(self);
   3751     CLEAR_DBT(key);
   3752     CLEAR_DBT(data);
   3753 
   3754     dbtype = _DB_get_type(self);
   3755     if (dbtype == -1)
   3756         return NULL;
   3757 
   3758     list = PyList_New(0);
   3759     if (list == NULL)
   3760         return NULL;
   3761 
   3762     /* get a cursor */
   3763     MYDB_BEGIN_ALLOW_THREADS;
   3764     err = self->db->cursor(self->db, txn, &cursor, 0);
   3765     MYDB_END_ALLOW_THREADS;
   3766     if (makeDBError(err)) {
   3767         Py_DECREF(list);
   3768         return NULL;
   3769     }
   3770 
   3771     while (1) { /* use the cursor to traverse the DB, collecting items */
   3772         MYDB_BEGIN_ALLOW_THREADS;
   3773         err = _DBC_get(cursor, &key, &data, DB_NEXT);
   3774         MYDB_END_ALLOW_THREADS;
   3775 
   3776         if (err) {
   3777             /* for any error, break out of the loop */
   3778             break;
   3779         }
   3780 
   3781         switch (type) {
   3782         case _KEYS_LIST:
   3783             switch(dbtype) {
   3784             case DB_BTREE:
   3785             case DB_HASH:
   3786             default:
   3787                 item = Build_PyString(key.data, key.size);
   3788                 break;
   3789             case DB_RECNO:
   3790             case DB_QUEUE:
   3791                 item = NUMBER_FromLong(*((db_recno_t*)key.data));
   3792                 break;
   3793             }
   3794             break;
   3795 
   3796         case _VALUES_LIST:
   3797             item = Build_PyString(data.data, data.size);
   3798             break;
   3799 
   3800         case _ITEMS_LIST:
   3801             switch(dbtype) {
   3802             case DB_BTREE:
   3803             case DB_HASH:
   3804             default:
   3805                 item = BuildValue_SS(key.data, key.size, data.data, data.size);
   3806                 break;
   3807             case DB_RECNO:
   3808             case DB_QUEUE:
   3809                 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
   3810                 break;
   3811             }
   3812             break;
   3813         default:
   3814             PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
   3815             item = NULL;
   3816             break;
   3817         }
   3818         if (item == NULL) {
   3819             Py_DECREF(list);
   3820             list = NULL;
   3821             goto done;
   3822         }
   3823         if (PyList_Append(list, item)) {
   3824             Py_DECREF(list);
   3825             Py_DECREF(item);
   3826             list = NULL;
   3827             goto done;
   3828         }
   3829         Py_DECREF(item);
   3830     }
   3831 
   3832     /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
   3833     if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
   3834         Py_DECREF(list);
   3835         list = NULL;
   3836     }
   3837 
   3838  done:
   3839     MYDB_BEGIN_ALLOW_THREADS;
   3840     _DBC_close(cursor);
   3841     MYDB_END_ALLOW_THREADS;
   3842     return list;
   3843 }
   3844 
   3845 
   3846 static PyObject*
   3847 DB_keys(DBObject* self, PyObject* args)
   3848 {
   3849     PyObject* txnobj = NULL;
   3850     DB_TXN *txn = NULL;
   3851 
   3852     if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
   3853         return NULL;
   3854     if (!checkTxnObj(txnobj, &txn))
   3855         return NULL;
   3856     return _DB_make_list(self, txn, _KEYS_LIST);
   3857 }
   3858 
   3859 
   3860 static PyObject*
   3861 DB_items(DBObject* self, PyObject* args)
   3862 {
   3863     PyObject* txnobj = NULL;
   3864     DB_TXN *txn = NULL;
   3865 
   3866     if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
   3867         return NULL;
   3868     if (!checkTxnObj(txnobj, &txn))
   3869         return NULL;
   3870     return _DB_make_list(self, txn, _ITEMS_LIST);
   3871 }
   3872 
   3873 
   3874 static PyObject*
   3875 DB_values(DBObject* self, PyObject* args)
   3876 {
   3877     PyObject* txnobj = NULL;
   3878     DB_TXN *txn = NULL;
   3879 
   3880     if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
   3881         return NULL;
   3882     if (!checkTxnObj(txnobj, &txn))
   3883         return NULL;
   3884     return _DB_make_list(self, txn, _VALUES_LIST);
   3885 }
   3886 
   3887 /* --------------------------------------------------------------------- */
   3888 /* DBLogCursor methods */
   3889 
   3890 
   3891 static PyObject*
   3892 DBLogCursor_close_internal(DBLogCursorObject* self)
   3893 {
   3894     int err = 0;
   3895 
   3896     if (self->logc != NULL) {
   3897         EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
   3898 
   3899         MYDB_BEGIN_ALLOW_THREADS;
   3900         err = self->logc->close(self->logc, 0);
   3901         MYDB_END_ALLOW_THREADS;
   3902         self->logc = NULL;
   3903     }
   3904     RETURN_IF_ERR();
   3905     RETURN_NONE();
   3906 }
   3907 
   3908 static PyObject*
   3909 DBLogCursor_close(DBLogCursorObject* self)
   3910 {
   3911     return DBLogCursor_close_internal(self);
   3912 }
   3913 
   3914 
   3915 static PyObject*
   3916 _DBLogCursor_get(DBLogCursorObject* self, int flag, DB_LSN *lsn2)
   3917 {
   3918     int err;
   3919     DBT data;
   3920     DB_LSN lsn = {0, 0};
   3921     PyObject *dummy, *retval;
   3922 
   3923     CLEAR_DBT(data);
   3924     data.flags = DB_DBT_MALLOC; /* Berkeley DB must do the malloc */
   3925 
   3926     CHECK_LOGCURSOR_NOT_CLOSED(self);
   3927 
   3928     if (lsn2)
   3929         lsn = *lsn2;
   3930 
   3931     MYDB_BEGIN_ALLOW_THREADS;
   3932     err = self->logc->get(self->logc, &lsn, &data, flag);
   3933     MYDB_END_ALLOW_THREADS;
   3934 
   3935     if (err == DB_NOTFOUND) {
   3936         Py_INCREF(Py_None);
   3937         retval = Py_None;
   3938     }
   3939     else if (makeDBError(err)) {
   3940         retval = NULL;
   3941     }
   3942     else {
   3943         retval = dummy = BuildValue_S(data.data, data.size);
   3944         if (dummy) {
   3945             retval = Py_BuildValue("(ii)O", lsn.file, lsn.offset, dummy);
   3946             Py_DECREF(dummy);
   3947         }
   3948     }
   3949 
   3950     FREE_DBT(data);
   3951     return retval;
   3952 }
   3953 
   3954 static PyObject*
   3955 DBLogCursor_current(DBLogCursorObject* self)
   3956 {
   3957     return _DBLogCursor_get(self, DB_CURRENT, NULL);
   3958 }
   3959 
   3960 static PyObject*
   3961 DBLogCursor_first(DBLogCursorObject* self)
   3962 {
   3963     return _DBLogCursor_get(self, DB_FIRST, NULL);
   3964 }
   3965 
   3966 static PyObject*
   3967 DBLogCursor_last(DBLogCursorObject* self)
   3968 {
   3969     return _DBLogCursor_get(self, DB_LAST, NULL);
   3970 }
   3971 
   3972 static PyObject*
   3973 DBLogCursor_next(DBLogCursorObject* self)
   3974 {
   3975     return _DBLogCursor_get(self, DB_NEXT, NULL);
   3976 }
   3977 
   3978 static PyObject*
   3979 DBLogCursor_prev(DBLogCursorObject* self)
   3980 {
   3981     return _DBLogCursor_get(self, DB_PREV, NULL);
   3982 }
   3983 
   3984 static PyObject*
   3985 DBLogCursor_set(DBLogCursorObject* self, PyObject* args)
   3986 {
   3987     DB_LSN lsn;
   3988 
   3989     if (!PyArg_ParseTuple(args, "(ii):set", &lsn.file, &lsn.offset))
   3990         return NULL;
   3991 
   3992     return _DBLogCursor_get(self, DB_SET, &lsn);
   3993 }
   3994 
   3995 
   3996 /* --------------------------------------------------------------------- */
   3997 /* DBSite methods */
   3998 
   3999 
   4000 #if (DBVER >= 52)
   4001 static PyObject*
   4002 DBSite_close_internal(DBSiteObject* self)
   4003 {
   4004     int err = 0;
   4005 
   4006     if (self->site != NULL) {
   4007         EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
   4008 
   4009         MYDB_BEGIN_ALLOW_THREADS;
   4010         err = self->site->close(self->site);
   4011         MYDB_END_ALLOW_THREADS;
   4012         self->site = NULL;
   4013     }
   4014     RETURN_IF_ERR();
   4015     RETURN_NONE();
   4016 }
   4017 
   4018 static PyObject*
   4019 DBSite_close(DBSiteObject* self)
   4020 {
   4021     return DBSite_close_internal(self);
   4022 }
   4023 
   4024 static PyObject*
   4025 DBSite_remove(DBSiteObject* self)
   4026 {
   4027     int err = 0;
   4028 
   4029     CHECK_SITE_NOT_CLOSED(self);
   4030 
   4031     MYDB_BEGIN_ALLOW_THREADS;
   4032     err = self->site->remove(self->site);
   4033     MYDB_END_ALLOW_THREADS;
   4034 
   4035     RETURN_IF_ERR();
   4036     RETURN_NONE();
   4037 }
   4038 
   4039 static PyObject*
   4040 DBSite_get_eid(DBSiteObject* self)
   4041 {
   4042     int err = 0;
   4043     int eid;
   4044 
   4045     CHECK_SITE_NOT_CLOSED(self);
   4046 
   4047     MYDB_BEGIN_ALLOW_THREADS;
   4048     err = self->site->get_eid(self->site, &eid);
   4049     MYDB_END_ALLOW_THREADS;
   4050 
   4051     RETURN_IF_ERR();
   4052     return NUMBER_FromLong(eid);
   4053 }
   4054 
   4055 static PyObject*
   4056 DBSite_get_address(DBSiteObject* self)
   4057 {
   4058     int err = 0;
   4059     const char *host;
   4060     u_int port;
   4061 
   4062     CHECK_SITE_NOT_CLOSED(self);
   4063 
   4064     MYDB_BEGIN_ALLOW_THREADS;
   4065     err = self->site->get_address(self->site, &host, &port);
   4066     MYDB_END_ALLOW_THREADS;
   4067 
   4068     RETURN_IF_ERR();
   4069 
   4070     return Py_BuildValue("(sI)", host, port);
   4071 }
   4072 
   4073 static PyObject*
   4074 DBSite_get_config(DBSiteObject* self, PyObject* args, PyObject* kwargs)
   4075 {
   4076     int err = 0;
   4077     u_int32_t which, value;
   4078     static char* kwnames[] = { "which", NULL };
   4079 
   4080     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:get_config", kwnames,
   4081                                      &which))
   4082         return NULL;
   4083 
   4084     CHECK_SITE_NOT_CLOSED(self);
   4085 
   4086     MYDB_BEGIN_ALLOW_THREADS;
   4087     err = self->site->get_config(self->site, which, &value);
   4088     MYDB_END_ALLOW_THREADS;
   4089 
   4090     RETURN_IF_ERR();
   4091 
   4092     if (value) {
   4093         Py_INCREF(Py_True);
   4094         return Py_True;
   4095     } else {
   4096         Py_INCREF(Py_False);
   4097         return Py_False;
   4098     }
   4099 }
   4100 
   4101 static PyObject*
   4102 DBSite_set_config(DBSiteObject* self, PyObject* args, PyObject* kwargs)
   4103 {
   4104     int err = 0;
   4105     u_int32_t which, value;
   4106     PyObject *valueO;
   4107     static char* kwnames[] = { "which", "value", NULL };
   4108 
   4109     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO:set_config", kwnames,
   4110                                      &which, &valueO))
   4111         return NULL;
   4112 
   4113     CHECK_SITE_NOT_CLOSED(self);
   4114 
   4115     value = PyObject_IsTrue(valueO);
   4116 
   4117     MYDB_BEGIN_ALLOW_THREADS;
   4118     err = self->site->set_config(self->site, which, value);
   4119     MYDB_END_ALLOW_THREADS;
   4120 
   4121     RETURN_IF_ERR();
   4122     RETURN_NONE();
   4123 }
   4124 #endif
   4125 
   4126 
   4127 /* --------------------------------------------------------------------- */
   4128 /* DBCursor methods */
   4129 
   4130 
   4131 static PyObject*
   4132 DBC_close_internal(DBCursorObject* self)
   4133 {
   4134     int err = 0;
   4135 
   4136     if (self->dbc != NULL) {
   4137         EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
   4138         if (self->txn) {
   4139             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
   4140             self->txn=NULL;
   4141         }
   4142 
   4143         MYDB_BEGIN_ALLOW_THREADS;
   4144         err = _DBC_close(self->dbc);
   4145         MYDB_END_ALLOW_THREADS;
   4146         self->dbc = NULL;
   4147     }
   4148     RETURN_IF_ERR();
   4149     RETURN_NONE();
   4150 }
   4151 
   4152 static PyObject*
   4153 DBC_close(DBCursorObject* self)
   4154 {
   4155     return DBC_close_internal(self);
   4156 }
   4157 
   4158 
   4159 static PyObject*
   4160 DBC_count(DBCursorObject* self, PyObject* args)
   4161 {
   4162     int err = 0;
   4163     db_recno_t count;
   4164     int flags = 0;
   4165 
   4166     if (!PyArg_ParseTuple(args, "|i:count", &flags))
   4167         return NULL;
   4168 
   4169     CHECK_CURSOR_NOT_CLOSED(self);
   4170 
   4171     MYDB_BEGIN_ALLOW_THREADS;
   4172     err = _DBC_count(self->dbc, &count, flags);
   4173     MYDB_END_ALLOW_THREADS;
   4174     RETURN_IF_ERR();
   4175 
   4176     return NUMBER_FromLong(count);
   4177 }
   4178 
   4179 
   4180 static PyObject*
   4181 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4182 {
   4183     return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
   4184 }
   4185 
   4186 
   4187 static PyObject*
   4188 DBC_delete(DBCursorObject* self, PyObject* args)
   4189 {
   4190     int err, flags=0;
   4191 
   4192     if (!PyArg_ParseTuple(args, "|i:delete", &flags))
   4193         return NULL;
   4194 
   4195     CHECK_CURSOR_NOT_CLOSED(self);
   4196 
   4197     MYDB_BEGIN_ALLOW_THREADS;
   4198     err = _DBC_del(self->dbc, flags);
   4199     MYDB_END_ALLOW_THREADS;
   4200     RETURN_IF_ERR();
   4201 
   4202     RETURN_NONE();
   4203 }
   4204 
   4205 
   4206 static PyObject*
   4207 DBC_dup(DBCursorObject* self, PyObject* args)
   4208 {
   4209     int err, flags =0;
   4210     DBC* dbc = NULL;
   4211 
   4212     if (!PyArg_ParseTuple(args, "|i:dup", &flags))
   4213         return NULL;
   4214 
   4215     CHECK_CURSOR_NOT_CLOSED(self);
   4216 
   4217     MYDB_BEGIN_ALLOW_THREADS;
   4218     err = _DBC_dup(self->dbc, &dbc, flags);
   4219     MYDB_END_ALLOW_THREADS;
   4220     RETURN_IF_ERR();
   4221 
   4222     return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
   4223 }
   4224 
   4225 static PyObject*
   4226 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
   4227 {
   4228     return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
   4229 }
   4230 
   4231 
   4232 static PyObject*
   4233 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4234 {
   4235     int err, flags=0;
   4236     PyObject* keyobj = NULL;
   4237     PyObject* dataobj = NULL;
   4238     PyObject* retval = NULL;
   4239     int dlen = -1;
   4240     int doff = -1;
   4241     DBT key, data;
   4242     static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
   4243                                      NULL };
   4244 
   4245     CLEAR_DBT(key);
   4246     CLEAR_DBT(data);
   4247     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
   4248                                      &flags, &dlen, &doff))
   4249     {
   4250         PyErr_Clear();
   4251         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
   4252                                          &kwnames[1],
   4253                                          &keyobj, &flags, &dlen, &doff))
   4254         {
   4255             PyErr_Clear();
   4256             if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
   4257                                              kwnames, &keyobj, &dataobj,
   4258                                              &flags, &dlen, &doff))
   4259             {
   4260                 return NULL;
   4261             }
   4262         }
   4263     }
   4264 
   4265     CHECK_CURSOR_NOT_CLOSED(self);
   4266 
   4267     if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
   4268         return NULL;
   4269     if ( (dataobj && !make_dbt(dataobj, &data)) ||
   4270          (!add_partial_dbt(&data, dlen, doff)) )
   4271     {
   4272         FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
   4273         return NULL;
   4274     }
   4275 
   4276     MYDB_BEGIN_ALLOW_THREADS;
   4277     err = _DBC_get(self->dbc, &key, &data, flags);
   4278     MYDB_END_ALLOW_THREADS;
   4279 
   4280     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   4281             && self->mydb->moduleFlags.getReturnsNone) {
   4282         Py_INCREF(Py_None);
   4283         retval = Py_None;
   4284     }
   4285     else if (makeDBError(err)) {
   4286         retval = NULL;
   4287     }
   4288     else {
   4289         switch (_DB_get_type(self->mydb)) {
   4290         case -1:
   4291             retval = NULL;
   4292             break;
   4293         case DB_BTREE:
   4294         case DB_HASH:
   4295         default:
   4296             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   4297             break;
   4298         case DB_RECNO:
   4299         case DB_QUEUE:
   4300             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
   4301             break;
   4302         }
   4303     }
   4304     FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4305     return retval;
   4306 }
   4307 
   4308 static PyObject*
   4309 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4310 {
   4311     int err, flags=0;
   4312     PyObject* keyobj = NULL;
   4313     PyObject* dataobj = NULL;
   4314     PyObject* retval = NULL;
   4315     int dlen = -1;
   4316     int doff = -1;
   4317     DBT key, pkey, data;
   4318     static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
   4319     static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
   4320 
   4321     CLEAR_DBT(key);
   4322     CLEAR_DBT(data);
   4323     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
   4324                                      &flags, &dlen, &doff))
   4325     {
   4326         PyErr_Clear();
   4327         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
   4328                                          kwnames_keyOnly,
   4329                                          &keyobj, &flags, &dlen, &doff))
   4330         {
   4331             PyErr_Clear();
   4332             if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
   4333                                              kwnames, &keyobj, &dataobj,
   4334                                              &flags, &dlen, &doff))
   4335             {
   4336                 return NULL;
   4337             }
   4338         }
   4339     }
   4340 
   4341     CHECK_CURSOR_NOT_CLOSED(self);
   4342 
   4343     if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
   4344         return NULL;
   4345     if ( (dataobj && !make_dbt(dataobj, &data)) ||
   4346          (!add_partial_dbt(&data, dlen, doff)) ) {
   4347         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4348         return NULL;
   4349     }
   4350 
   4351     CLEAR_DBT(pkey);
   4352     pkey.flags = DB_DBT_MALLOC;
   4353 
   4354     MYDB_BEGIN_ALLOW_THREADS;
   4355     err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
   4356     MYDB_END_ALLOW_THREADS;
   4357 
   4358     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   4359             && self->mydb->moduleFlags.getReturnsNone) {
   4360         Py_INCREF(Py_None);
   4361         retval = Py_None;
   4362     }
   4363     else if (makeDBError(err)) {
   4364         retval = NULL;
   4365     }
   4366     else {
   4367         PyObject *pkeyObj;
   4368         PyObject *dataObj;
   4369         dataObj = Build_PyString(data.data, data.size);
   4370 
   4371         if (self->mydb->primaryDBType == DB_RECNO ||
   4372             self->mydb->primaryDBType == DB_QUEUE)
   4373             pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
   4374         else
   4375             pkeyObj = Build_PyString(pkey.data, pkey.size);
   4376 
   4377         if (key.data && key.size) /* return key, pkey and data */
   4378         {
   4379             PyObject *keyObj;
   4380             int type = _DB_get_type(self->mydb);
   4381             if (type == DB_RECNO || type == DB_QUEUE)
   4382                 keyObj = NUMBER_FromLong(*(int *)key.data);
   4383             else
   4384                 keyObj = Build_PyString(key.data, key.size);
   4385             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
   4386             Py_DECREF(keyObj);
   4387             FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4388         }
   4389         else /* return just the pkey and data */
   4390         {
   4391             retval = PyTuple_Pack(2, pkeyObj, dataObj);
   4392         }
   4393         Py_DECREF(dataObj);
   4394         Py_DECREF(pkeyObj);
   4395         FREE_DBT(pkey);
   4396     }
   4397     /* the only time REALLOC should be set is if we used an integer
   4398      * key that make_key_dbt malloc'd for us.  always free these. */
   4399     if (key.flags & DB_DBT_REALLOC) {  /* 'make_key_dbt' could do a 'malloc' */
   4400         FREE_DBT(key);
   4401     }
   4402     return retval;
   4403 }
   4404 
   4405 
   4406 static PyObject*
   4407 DBC_get_recno(DBCursorObject* self)
   4408 {
   4409     int err;
   4410     db_recno_t recno;
   4411     DBT key;
   4412     DBT data;
   4413 
   4414     CHECK_CURSOR_NOT_CLOSED(self);
   4415 
   4416     CLEAR_DBT(key);
   4417     CLEAR_DBT(data);
   4418 
   4419     MYDB_BEGIN_ALLOW_THREADS;
   4420     err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
   4421     MYDB_END_ALLOW_THREADS;
   4422     RETURN_IF_ERR();
   4423 
   4424     recno = *((db_recno_t*)data.data);
   4425     return NUMBER_FromLong(recno);
   4426 }
   4427 
   4428 
   4429 static PyObject*
   4430 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4431 {
   4432     return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
   4433 }
   4434 
   4435 
   4436 static PyObject*
   4437 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4438 {
   4439     return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
   4440 }
   4441 
   4442 
   4443 static PyObject*
   4444 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4445 {
   4446     return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
   4447 }
   4448 
   4449 
   4450 static PyObject*
   4451 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
   4452 {
   4453     int err, flags = 0;
   4454     PyObject* keyobj, *dataobj;
   4455     DBT key, data;
   4456     static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
   4457                                      NULL };
   4458     int dlen = -1;
   4459     int doff = -1;
   4460 
   4461     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
   4462                                      &keyobj, &dataobj, &flags, &dlen, &doff))
   4463         return NULL;
   4464 
   4465     CHECK_CURSOR_NOT_CLOSED(self);
   4466 
   4467     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
   4468         return NULL;
   4469     if (!make_dbt(dataobj, &data) ||
   4470         !add_partial_dbt(&data, dlen, doff) )
   4471     {
   4472         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4473         return NULL;
   4474     }
   4475 
   4476     MYDB_BEGIN_ALLOW_THREADS;
   4477     err = _DBC_put(self->dbc, &key, &data, flags);
   4478     MYDB_END_ALLOW_THREADS;
   4479     FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4480     RETURN_IF_ERR();
   4481     RETURN_NONE();
   4482 }
   4483 
   4484 
   4485 static PyObject*
   4486 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4487 {
   4488     int err, flags = 0;
   4489     DBT key, data;
   4490     PyObject* retval, *keyobj;
   4491     static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
   4492     int dlen = -1;
   4493     int doff = -1;
   4494 
   4495     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
   4496                                      &keyobj, &flags, &dlen, &doff))
   4497         return NULL;
   4498 
   4499     CHECK_CURSOR_NOT_CLOSED(self);
   4500 
   4501     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
   4502         return NULL;
   4503 
   4504     CLEAR_DBT(data);
   4505     if (!add_partial_dbt(&data, dlen, doff)) {
   4506         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4507         return NULL;
   4508     }
   4509 
   4510     MYDB_BEGIN_ALLOW_THREADS;
   4511     err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
   4512     MYDB_END_ALLOW_THREADS;
   4513     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   4514             && self->mydb->moduleFlags.cursorSetReturnsNone) {
   4515         Py_INCREF(Py_None);
   4516         retval = Py_None;
   4517     }
   4518     else if (makeDBError(err)) {
   4519         retval = NULL;
   4520     }
   4521     else {
   4522         switch (_DB_get_type(self->mydb)) {
   4523         case -1:
   4524             retval = NULL;
   4525             break;
   4526         case DB_BTREE:
   4527         case DB_HASH:
   4528         default:
   4529             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   4530             break;
   4531         case DB_RECNO:
   4532         case DB_QUEUE:
   4533             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
   4534             break;
   4535         }
   4536         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4537     }
   4538     /* the only time REALLOC should be set is if we used an integer
   4539      * key that make_key_dbt malloc'd for us.  always free these. */
   4540     if (key.flags & DB_DBT_REALLOC) {
   4541         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4542     }
   4543 
   4544     return retval;
   4545 }
   4546 
   4547 
   4548 static PyObject*
   4549 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
   4550 {
   4551     int err, flags = 0;
   4552     DBT key, data;
   4553     PyObject* retval, *keyobj;
   4554     static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
   4555     int dlen = -1;
   4556     int doff = -1;
   4557 
   4558     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
   4559                                      &keyobj, &flags, &dlen, &doff))
   4560         return NULL;
   4561 
   4562     CHECK_CURSOR_NOT_CLOSED(self);
   4563 
   4564     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
   4565         return NULL;
   4566 
   4567     CLEAR_DBT(data);
   4568     if (!add_partial_dbt(&data, dlen, doff)) {
   4569         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4570         return NULL;
   4571     }
   4572     MYDB_BEGIN_ALLOW_THREADS;
   4573     err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
   4574     MYDB_END_ALLOW_THREADS;
   4575     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   4576             && self->mydb->moduleFlags.cursorSetReturnsNone) {
   4577         Py_INCREF(Py_None);
   4578         retval = Py_None;
   4579     }
   4580     else if (makeDBError(err)) {
   4581         retval = NULL;
   4582     }
   4583     else {
   4584         switch (_DB_get_type(self->mydb)) {
   4585         case -1:
   4586             retval = NULL;
   4587             break;
   4588         case DB_BTREE:
   4589         case DB_HASH:
   4590         default:
   4591             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   4592             break;
   4593         case DB_RECNO:
   4594         case DB_QUEUE:
   4595             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
   4596             break;
   4597         }
   4598         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4599     }
   4600     /* the only time REALLOC should be set is if we used an integer
   4601      * key that make_key_dbt malloc'd for us.  always free these. */
   4602     if (key.flags & DB_DBT_REALLOC) {
   4603         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4604     }
   4605 
   4606     return retval;
   4607 }
   4608 
   4609 static PyObject*
   4610 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
   4611                   int flags, unsigned int returnsNone)
   4612 {
   4613     int err;
   4614     DBT key, data;
   4615     PyObject* retval;
   4616 
   4617     /* the caller did this:  CHECK_CURSOR_NOT_CLOSED(self); */
   4618     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
   4619         return NULL;
   4620     if (!make_dbt(dataobj, &data)) {
   4621         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4622         return NULL;
   4623     }
   4624 
   4625     MYDB_BEGIN_ALLOW_THREADS;
   4626     err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
   4627     MYDB_END_ALLOW_THREADS;
   4628     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
   4629         Py_INCREF(Py_None);
   4630         retval = Py_None;
   4631     }
   4632     else if (makeDBError(err)) {
   4633         retval = NULL;
   4634     }
   4635     else {
   4636         switch (_DB_get_type(self->mydb)) {
   4637         case -1:
   4638             retval = NULL;
   4639             break;
   4640         case DB_BTREE:
   4641         case DB_HASH:
   4642         default:
   4643             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   4644             break;
   4645         case DB_RECNO:
   4646         case DB_QUEUE:
   4647             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
   4648             break;
   4649         }
   4650     }
   4651 
   4652     FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
   4653     return retval;
   4654 }
   4655 
   4656 static PyObject*
   4657 DBC_get_both(DBCursorObject* self, PyObject* args)
   4658 {
   4659     int flags=0;
   4660     PyObject *keyobj, *dataobj;
   4661 
   4662     if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
   4663         return NULL;
   4664 
   4665     /* if the cursor is closed, self->mydb may be invalid */
   4666     CHECK_CURSOR_NOT_CLOSED(self);
   4667 
   4668     return _DBC_get_set_both(self, keyobj, dataobj, flags,
   4669                 self->mydb->moduleFlags.getReturnsNone);
   4670 }
   4671 
   4672 /* Return size of entry */
   4673 static PyObject*
   4674 DBC_get_current_size(DBCursorObject* self)
   4675 {
   4676     int err, flags=DB_CURRENT;
   4677     PyObject* retval = NULL;
   4678     DBT key, data;
   4679 
   4680     CHECK_CURSOR_NOT_CLOSED(self);
   4681     CLEAR_DBT(key);
   4682     CLEAR_DBT(data);
   4683 
   4684     /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
   4685        getting the record size. */
   4686     data.flags = DB_DBT_USERMEM;
   4687     data.ulen = 0;
   4688     MYDB_BEGIN_ALLOW_THREADS;
   4689     err = _DBC_get(self->dbc, &key, &data, flags);
   4690     MYDB_END_ALLOW_THREADS;
   4691     if (err == DB_BUFFER_SMALL || !err) {
   4692         /* DB_BUFFER_SMALL means positive size, !err means zero length value */
   4693         retval = NUMBER_FromLong((long)data.size);
   4694         err = 0;
   4695     }
   4696 
   4697     RETURN_IF_ERR();
   4698     return retval;
   4699 }
   4700 
   4701 static PyObject*
   4702 DBC_set_both(DBCursorObject* self, PyObject* args)
   4703 {
   4704     int flags=0;
   4705     PyObject *keyobj, *dataobj;
   4706 
   4707     if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
   4708         return NULL;
   4709 
   4710     /* if the cursor is closed, self->mydb may be invalid */
   4711     CHECK_CURSOR_NOT_CLOSED(self);
   4712 
   4713     return _DBC_get_set_both(self, keyobj, dataobj, flags,
   4714                 self->mydb->moduleFlags.cursorSetReturnsNone);
   4715 }
   4716 
   4717 
   4718 static PyObject*
   4719 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4720 {
   4721     int err, irecno, flags=0;
   4722     db_recno_t recno;
   4723     DBT key, data;
   4724     PyObject* retval;
   4725     int dlen = -1;
   4726     int doff = -1;
   4727     static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
   4728 
   4729     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
   4730                                      &irecno, &flags, &dlen, &doff))
   4731       return NULL;
   4732 
   4733     CHECK_CURSOR_NOT_CLOSED(self);
   4734 
   4735     CLEAR_DBT(key);
   4736     recno = (db_recno_t) irecno;
   4737     /* use allocated space so DB will be able to realloc room for the real
   4738      * key */
   4739     key.data = malloc(sizeof(db_recno_t));
   4740     if (key.data == NULL) {
   4741         PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
   4742         return NULL;
   4743     }
   4744     key.size = sizeof(db_recno_t);
   4745     key.ulen = key.size;
   4746     memcpy(key.data, &recno, sizeof(db_recno_t));
   4747     key.flags = DB_DBT_REALLOC;
   4748 
   4749     CLEAR_DBT(data);
   4750     if (!add_partial_dbt(&data, dlen, doff)) {
   4751         FREE_DBT(key);
   4752         return NULL;
   4753     }
   4754 
   4755     MYDB_BEGIN_ALLOW_THREADS;
   4756     err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
   4757     MYDB_END_ALLOW_THREADS;
   4758     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   4759             && self->mydb->moduleFlags.cursorSetReturnsNone) {
   4760         Py_INCREF(Py_None);
   4761         retval = Py_None;
   4762     }
   4763     else if (makeDBError(err)) {
   4764         retval = NULL;
   4765     }
   4766     else {  /* Can only be used for BTrees, so no need to return int key */
   4767         retval = BuildValue_SS(key.data, key.size, data.data, data.size);
   4768     }
   4769     FREE_DBT(key);
   4770 
   4771     return retval;
   4772 }
   4773 
   4774 
   4775 static PyObject*
   4776 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4777 {
   4778     return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
   4779 }
   4780 
   4781 
   4782 static PyObject*
   4783 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4784 {
   4785     return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
   4786 }
   4787 
   4788 
   4789 static PyObject*
   4790 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4791 {
   4792     return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
   4793 }
   4794 
   4795 #if (DBVER >= 46)
   4796 static PyObject*
   4797 DBC_prev_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4798 {
   4799     return _DBCursor_get(self,DB_PREV_DUP,args,kwargs,"|iii:prev_dup");
   4800 }
   4801 #endif
   4802 
   4803 static PyObject*
   4804 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
   4805 {
   4806     return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
   4807 }
   4808 
   4809 
   4810 static PyObject*
   4811 DBC_join_item(DBCursorObject* self, PyObject* args)
   4812 {
   4813     int err, flags=0;
   4814     DBT key, data;
   4815     PyObject* retval;
   4816 
   4817     if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
   4818         return NULL;
   4819 
   4820     CHECK_CURSOR_NOT_CLOSED(self);
   4821 
   4822     CLEAR_DBT(key);
   4823     CLEAR_DBT(data);
   4824 
   4825     MYDB_BEGIN_ALLOW_THREADS;
   4826     err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
   4827     MYDB_END_ALLOW_THREADS;
   4828     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
   4829             && self->mydb->moduleFlags.getReturnsNone) {
   4830         Py_INCREF(Py_None);
   4831         retval = Py_None;
   4832     }
   4833     else if (makeDBError(err)) {
   4834         retval = NULL;
   4835     }
   4836     else {
   4837         retval = BuildValue_S(key.data, key.size);
   4838     }
   4839 
   4840     return retval;
   4841 }
   4842 
   4843 
   4844 #if (DBVER >= 46)
   4845 static PyObject*
   4846 DBC_set_priority(DBCursorObject* self, PyObject* args, PyObject* kwargs)
   4847 {
   4848     int err, priority;
   4849     static char* kwnames[] = { "priority", NULL };
   4850 
   4851     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_priority", kwnames,
   4852                                      &priority))
   4853         return NULL;
   4854 
   4855     CHECK_CURSOR_NOT_CLOSED(self);
   4856 
   4857     MYDB_BEGIN_ALLOW_THREADS;
   4858     err = self->dbc->set_priority(self->dbc, priority);
   4859     MYDB_END_ALLOW_THREADS;
   4860     RETURN_IF_ERR();
   4861     RETURN_NONE();
   4862 }
   4863 
   4864 
   4865 static PyObject*
   4866 DBC_get_priority(DBCursorObject* self)
   4867 {
   4868     int err;
   4869     DB_CACHE_PRIORITY priority;
   4870 
   4871     CHECK_CURSOR_NOT_CLOSED(self);
   4872 
   4873     MYDB_BEGIN_ALLOW_THREADS;
   4874     err = self->dbc->get_priority(self->dbc, &priority);
   4875     MYDB_END_ALLOW_THREADS;
   4876     RETURN_IF_ERR();
   4877     return NUMBER_FromLong(priority);
   4878 }
   4879 #endif
   4880 
   4881 
   4882 
   4883 /* --------------------------------------------------------------------- */
   4884 /* DBEnv methods */
   4885 
   4886 
   4887 static PyObject*
   4888 DBEnv_close_internal(DBEnvObject* self, int flags)
   4889 {
   4890     PyObject *dummy;
   4891     int err;
   4892 
   4893     if (!self->closed) {      /* Don't close more than once */
   4894         while(self->children_txns) {
   4895             dummy = DBTxn_abort_discard_internal(self->children_txns, 0);
   4896             Py_XDECREF(dummy);
   4897         }
   4898         while(self->children_dbs) {
   4899             dummy = DB_close_internal(self->children_dbs, 0, 0);
   4900             Py_XDECREF(dummy);
   4901         }
   4902         while(self->children_logcursors) {
   4903             dummy = DBLogCursor_close_internal(self->children_logcursors);
   4904             Py_XDECREF(dummy);
   4905         }
   4906 #if (DBVER >= 52)
   4907         while(self->children_sites) {
   4908             dummy = DBSite_close_internal(self->children_sites);
   4909             Py_XDECREF(dummy);
   4910         }
   4911 #endif
   4912     }
   4913 
   4914     self->closed = 1;
   4915     if (self->db_env) {
   4916         MYDB_BEGIN_ALLOW_THREADS;
   4917         err = self->db_env->close(self->db_env, flags);
   4918         MYDB_END_ALLOW_THREADS;
   4919         /* after calling DBEnv->close, regardless of error, this DBEnv
   4920          * may not be accessed again (Berkeley DB docs). */
   4921         self->db_env = NULL;
   4922         RETURN_IF_ERR();
   4923     }
   4924     RETURN_NONE();
   4925 }
   4926 
   4927 static PyObject*
   4928 DBEnv_close(DBEnvObject* self, PyObject* args)
   4929 {
   4930     int flags = 0;
   4931 
   4932     if (!PyArg_ParseTuple(args, "|i:close", &flags))
   4933         return NULL;
   4934     return DBEnv_close_internal(self, flags);
   4935 }
   4936 
   4937 
   4938 static PyObject*
   4939 DBEnv_open(DBEnvObject* self, PyObject* args)
   4940 {
   4941     int err, flags=0, mode=0660;
   4942     char *db_home;
   4943 
   4944     if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
   4945         return NULL;
   4946 
   4947     CHECK_ENV_NOT_CLOSED(self);
   4948 
   4949     MYDB_BEGIN_ALLOW_THREADS;
   4950     err = self->db_env->open(self->db_env, db_home, flags, mode);
   4951     MYDB_END_ALLOW_THREADS;
   4952     RETURN_IF_ERR();
   4953     self->closed = 0;
   4954     self->flags = flags;
   4955     RETURN_NONE();
   4956 }
   4957 
   4958 
   4959 static PyObject*
   4960 DBEnv_memp_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   4961 {
   4962     int err;
   4963     DB_MPOOL_STAT *gsp;
   4964     DB_MPOOL_FSTAT **fsp, **fsp2;
   4965     PyObject* d = NULL, *d2, *d3, *r;
   4966     u_int32_t flags = 0;
   4967     static char* kwnames[] = { "flags", NULL };
   4968 
   4969     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat",
   4970                 kwnames, &flags))
   4971         return NULL;
   4972 
   4973     CHECK_ENV_NOT_CLOSED(self);
   4974 
   4975     MYDB_BEGIN_ALLOW_THREADS;
   4976     err = self->db_env->memp_stat(self->db_env, &gsp, &fsp, flags);
   4977     MYDB_END_ALLOW_THREADS;
   4978     RETURN_IF_ERR();
   4979 
   4980     /* Turn the stat structure into a dictionary */
   4981     d = PyDict_New();
   4982     if (d == NULL) {
   4983         if (gsp)
   4984             free(gsp);
   4985         return NULL;
   4986     }
   4987 
   4988 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, gsp->st_##name)
   4989 
   4990     MAKE_ENTRY(gbytes);
   4991     MAKE_ENTRY(bytes);
   4992     MAKE_ENTRY(ncache);
   4993 #if (DBVER >= 46)
   4994     MAKE_ENTRY(max_ncache);
   4995 #endif
   4996     MAKE_ENTRY(regsize);
   4997     MAKE_ENTRY(mmapsize);
   4998     MAKE_ENTRY(maxopenfd);
   4999     MAKE_ENTRY(maxwrite);
   5000     MAKE_ENTRY(maxwrite_sleep);
   5001     MAKE_ENTRY(map);
   5002     MAKE_ENTRY(cache_hit);
   5003     MAKE_ENTRY(cache_miss);
   5004     MAKE_ENTRY(page_create);
   5005     MAKE_ENTRY(page_in);
   5006     MAKE_ENTRY(page_out);
   5007     MAKE_ENTRY(ro_evict);
   5008     MAKE_ENTRY(rw_evict);
   5009     MAKE_ENTRY(page_trickle);
   5010     MAKE_ENTRY(pages);
   5011     MAKE_ENTRY(page_clean);
   5012     MAKE_ENTRY(page_dirty);
   5013     MAKE_ENTRY(hash_buckets);
   5014     MAKE_ENTRY(hash_searches);
   5015     MAKE_ENTRY(hash_longest);
   5016     MAKE_ENTRY(hash_examined);
   5017     MAKE_ENTRY(hash_nowait);
   5018     MAKE_ENTRY(hash_wait);
   5019 #if (DBVER >= 45)
   5020     MAKE_ENTRY(hash_max_nowait);
   5021 #endif
   5022     MAKE_ENTRY(hash_max_wait);
   5023     MAKE_ENTRY(region_wait);
   5024     MAKE_ENTRY(region_nowait);
   5025 #if (DBVER >= 45)
   5026     MAKE_ENTRY(mvcc_frozen);
   5027     MAKE_ENTRY(mvcc_thawed);
   5028     MAKE_ENTRY(mvcc_freed);
   5029 #endif
   5030     MAKE_ENTRY(alloc);
   5031     MAKE_ENTRY(alloc_buckets);
   5032     MAKE_ENTRY(alloc_max_buckets);
   5033     MAKE_ENTRY(alloc_pages);
   5034     MAKE_ENTRY(alloc_max_pages);
   5035 #if (DBVER >= 45)
   5036     MAKE_ENTRY(io_wait);
   5037 #endif
   5038 #if (DBVER >= 48)
   5039     MAKE_ENTRY(sync_interrupted);
   5040 #endif
   5041 
   5042 #undef MAKE_ENTRY
   5043     free(gsp);
   5044 
   5045     d2 = PyDict_New();
   5046     if (d2 == NULL) {
   5047         Py_DECREF(d);
   5048         if (fsp)
   5049             free(fsp);
   5050         return NULL;
   5051     }
   5052 #define MAKE_ENTRY(name)  _addIntToDict(d3, #name, (*fsp2)->st_##name)
   5053     for(fsp2=fsp;*fsp2; fsp2++) {
   5054         d3 = PyDict_New();
   5055         if (d3 == NULL) {
   5056             Py_DECREF(d);
   5057             Py_DECREF(d2);
   5058             if (fsp)
   5059                 free(fsp);
   5060             return NULL;
   5061         }
   5062         MAKE_ENTRY(pagesize);
   5063         MAKE_ENTRY(cache_hit);
   5064         MAKE_ENTRY(cache_miss);
   5065         MAKE_ENTRY(map);
   5066         MAKE_ENTRY(page_create);
   5067         MAKE_ENTRY(page_in);
   5068         MAKE_ENTRY(page_out);
   5069         if(PyDict_SetItemString(d2, (*fsp2)->file_name, d3)) {
   5070             Py_DECREF(d);
   5071             Py_DECREF(d2);
   5072             Py_DECREF(d3);
   5073             if (fsp)
   5074                 free(fsp);
   5075             return NULL;
   5076         }
   5077         Py_DECREF(d3);
   5078     }
   5079 
   5080 #undef MAKE_ENTRY
   5081     free(fsp);
   5082 
   5083     r = PyTuple_Pack(2, d, d2);
   5084     Py_DECREF(d);
   5085     Py_DECREF(d2);
   5086     return r;
   5087 }
   5088 
   5089 static PyObject*
   5090 DBEnv_memp_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   5091 {
   5092     int err;
   5093     int flags=0;
   5094     static char* kwnames[] = { "flags", NULL };
   5095 
   5096     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat_print",
   5097                 kwnames, &flags))
   5098     {
   5099         return NULL;
   5100     }
   5101     CHECK_ENV_NOT_CLOSED(self);
   5102     MYDB_BEGIN_ALLOW_THREADS;
   5103     err = self->db_env->memp_stat_print(self->db_env, flags);
   5104     MYDB_END_ALLOW_THREADS;
   5105     RETURN_IF_ERR();
   5106     RETURN_NONE();
   5107 }
   5108 
   5109 
   5110 static PyObject*
   5111 DBEnv_memp_trickle(DBEnvObject* self, PyObject* args)
   5112 {
   5113     int err, percent, nwrotep;
   5114 
   5115     if (!PyArg_ParseTuple(args, "i:memp_trickle", &percent))
   5116         return NULL;
   5117     CHECK_ENV_NOT_CLOSED(self);
   5118     MYDB_BEGIN_ALLOW_THREADS;
   5119     err = self->db_env->memp_trickle(self->db_env, percent, &nwrotep);
   5120     MYDB_END_ALLOW_THREADS;
   5121     RETURN_IF_ERR();
   5122     return NUMBER_FromLong(nwrotep);
   5123 }
   5124 
   5125 static PyObject*
   5126 DBEnv_memp_sync(DBEnvObject* self, PyObject* args)
   5127 {
   5128     int err;
   5129     DB_LSN lsn = {0, 0};
   5130     DB_LSN *lsn_p = NULL;
   5131 
   5132     if (!PyArg_ParseTuple(args, "|(ii):memp_sync", &lsn.file, &lsn.offset))
   5133         return NULL;
   5134     if ((lsn.file!=0) || (lsn.offset!=0)) {
   5135         lsn_p = &lsn;
   5136     }
   5137     CHECK_ENV_NOT_CLOSED(self);
   5138     MYDB_BEGIN_ALLOW_THREADS;
   5139     err = self->db_env->memp_sync(self->db_env, lsn_p);
   5140     MYDB_END_ALLOW_THREADS;
   5141     RETURN_IF_ERR();
   5142     RETURN_NONE();
   5143 }
   5144 
   5145 static PyObject*
   5146 DBEnv_remove(DBEnvObject* self, PyObject* args)
   5147 {
   5148     int err, flags=0;
   5149     char *db_home;
   5150 
   5151     if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
   5152         return NULL;
   5153     CHECK_ENV_NOT_CLOSED(self);
   5154     MYDB_BEGIN_ALLOW_THREADS;
   5155     err = self->db_env->remove(self->db_env, db_home, flags);
   5156     MYDB_END_ALLOW_THREADS;
   5157     RETURN_IF_ERR();
   5158     RETURN_NONE();
   5159 }
   5160 
   5161 static PyObject*
   5162 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   5163 {
   5164     int err;
   5165     u_int32_t flags=0;
   5166     char *file = NULL;
   5167     char *database = NULL;
   5168     PyObject *txnobj = NULL;
   5169     DB_TXN *txn = NULL;
   5170     static char* kwnames[] = { "file", "database", "txn", "flags",
   5171                                      NULL };
   5172 
   5173     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
   5174                 &file, &database, &txnobj, &flags)) {
   5175         return NULL;
   5176     }
   5177     if (!checkTxnObj(txnobj, &txn)) {
   5178         return NULL;
   5179     }
   5180     CHECK_ENV_NOT_CLOSED(self);
   5181     MYDB_BEGIN_ALLOW_THREADS;
   5182     err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
   5183     MYDB_END_ALLOW_THREADS;
   5184     RETURN_IF_ERR();
   5185     RETURN_NONE();
   5186 }
   5187 
   5188 static PyObject*
   5189 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   5190 {
   5191     int err;
   5192     u_int32_t flags=0;
   5193     char *file = NULL;
   5194     char *database = NULL;
   5195     char *newname = NULL;
   5196     PyObject *txnobj = NULL;
   5197     DB_TXN *txn = NULL;
   5198     static char* kwnames[] = { "file", "database", "newname", "txn",
   5199                                      "flags", NULL };
   5200 
   5201     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
   5202                 &file, &database, &newname, &txnobj, &flags)) {
   5203         return NULL;
   5204     }
   5205     if (!checkTxnObj(txnobj, &txn)) {
   5206         return NULL;
   5207     }
   5208     CHECK_ENV_NOT_CLOSED(self);
   5209     MYDB_BEGIN_ALLOW_THREADS;
   5210     err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
   5211                                  flags);
   5212     MYDB_END_ALLOW_THREADS;
   5213     RETURN_IF_ERR();
   5214     RETURN_NONE();
   5215 }
   5216 
   5217 
   5218 
   5219 static PyObject*
   5220 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   5221 {
   5222     int err;
   5223     u_int32_t flags=0;
   5224     char *passwd = NULL;
   5225     static char* kwnames[] = { "passwd", "flags", NULL };
   5226 
   5227     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
   5228                 &passwd, &flags)) {
   5229         return NULL;
   5230     }
   5231 
   5232     MYDB_BEGIN_ALLOW_THREADS;
   5233     err = self->db_env->set_encrypt(self->db_env, passwd, flags);
   5234     MYDB_END_ALLOW_THREADS;
   5235 
   5236     RETURN_IF_ERR();
   5237     RETURN_NONE();
   5238 }
   5239 
   5240 static PyObject*
   5241 DBEnv_get_encrypt_flags(DBEnvObject* self)
   5242 {
   5243     int err;
   5244     u_int32_t flags;
   5245 
   5246     CHECK_ENV_NOT_CLOSED(self);
   5247 
   5248     MYDB_BEGIN_ALLOW_THREADS;
   5249     err = self->db_env->get_encrypt_flags(self->db_env, &flags);
   5250     MYDB_END_ALLOW_THREADS;
   5251 
   5252     RETURN_IF_ERR();
   5253 
   5254     return NUMBER_FromLong(flags);
   5255 }
   5256 
   5257 static PyObject*
   5258 DBEnv_get_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   5259 {
   5260     int err;
   5261     int flag;
   5262     u_int32_t timeout;
   5263     static char* kwnames[] = {"flag", NULL };
   5264 
   5265     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:get_timeout", kwnames,
   5266                 &flag)) {
   5267         return NULL;
   5268     }
   5269     CHECK_ENV_NOT_CLOSED(self);
   5270 
   5271     MYDB_BEGIN_ALLOW_THREADS;
   5272     err = self->db_env->get_timeout(self->db_env, &timeout, flag);
   5273     MYDB_END_ALLOW_THREADS;
   5274     RETURN_IF_ERR();
   5275     return NUMBER_FromLong(timeout);
   5276 }
   5277 
   5278 
   5279 static PyObject*
   5280 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   5281 {
   5282     int err;
   5283     u_int32_t flags=0;
   5284     u_int32_t timeout = 0;
   5285     static char* kwnames[] = { "timeout", "flags", NULL };
   5286 
   5287     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
   5288                 &timeout, &flags)) {
   5289         return NULL;
   5290     }
   5291 
   5292     MYDB_BEGIN_ALLOW_THREADS;
   5293     err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
   5294     MYDB_END_ALLOW_THREADS;
   5295 
   5296     RETURN_IF_ERR();
   5297     RETURN_NONE();
   5298 }
   5299 
   5300 static PyObject*
   5301 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
   5302 {
   5303     int err;
   5304     long shm_key = 0;
   5305 
   5306     if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
   5307         return NULL;
   5308     CHECK_ENV_NOT_CLOSED(self);
   5309 
   5310     err = self->db_env->set_shm_key(self->db_env, shm_key);
   5311     RETURN_IF_ERR();
   5312     RETURN_NONE();
   5313 }
   5314 
   5315 static PyObject*
   5316 DBEnv_get_shm_key(DBEnvObject* self)
   5317 {
   5318     int err;
   5319     long shm_key;
   5320 
   5321     CHECK_ENV_NOT_CLOSED(self);
   5322 
   5323     MYDB_BEGIN_ALLOW_THREADS;
   5324     err = self->db_env->get_shm_key(self->db_env, &shm_key);
   5325     MYDB_END_ALLOW_THREADS;
   5326 
   5327     RETURN_IF_ERR();
   5328 
   5329     return NUMBER_FromLong(shm_key);
   5330 }
   5331 
   5332 #if (DBVER >= 46)
   5333 static PyObject*
   5334 DBEnv_set_cache_max(DBEnvObject* self, PyObject* args)
   5335 {
   5336     int err, gbytes, bytes;
   5337 
   5338     if (!PyArg_ParseTuple(args, "ii:set_cache_max",
   5339                           &gbytes, &bytes))
   5340         return NULL;
   5341     CHECK_ENV_NOT_CLOSED(self);
   5342 
   5343     MYDB_BEGIN_ALLOW_THREADS;
   5344     err = self->db_env->set_cache_max(self->db_env, gbytes, bytes);
   5345     MYDB_END_ALLOW_THREADS;
   5346     RETURN_IF_ERR();
   5347     RETURN_NONE();
   5348 }
   5349 
   5350 static PyObject*
   5351 DBEnv_get_cache_max(DBEnvObject* self)
   5352 {
   5353     int err;
   5354     u_int32_t gbytes, bytes;
   5355 
   5356     CHECK_ENV_NOT_CLOSED(self);
   5357 
   5358     MYDB_BEGIN_ALLOW_THREADS;
   5359     err = self->db_env->get_cache_max(self->db_env, &gbytes, &bytes);
   5360     MYDB_END_ALLOW_THREADS;
   5361 
   5362     RETURN_IF_ERR();
   5363 
   5364     return Py_BuildValue("(ii)", gbytes, bytes);
   5365 }
   5366 #endif
   5367 
   5368 #if (DBVER >= 46)
   5369 static PyObject*
   5370 DBEnv_set_thread_count(DBEnvObject* self, PyObject* args)
   5371 {
   5372     int err;
   5373     u_int32_t count;
   5374 
   5375     if (!PyArg_ParseTuple(args, "i:set_thread_count", &count))
   5376         return NULL;
   5377     CHECK_ENV_NOT_CLOSED(self);
   5378 
   5379     MYDB_BEGIN_ALLOW_THREADS;
   5380     err = self->db_env->set_thread_count(self->db_env, count);
   5381     MYDB_END_ALLOW_THREADS;
   5382     RETURN_IF_ERR();
   5383     RETURN_NONE();
   5384 }
   5385 
   5386 static PyObject*
   5387 DBEnv_get_thread_count(DBEnvObject* self)
   5388 {
   5389     int err;
   5390     u_int32_t count;
   5391 
   5392     CHECK_ENV_NOT_CLOSED(self);
   5393 
   5394     MYDB_BEGIN_ALLOW_THREADS;
   5395     err = self->db_env->get_thread_count(self->db_env, &count);
   5396     MYDB_END_ALLOW_THREADS;
   5397     RETURN_IF_ERR();
   5398     return NUMBER_FromLong(count);
   5399 }
   5400 #endif
   5401 
   5402 static PyObject*
   5403 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
   5404 {
   5405     int err, gbytes=0, bytes=0, ncache=0;
   5406 
   5407     if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
   5408                           &gbytes, &bytes, &ncache))
   5409         return NULL;
   5410     CHECK_ENV_NOT_CLOSED(self);
   5411 
   5412     MYDB_BEGIN_ALLOW_THREADS;
   5413     err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
   5414     MYDB_END_ALLOW_THREADS;
   5415     RETURN_IF_ERR();
   5416     RETURN_NONE();
   5417 }
   5418 
   5419 static PyObject*
   5420 DBEnv_get_cachesize(DBEnvObject* self)
   5421 {
   5422     int err;
   5423     u_int32_t gbytes, bytes;
   5424     int ncache;
   5425 
   5426     CHECK_ENV_NOT_CLOSED(self);
   5427 
   5428     MYDB_BEGIN_ALLOW_THREADS;
   5429     err = self->db_env->get_cachesize(self->db_env, &gbytes, &bytes, &ncache);
   5430     MYDB_END_ALLOW_THREADS;
   5431 
   5432     RETURN_IF_ERR();
   5433 
   5434     return Py_BuildValue("(iii)", gbytes, bytes, ncache);
   5435 }
   5436 
   5437 
   5438 static PyObject*
   5439 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
   5440 {
   5441     int err, flags=0, onoff=0;
   5442 
   5443     if (!PyArg_ParseTuple(args, "ii:set_flags",
   5444                           &flags, &onoff))
   5445         return NULL;
   5446     CHECK_ENV_NOT_CLOSED(self);
   5447 
   5448     MYDB_BEGIN_ALLOW_THREADS;
   5449     err = self->db_env->set_flags(self->db_env, flags, onoff);
   5450     MYDB_END_ALLOW_THREADS;
   5451     RETURN_IF_ERR();
   5452     RETURN_NONE();
   5453 }
   5454 
   5455 static PyObject*
   5456 DBEnv_get_flags(DBEnvObject* self)
   5457 {
   5458     int err;
   5459     u_int32_t flags;
   5460 
   5461     CHECK_ENV_NOT_CLOSED(self);
   5462 
   5463     MYDB_BEGIN_ALLOW_THREADS;
   5464     err = self->db_env->get_flags(self->db_env, &flags);
   5465     MYDB_END_ALLOW_THREADS;
   5466     RETURN_IF_ERR();
   5467     return NUMBER_FromLong(flags);
   5468 }
   5469 
   5470 #if (DBVER >= 47)
   5471 static PyObject*
   5472 DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
   5473 {
   5474     int err, flags, onoff;
   5475 
   5476     if (!PyArg_ParseTuple(args, "ii:log_set_config",
   5477                           &flags, &onoff))
   5478         return NULL;
   5479     CHECK_ENV_NOT_CLOSED(self);
   5480 
   5481     MYDB_BEGIN_ALLOW_THREADS;
   5482     err = self->db_env->log_set_config(self->db_env, flags, onoff);
   5483     MYDB_END_ALLOW_THREADS;
   5484     RETURN_IF_ERR();
   5485     RETURN_NONE();
   5486 }
   5487 
   5488 static PyObject*
   5489 DBEnv_log_get_config(DBEnvObject* self, PyObject* args)
   5490 {
   5491     int err, flag, onoff;
   5492 
   5493     if (!PyArg_ParseTuple(args, "i:log_get_config", &flag))
   5494         return NULL;
   5495     CHECK_ENV_NOT_CLOSED(self);
   5496 
   5497     MYDB_BEGIN_ALLOW_THREADS;
   5498     err = self->db_env->log_get_config(self->db_env, flag, &onoff);
   5499     MYDB_END_ALLOW_THREADS;
   5500     RETURN_IF_ERR();
   5501     return PyBool_FromLong(onoff);
   5502 }
   5503 #endif /* DBVER >= 47 */
   5504 
   5505 #if (DBVER >= 44)
   5506 static PyObject*
   5507 DBEnv_mutex_set_max(DBEnvObject* self, PyObject* args)
   5508 {
   5509     int err;
   5510     int value;
   5511 
   5512     if (!PyArg_ParseTuple(args, "i:mutex_set_max", &value))
   5513         return NULL;
   5514 
   5515     CHECK_ENV_NOT_CLOSED(self);
   5516 
   5517     MYDB_BEGIN_ALLOW_THREADS;
   5518     err = self->db_env->mutex_set_max(self->db_env, value);
   5519     MYDB_END_ALLOW_THREADS;
   5520 
   5521     RETURN_IF_ERR();
   5522     RETURN_NONE();
   5523 }
   5524 
   5525 static PyObject*
   5526 DBEnv_mutex_get_max(DBEnvObject* self)
   5527 {
   5528     int err;
   5529     u_int32_t value;
   5530 
   5531     CHECK_ENV_NOT_CLOSED(self);
   5532 
   5533     MYDB_BEGIN_ALLOW_THREADS;
   5534     err = self->db_env->mutex_get_max(self->db_env, &value);
   5535     MYDB_END_ALLOW_THREADS;
   5536 
   5537     RETURN_IF_ERR();
   5538 
   5539     return NUMBER_FromLong(value);
   5540 }
   5541 
   5542 static PyObject*
   5543 DBEnv_mutex_set_align(DBEnvObject* self, PyObject* args)
   5544 {
   5545     int err;
   5546     int align;
   5547 
   5548     if (!PyArg_ParseTuple(args, "i:mutex_set_align", &align))
   5549         return NULL;
   5550 
   5551     CHECK_ENV_NOT_CLOSED(self);
   5552 
   5553     MYDB_BEGIN_ALLOW_THREADS;
   5554     err = self->db_env->mutex_set_align(self->db_env, align);
   5555     MYDB_END_ALLOW_THREADS;
   5556 
   5557     RETURN_IF_ERR();
   5558     RETURN_NONE();
   5559 }
   5560 
   5561 static PyObject*
   5562 DBEnv_mutex_get_align(DBEnvObject* self)
   5563 {
   5564     int err;
   5565     u_int32_t align;
   5566 
   5567     CHECK_ENV_NOT_CLOSED(self);
   5568 
   5569     MYDB_BEGIN_ALLOW_THREADS;
   5570     err = self->db_env->mutex_get_align(self->db_env, &align);
   5571     MYDB_END_ALLOW_THREADS;
   5572 
   5573     RETURN_IF_ERR();
   5574 
   5575     return NUMBER_FromLong(align);
   5576 }
   5577 
   5578 static PyObject*
   5579 DBEnv_mutex_set_increment(DBEnvObject* self, PyObject* args)
   5580 {
   5581     int err;
   5582     int increment;
   5583 
   5584     if (!PyArg_ParseTuple(args, "i:mutex_set_increment", &increment))
   5585         return NULL;
   5586 
   5587     CHECK_ENV_NOT_CLOSED(self);
   5588 
   5589     MYDB_BEGIN_ALLOW_THREADS;
   5590     err = self->db_env->mutex_set_increment(self->db_env, increment);
   5591     MYDB_END_ALLOW_THREADS;
   5592 
   5593     RETURN_IF_ERR();
   5594     RETURN_NONE();
   5595 }
   5596 
   5597 static PyObject*
   5598 DBEnv_mutex_get_increment(DBEnvObject* self)
   5599 {
   5600     int err;
   5601     u_int32_t increment;
   5602 
   5603     CHECK_ENV_NOT_CLOSED(self);
   5604 
   5605     MYDB_BEGIN_ALLOW_THREADS;
   5606     err = self->db_env->mutex_get_increment(self->db_env, &increment);
   5607     MYDB_END_ALLOW_THREADS;
   5608 
   5609     RETURN_IF_ERR();
   5610 
   5611     return NUMBER_FromLong(increment);
   5612 }
   5613 
   5614 static PyObject*
   5615 DBEnv_mutex_set_tas_spins(DBEnvObject* self, PyObject* args)
   5616 {
   5617     int err;
   5618     int tas_spins;
   5619 
   5620     if (!PyArg_ParseTuple(args, "i:mutex_set_tas_spins", &tas_spins))
   5621         return NULL;
   5622 
   5623     CHECK_ENV_NOT_CLOSED(self);
   5624 
   5625     MYDB_BEGIN_ALLOW_THREADS;
   5626     err = self->db_env->mutex_set_tas_spins(self->db_env, tas_spins);
   5627     MYDB_END_ALLOW_THREADS;
   5628 
   5629     RETURN_IF_ERR();
   5630     RETURN_NONE();
   5631 }
   5632 
   5633 static PyObject*
   5634 DBEnv_mutex_get_tas_spins(DBEnvObject* self)
   5635 {
   5636     int err;
   5637     u_int32_t tas_spins;
   5638 
   5639     CHECK_ENV_NOT_CLOSED(self);
   5640 
   5641     MYDB_BEGIN_ALLOW_THREADS;
   5642     err = self->db_env->mutex_get_tas_spins(self->db_env, &tas_spins);
   5643     MYDB_END_ALLOW_THREADS;
   5644 
   5645     RETURN_IF_ERR();
   5646 
   5647     return NUMBER_FromLong(tas_spins);
   5648 }
   5649 #endif
   5650 
   5651 static PyObject*
   5652 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
   5653 {
   5654     int err;
   5655     char *dir;
   5656 
   5657     if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
   5658         return NULL;
   5659     CHECK_ENV_NOT_CLOSED(self);
   5660 
   5661     MYDB_BEGIN_ALLOW_THREADS;
   5662     err = self->db_env->set_data_dir(self->db_env, dir);
   5663     MYDB_END_ALLOW_THREADS;
   5664     RETURN_IF_ERR();
   5665     RETURN_NONE();
   5666 }
   5667 
   5668 static PyObject*
   5669 DBEnv_get_data_dirs(DBEnvObject* self)
   5670 {
   5671     int err;
   5672     PyObject *tuple;
   5673     PyObject *item;
   5674     const char **dirpp;
   5675     int size, i;
   5676 
   5677     CHECK_ENV_NOT_CLOSED(self);
   5678 
   5679     MYDB_BEGIN_ALLOW_THREADS;
   5680     err = self->db_env->get_data_dirs(self->db_env, &dirpp);
   5681     MYDB_END_ALLOW_THREADS;
   5682 
   5683     RETURN_IF_ERR();
   5684 
   5685     /*
   5686     ** Calculate size. Python C API
   5687     ** actually allows for tuple resizing,
   5688     ** but this is simple enough.
   5689     */
   5690     for (size=0; *(dirpp+size) ; size++);
   5691 
   5692     tuple = PyTuple_New(size);
   5693     if (!tuple)
   5694         return NULL;
   5695 
   5696     for (i=0; i<size; i++) {
   5697         item = PyBytes_FromString (*(dirpp+i));
   5698         if (item == NULL) {
   5699             Py_DECREF(tuple);
   5700             tuple = NULL;
   5701             break;
   5702         }
   5703         PyTuple_SET_ITEM(tuple, i, item);
   5704     }
   5705     return tuple;
   5706 }
   5707 
   5708 #if (DBVER >= 44)
   5709 static PyObject*
   5710 DBEnv_set_lg_filemode(DBEnvObject* self, PyObject* args)
   5711 {
   5712     int err, filemode;
   5713 
   5714     if (!PyArg_ParseTuple(args, "i:set_lg_filemode", &filemode))
   5715         return NULL;
   5716     CHECK_ENV_NOT_CLOSED(self);
   5717 
   5718     MYDB_BEGIN_ALLOW_THREADS;
   5719     err = self->db_env->set_lg_filemode(self->db_env, filemode);
   5720     MYDB_END_ALLOW_THREADS;
   5721     RETURN_IF_ERR();
   5722     RETURN_NONE();
   5723 }
   5724 
   5725 static PyObject*
   5726 DBEnv_get_lg_filemode(DBEnvObject* self)
   5727 {
   5728     int err, filemode;
   5729 
   5730     CHECK_ENV_NOT_CLOSED(self);
   5731 
   5732     MYDB_BEGIN_ALLOW_THREADS;
   5733     err = self->db_env->get_lg_filemode(self->db_env, &filemode);
   5734     MYDB_END_ALLOW_THREADS;
   5735     RETURN_IF_ERR();
   5736     return NUMBER_FromLong(filemode);
   5737 }
   5738 #endif
   5739 
   5740 static PyObject*
   5741 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
   5742 {
   5743     int err, lg_bsize;
   5744 
   5745     if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
   5746         return NULL;
   5747     CHECK_ENV_NOT_CLOSED(self);
   5748 
   5749     MYDB_BEGIN_ALLOW_THREADS;
   5750     err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
   5751     MYDB_END_ALLOW_THREADS;
   5752     RETURN_IF_ERR();
   5753     RETURN_NONE();
   5754 }
   5755 
   5756 static PyObject*
   5757 DBEnv_get_lg_bsize(DBEnvObject* self)
   5758 {
   5759     int err;
   5760     u_int32_t lg_bsize;
   5761 
   5762     CHECK_ENV_NOT_CLOSED(self);
   5763 
   5764     MYDB_BEGIN_ALLOW_THREADS;
   5765     err = self->db_env->get_lg_bsize(self->db_env, &lg_bsize);
   5766     MYDB_END_ALLOW_THREADS;
   5767     RETURN_IF_ERR();
   5768     return NUMBER_FromLong(lg_bsize);
   5769 }
   5770 
   5771 static PyObject*
   5772 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
   5773 {
   5774     int err;
   5775     char *dir;
   5776 
   5777     if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
   5778         return NULL;
   5779     CHECK_ENV_NOT_CLOSED(self);
   5780 
   5781     MYDB_BEGIN_ALLOW_THREADS;
   5782     err = self->db_env->set_lg_dir(self->db_env, dir);
   5783     MYDB_END_ALLOW_THREADS;
   5784     RETURN_IF_ERR();
   5785     RETURN_NONE();
   5786 }
   5787 
   5788 static PyObject*
   5789 DBEnv_get_lg_dir(DBEnvObject* self)
   5790 {
   5791     int err;
   5792     const char *dirp;
   5793 
   5794     CHECK_ENV_NOT_CLOSED(self);
   5795 
   5796     MYDB_BEGIN_ALLOW_THREADS;
   5797     err = self->db_env->get_lg_dir(self->db_env, &dirp);
   5798     MYDB_END_ALLOW_THREADS;
   5799     RETURN_IF_ERR();
   5800     return PyBytes_FromString(dirp);
   5801 }
   5802 
   5803 static PyObject*
   5804 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
   5805 {
   5806     int err, lg_max;
   5807 
   5808     if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
   5809         return NULL;
   5810     CHECK_ENV_NOT_CLOSED(self);
   5811 
   5812     MYDB_BEGIN_ALLOW_THREADS;
   5813     err = self->db_env->set_lg_max(self->db_env, lg_max);
   5814     MYDB_END_ALLOW_THREADS;
   5815     RETURN_IF_ERR();
   5816     RETURN_NONE();
   5817 }
   5818 
   5819 static PyObject*
   5820 DBEnv_get_lg_max(DBEnvObject* self)
   5821 {
   5822     int err;
   5823     u_int32_t lg_max;
   5824 
   5825     CHECK_ENV_NOT_CLOSED(self);
   5826 
   5827     MYDB_BEGIN_ALLOW_THREADS;
   5828     err = self->db_env->get_lg_max(self->db_env, &lg_max);
   5829     MYDB_END_ALLOW_THREADS;
   5830     RETURN_IF_ERR();
   5831     return NUMBER_FromLong(lg_max);
   5832 }
   5833 
   5834 static PyObject*
   5835 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
   5836 {
   5837     int err, lg_max;
   5838 
   5839     if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
   5840         return NULL;
   5841     CHECK_ENV_NOT_CLOSED(self);
   5842 
   5843     MYDB_BEGIN_ALLOW_THREADS;
   5844     err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
   5845     MYDB_END_ALLOW_THREADS;
   5846     RETURN_IF_ERR();
   5847     RETURN_NONE();
   5848 }
   5849 
   5850 static PyObject*
   5851 DBEnv_get_lg_regionmax(DBEnvObject* self)
   5852 {
   5853     int err;
   5854     u_int32_t lg_regionmax;
   5855 
   5856     CHECK_ENV_NOT_CLOSED(self);
   5857 
   5858     MYDB_BEGIN_ALLOW_THREADS;
   5859     err = self->db_env->get_lg_regionmax(self->db_env, &lg_regionmax);
   5860     MYDB_END_ALLOW_THREADS;
   5861     RETURN_IF_ERR();
   5862     return NUMBER_FromLong(lg_regionmax);
   5863 }
   5864 
   5865 #if (DBVER >= 47)
   5866 static PyObject*
   5867 DBEnv_set_lk_partitions(DBEnvObject* self, PyObject* args)
   5868 {
   5869     int err, lk_partitions;
   5870 
   5871     if (!PyArg_ParseTuple(args, "i:set_lk_partitions", &lk_partitions))
   5872         return NULL;
   5873     CHECK_ENV_NOT_CLOSED(self);
   5874 
   5875     MYDB_BEGIN_ALLOW_THREADS;
   5876     err = self->db_env->set_lk_partitions(self->db_env, lk_partitions);
   5877     MYDB_END_ALLOW_THREADS;
   5878     RETURN_IF_ERR();
   5879     RETURN_NONE();
   5880 }
   5881 
   5882 static PyObject*
   5883 DBEnv_get_lk_partitions(DBEnvObject* self)
   5884 {
   5885     int err;
   5886     u_int32_t lk_partitions;
   5887 
   5888     CHECK_ENV_NOT_CLOSED(self);
   5889 
   5890     MYDB_BEGIN_ALLOW_THREADS;
   5891     err = self->db_env->get_lk_partitions(self->db_env, &lk_partitions);
   5892     MYDB_END_ALLOW_THREADS;
   5893     RETURN_IF_ERR();
   5894     return NUMBER_FromLong(lk_partitions);
   5895 }
   5896 #endif
   5897 
   5898 static PyObject*
   5899 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
   5900 {
   5901     int err, lk_detect;
   5902 
   5903     if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
   5904         return NULL;
   5905     CHECK_ENV_NOT_CLOSED(self);
   5906 
   5907     MYDB_BEGIN_ALLOW_THREADS;
   5908     err = self->db_env->set_lk_detect(self->db_env, lk_detect);
   5909     MYDB_END_ALLOW_THREADS;
   5910     RETURN_IF_ERR();
   5911     RETURN_NONE();
   5912 }
   5913 
   5914 static PyObject*
   5915 DBEnv_get_lk_detect(DBEnvObject* self)
   5916 {
   5917     int err;
   5918     u_int32_t lk_detect;
   5919 
   5920     CHECK_ENV_NOT_CLOSED(self);
   5921 
   5922     MYDB_BEGIN_ALLOW_THREADS;
   5923     err = self->db_env->get_lk_detect(self->db_env, &lk_detect);
   5924     MYDB_END_ALLOW_THREADS;
   5925     RETURN_IF_ERR();
   5926     return NUMBER_FromLong(lk_detect);
   5927 }
   5928 
   5929 #if (DBVER < 45)
   5930 static PyObject*
   5931 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
   5932 {
   5933     int err, max;
   5934 
   5935     if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
   5936         return NULL;
   5937     CHECK_ENV_NOT_CLOSED(self);
   5938 
   5939     MYDB_BEGIN_ALLOW_THREADS;
   5940     err = self->db_env->set_lk_max(self->db_env, max);
   5941     MYDB_END_ALLOW_THREADS;
   5942     RETURN_IF_ERR();
   5943     RETURN_NONE();
   5944 }
   5945 #endif
   5946 
   5947 
   5948 
   5949 static PyObject*
   5950 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
   5951 {
   5952     int err, max;
   5953 
   5954     if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
   5955         return NULL;
   5956     CHECK_ENV_NOT_CLOSED(self);
   5957 
   5958     MYDB_BEGIN_ALLOW_THREADS;
   5959     err = self->db_env->set_lk_max_locks(self->db_env, max);
   5960     MYDB_END_ALLOW_THREADS;
   5961     RETURN_IF_ERR();
   5962     RETURN_NONE();
   5963 }
   5964 
   5965 static PyObject*
   5966 DBEnv_get_lk_max_locks(DBEnvObject* self)
   5967 {
   5968     int err;
   5969     u_int32_t lk_max;
   5970 
   5971     CHECK_ENV_NOT_CLOSED(self);
   5972 
   5973     MYDB_BEGIN_ALLOW_THREADS;
   5974     err = self->db_env->get_lk_max_locks(self->db_env, &lk_max);
   5975     MYDB_END_ALLOW_THREADS;
   5976     RETURN_IF_ERR();
   5977     return NUMBER_FromLong(lk_max);
   5978 }
   5979 
   5980 static PyObject*
   5981 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
   5982 {
   5983     int err, max;
   5984 
   5985     if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
   5986         return NULL;
   5987     CHECK_ENV_NOT_CLOSED(self);
   5988 
   5989     MYDB_BEGIN_ALLOW_THREADS;
   5990     err = self->db_env->set_lk_max_lockers(self->db_env, max);
   5991     MYDB_END_ALLOW_THREADS;
   5992     RETURN_IF_ERR();
   5993     RETURN_NONE();
   5994 }
   5995 
   5996 static PyObject*
   5997 DBEnv_get_lk_max_lockers(DBEnvObject* self)
   5998 {
   5999     int err;
   6000     u_int32_t lk_max;
   6001 
   6002     CHECK_ENV_NOT_CLOSED(self);
   6003 
   6004     MYDB_BEGIN_ALLOW_THREADS;
   6005     err = self->db_env->get_lk_max_lockers(self->db_env, &lk_max);
   6006     MYDB_END_ALLOW_THREADS;
   6007     RETURN_IF_ERR();
   6008     return NUMBER_FromLong(lk_max);
   6009 }
   6010 
   6011 static PyObject*
   6012 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
   6013 {
   6014     int err, max;
   6015 
   6016     if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
   6017         return NULL;
   6018     CHECK_ENV_NOT_CLOSED(self);
   6019 
   6020     MYDB_BEGIN_ALLOW_THREADS;
   6021     err = self->db_env->set_lk_max_objects(self->db_env, max);
   6022     MYDB_END_ALLOW_THREADS;
   6023     RETURN_IF_ERR();
   6024     RETURN_NONE();
   6025 }
   6026 
   6027 static PyObject*
   6028 DBEnv_get_lk_max_objects(DBEnvObject* self)
   6029 {
   6030     int err;
   6031     u_int32_t lk_max;
   6032 
   6033     CHECK_ENV_NOT_CLOSED(self);
   6034 
   6035     MYDB_BEGIN_ALLOW_THREADS;
   6036     err = self->db_env->get_lk_max_objects(self->db_env, &lk_max);
   6037     MYDB_END_ALLOW_THREADS;
   6038     RETURN_IF_ERR();
   6039     return NUMBER_FromLong(lk_max);
   6040 }
   6041 
   6042 static PyObject*
   6043 DBEnv_get_mp_mmapsize(DBEnvObject* self)
   6044 {
   6045     int err;
   6046     size_t mmapsize;
   6047 
   6048     CHECK_ENV_NOT_CLOSED(self);
   6049 
   6050     MYDB_BEGIN_ALLOW_THREADS;
   6051     err = self->db_env->get_mp_mmapsize(self->db_env, &mmapsize);
   6052     MYDB_END_ALLOW_THREADS;
   6053     RETURN_IF_ERR();
   6054     return NUMBER_FromLong(mmapsize);
   6055 }
   6056 
   6057 static PyObject*
   6058 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
   6059 {
   6060     int err, mp_mmapsize;
   6061 
   6062     if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
   6063         return NULL;
   6064     CHECK_ENV_NOT_CLOSED(self);
   6065 
   6066     MYDB_BEGIN_ALLOW_THREADS;
   6067     err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
   6068     MYDB_END_ALLOW_THREADS;
   6069     RETURN_IF_ERR();
   6070     RETURN_NONE();
   6071 }
   6072 
   6073 
   6074 static PyObject*
   6075 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
   6076 {
   6077     int err;
   6078     char *dir;
   6079 
   6080     if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
   6081         return NULL;
   6082     CHECK_ENV_NOT_CLOSED(self);
   6083 
   6084     MYDB_BEGIN_ALLOW_THREADS;
   6085     err = self->db_env->set_tmp_dir(self->db_env, dir);
   6086     MYDB_END_ALLOW_THREADS;
   6087     RETURN_IF_ERR();
   6088     RETURN_NONE();
   6089 }
   6090 
   6091 static PyObject*
   6092 DBEnv_get_tmp_dir(DBEnvObject* self)
   6093 {
   6094     int err;
   6095     const char *dirpp;
   6096 
   6097     CHECK_ENV_NOT_CLOSED(self);
   6098 
   6099     MYDB_BEGIN_ALLOW_THREADS;
   6100     err = self->db_env->get_tmp_dir(self->db_env, &dirpp);
   6101     MYDB_END_ALLOW_THREADS;
   6102 
   6103     RETURN_IF_ERR();
   6104 
   6105     return PyBytes_FromString(dirpp);
   6106 }
   6107 
   6108 static PyObject*
   6109 DBEnv_txn_recover(DBEnvObject* self)
   6110 {
   6111     int flags = DB_FIRST;
   6112     int err, i;
   6113     PyObject *list, *tuple, *gid;
   6114     DBTxnObject *txn;
   6115 #define PREPLIST_LEN 16
   6116     DB_PREPLIST preplist[PREPLIST_LEN];
   6117 #if (DBVER < 48) || (DBVER >= 52)
   6118     long retp;
   6119 #else
   6120     u_int32_t retp;
   6121 #endif
   6122 
   6123     CHECK_ENV_NOT_CLOSED(self);
   6124 
   6125     list=PyList_New(0);
   6126     if (!list)
   6127         return NULL;
   6128     while (!0) {
   6129         MYDB_BEGIN_ALLOW_THREADS
   6130         err=self->db_env->txn_recover(self->db_env,
   6131                         preplist, PREPLIST_LEN, &retp, flags);
   6132 #undef PREPLIST_LEN
   6133         MYDB_END_ALLOW_THREADS
   6134         if (err) {
   6135             Py_DECREF(list);
   6136             RETURN_IF_ERR();
   6137         }
   6138         if (!retp) break;
   6139         flags=DB_NEXT;  /* Prepare for next loop pass */
   6140         for (i=0; i<retp; i++) {
   6141             gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
   6142                                 DB_GID_SIZE);
   6143             if (!gid) {
   6144                 Py_DECREF(list);
   6145                 return NULL;
   6146             }
   6147             txn=newDBTxnObject(self, NULL, preplist[i].txn, 0);
   6148             if (!txn) {
   6149                 Py_DECREF(list);
   6150                 Py_DECREF(gid);
   6151                 return NULL;
   6152             }
   6153             txn->flag_prepare=1;  /* Recover state */
   6154             tuple=PyTuple_New(2);
   6155             if (!tuple) {
   6156                 Py_DECREF(list);
   6157                 Py_DECREF(gid);
   6158                 Py_DECREF(txn);
   6159                 return NULL;
   6160             }
   6161             if (PyTuple_SetItem(tuple, 0, gid)) {
   6162                 Py_DECREF(list);
   6163                 Py_DECREF(gid);
   6164                 Py_DECREF(txn);
   6165                 Py_DECREF(tuple);
   6166                 return NULL;
   6167             }
   6168             if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
   6169                 Py_DECREF(list);
   6170                 Py_DECREF(txn);
   6171                 Py_DECREF(tuple); /* This delete the "gid" also */
   6172                 return NULL;
   6173             }
   6174             if (PyList_Append(list, tuple)) {
   6175                 Py_DECREF(list);
   6176                 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
   6177                 return NULL;
   6178             }
   6179             Py_DECREF(tuple);
   6180         }
   6181     }
   6182     return list;
   6183 }
   6184 
   6185 static PyObject*
   6186 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   6187 {
   6188     int flags = 0;
   6189     PyObject* txnobj = NULL;
   6190     DB_TXN *txn = NULL;
   6191     static char* kwnames[] = { "parent", "flags", NULL };
   6192 
   6193     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
   6194                                      &txnobj, &flags))
   6195         return NULL;
   6196 
   6197     if (!checkTxnObj(txnobj, &txn))
   6198         return NULL;
   6199     CHECK_ENV_NOT_CLOSED(self);
   6200 
   6201     return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
   6202 }
   6203 
   6204 
   6205 static PyObject*
   6206 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
   6207 {
   6208     int err, kbyte=0, min=0, flags=0;
   6209 
   6210     if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
   6211         return NULL;
   6212     CHECK_ENV_NOT_CLOSED(self);
   6213 
   6214     MYDB_BEGIN_ALLOW_THREADS;
   6215     err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
   6216     MYDB_END_ALLOW_THREADS;
   6217     RETURN_IF_ERR();
   6218     RETURN_NONE();
   6219 }
   6220 
   6221 static PyObject*
   6222 DBEnv_get_tx_max(DBEnvObject* self)
   6223 {
   6224     int err;
   6225     u_int32_t max;
   6226 
   6227     CHECK_ENV_NOT_CLOSED(self);
   6228 
   6229     MYDB_BEGIN_ALLOW_THREADS;
   6230     err = self->db_env->get_tx_max(self->db_env, &max);
   6231     MYDB_END_ALLOW_THREADS;
   6232     RETURN_IF_ERR();
   6233     return PyLong_FromUnsignedLong(max);
   6234 }
   6235 
   6236 static PyObject*
   6237 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
   6238 {
   6239     int err, max;
   6240 
   6241     if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
   6242         return NULL;
   6243     CHECK_ENV_NOT_CLOSED(self);
   6244 
   6245     MYDB_BEGIN_ALLOW_THREADS;
   6246     err = self->db_env->set_tx_max(self->db_env, max);
   6247     MYDB_END_ALLOW_THREADS;
   6248     RETURN_IF_ERR();
   6249     RETURN_NONE();
   6250 }
   6251 
   6252 static PyObject*
   6253 DBEnv_get_tx_timestamp(DBEnvObject* self)
   6254 {
   6255     int err;
   6256     time_t timestamp;
   6257 
   6258     CHECK_ENV_NOT_CLOSED(self);
   6259 
   6260     MYDB_BEGIN_ALLOW_THREADS;
   6261     err = self->db_env->get_tx_timestamp(self->db_env, &timestamp);
   6262     MYDB_END_ALLOW_THREADS;
   6263     RETURN_IF_ERR();
   6264     return NUMBER_FromLong(timestamp);
   6265 }
   6266 
   6267 static PyObject*
   6268 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
   6269 {
   6270     int err;
   6271     long stamp;
   6272     time_t timestamp;
   6273 
   6274     if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
   6275         return NULL;
   6276     CHECK_ENV_NOT_CLOSED(self);
   6277     timestamp = (time_t)stamp;
   6278     MYDB_BEGIN_ALLOW_THREADS;
   6279     err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
   6280     MYDB_END_ALLOW_THREADS;
   6281     RETURN_IF_ERR();
   6282     RETURN_NONE();
   6283 }
   6284 
   6285 
   6286 static PyObject*
   6287 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
   6288 {
   6289     int err, atype, flags=0;
   6290     int aborted = 0;
   6291 
   6292     if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
   6293         return NULL;
   6294     CHECK_ENV_NOT_CLOSED(self);
   6295 
   6296     MYDB_BEGIN_ALLOW_THREADS;
   6297     err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
   6298     MYDB_END_ALLOW_THREADS;
   6299     RETURN_IF_ERR();
   6300     return NUMBER_FromLong(aborted);
   6301 }
   6302 
   6303 
   6304 static PyObject*
   6305 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
   6306 {
   6307     int flags=0;
   6308     int locker, lock_mode;
   6309     DBT obj;
   6310     PyObject* objobj;
   6311 
   6312     if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
   6313         return NULL;
   6314 
   6315 
   6316     if (!make_dbt(objobj, &obj))
   6317         return NULL;
   6318 
   6319     return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
   6320 }
   6321 
   6322 
   6323 static PyObject*
   6324 DBEnv_lock_id(DBEnvObject* self)
   6325 {
   6326     int err;
   6327     u_int32_t theID;
   6328 
   6329     CHECK_ENV_NOT_CLOSED(self);
   6330     MYDB_BEGIN_ALLOW_THREADS;
   6331     err = self->db_env->lock_id(self->db_env, &theID);
   6332     MYDB_END_ALLOW_THREADS;
   6333     RETURN_IF_ERR();
   6334 
   6335     return NUMBER_FromLong((long)theID);
   6336 }
   6337 
   6338 static PyObject*
   6339 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
   6340 {
   6341     int err;
   6342     u_int32_t theID;
   6343 
   6344     if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
   6345         return NULL;
   6346 
   6347     CHECK_ENV_NOT_CLOSED(self);
   6348     MYDB_BEGIN_ALLOW_THREADS;
   6349     err = self->db_env->lock_id_free(self->db_env, theID);
   6350     MYDB_END_ALLOW_THREADS;
   6351     RETURN_IF_ERR();
   6352     RETURN_NONE();
   6353 }
   6354 
   6355 static PyObject*
   6356 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
   6357 {
   6358     int err;
   6359     DBLockObject* dblockobj;
   6360 
   6361     if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
   6362         return NULL;
   6363 
   6364     CHECK_ENV_NOT_CLOSED(self);
   6365     MYDB_BEGIN_ALLOW_THREADS;
   6366     err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
   6367     MYDB_END_ALLOW_THREADS;
   6368     RETURN_IF_ERR();
   6369     RETURN_NONE();
   6370 }
   6371 
   6372 #if (DBVER >= 44)
   6373 static PyObject*
   6374 DBEnv_fileid_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   6375 {
   6376     int err;
   6377     char *file;
   6378     u_int32_t flags = 0;
   6379     static char* kwnames[] = { "file", "flags", NULL};
   6380 
   6381     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:fileid_reset", kwnames,
   6382                                      &file, &flags))
   6383         return NULL;
   6384     CHECK_ENV_NOT_CLOSED(self);
   6385 
   6386     MYDB_BEGIN_ALLOW_THREADS;
   6387     err = self->db_env->fileid_reset(self->db_env, file, flags);
   6388     MYDB_END_ALLOW_THREADS;
   6389     RETURN_IF_ERR();
   6390     RETURN_NONE();
   6391 }
   6392 
   6393 static PyObject*
   6394 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   6395 {
   6396     int err;
   6397     char *file;
   6398     u_int32_t flags = 0;
   6399     static char* kwnames[] = { "file", "flags", NULL};
   6400 
   6401     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
   6402                                      &file, &flags))
   6403         return NULL;
   6404     CHECK_ENV_NOT_CLOSED(self);
   6405 
   6406     MYDB_BEGIN_ALLOW_THREADS;
   6407     err = self->db_env->lsn_reset(self->db_env, file, flags);
   6408     MYDB_END_ALLOW_THREADS;
   6409     RETURN_IF_ERR();
   6410     RETURN_NONE();
   6411 }
   6412 #endif /* DBVER >= 4.4 */
   6413 
   6414 
   6415 static PyObject*
   6416 DBEnv_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6417 {
   6418     int err;
   6419     int flags=0;
   6420     static char* kwnames[] = { "flags", NULL };
   6421 
   6422     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
   6423                 kwnames, &flags))
   6424     {
   6425         return NULL;
   6426     }
   6427     CHECK_ENV_NOT_CLOSED(self);
   6428     MYDB_BEGIN_ALLOW_THREADS;
   6429     err = self->db_env->stat_print(self->db_env, flags);
   6430     MYDB_END_ALLOW_THREADS;
   6431     RETURN_IF_ERR();
   6432     RETURN_NONE();
   6433 }
   6434 
   6435 
   6436 static PyObject*
   6437 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
   6438 {
   6439     int err;
   6440     DB_LOG_STAT* statp = NULL;
   6441     PyObject* d = NULL;
   6442     u_int32_t flags = 0;
   6443 
   6444     if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
   6445         return NULL;
   6446     CHECK_ENV_NOT_CLOSED(self);
   6447 
   6448     MYDB_BEGIN_ALLOW_THREADS;
   6449     err = self->db_env->log_stat(self->db_env, &statp, flags);
   6450     MYDB_END_ALLOW_THREADS;
   6451     RETURN_IF_ERR();
   6452 
   6453     /* Turn the stat structure into a dictionary */
   6454     d = PyDict_New();
   6455     if (d == NULL) {
   6456         if (statp)
   6457             free(statp);
   6458         return NULL;
   6459     }
   6460 
   6461 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, statp->st_##name)
   6462 
   6463     MAKE_ENTRY(magic);
   6464     MAKE_ENTRY(version);
   6465     MAKE_ENTRY(mode);
   6466     MAKE_ENTRY(lg_bsize);
   6467 #if (DBVER >= 44)
   6468     MAKE_ENTRY(lg_size);
   6469     MAKE_ENTRY(record);
   6470 #endif
   6471     MAKE_ENTRY(w_mbytes);
   6472     MAKE_ENTRY(w_bytes);
   6473     MAKE_ENTRY(wc_mbytes);
   6474     MAKE_ENTRY(wc_bytes);
   6475     MAKE_ENTRY(wcount);
   6476     MAKE_ENTRY(wcount_fill);
   6477 #if (DBVER >= 44)
   6478     MAKE_ENTRY(rcount);
   6479 #endif
   6480     MAKE_ENTRY(scount);
   6481     MAKE_ENTRY(cur_file);
   6482     MAKE_ENTRY(cur_offset);
   6483     MAKE_ENTRY(disk_file);
   6484     MAKE_ENTRY(disk_offset);
   6485     MAKE_ENTRY(maxcommitperflush);
   6486     MAKE_ENTRY(mincommitperflush);
   6487     MAKE_ENTRY(regsize);
   6488     MAKE_ENTRY(region_wait);
   6489     MAKE_ENTRY(region_nowait);
   6490 
   6491 #undef MAKE_ENTRY
   6492     free(statp);
   6493     return d;
   6494 } /* DBEnv_log_stat */
   6495 
   6496 
   6497 static PyObject*
   6498 DBEnv_log_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6499 {
   6500     int err;
   6501     int flags=0;
   6502     static char* kwnames[] = { "flags", NULL };
   6503 
   6504     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:log_stat_print",
   6505                 kwnames, &flags))
   6506     {
   6507         return NULL;
   6508     }
   6509     CHECK_ENV_NOT_CLOSED(self);
   6510     MYDB_BEGIN_ALLOW_THREADS;
   6511     err = self->db_env->log_stat_print(self->db_env, flags);
   6512     MYDB_END_ALLOW_THREADS;
   6513     RETURN_IF_ERR();
   6514     RETURN_NONE();
   6515 }
   6516 
   6517 
   6518 static PyObject*
   6519 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
   6520 {
   6521     int err;
   6522     DB_LOCK_STAT* sp;
   6523     PyObject* d = NULL;
   6524     u_int32_t flags = 0;
   6525 
   6526     if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
   6527         return NULL;
   6528     CHECK_ENV_NOT_CLOSED(self);
   6529 
   6530     MYDB_BEGIN_ALLOW_THREADS;
   6531     err = self->db_env->lock_stat(self->db_env, &sp, flags);
   6532     MYDB_END_ALLOW_THREADS;
   6533     RETURN_IF_ERR();
   6534 
   6535     /* Turn the stat structure into a dictionary */
   6536     d = PyDict_New();
   6537     if (d == NULL) {
   6538         free(sp);
   6539         return NULL;
   6540     }
   6541 
   6542 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, sp->st_##name)
   6543 
   6544     MAKE_ENTRY(id);
   6545     MAKE_ENTRY(cur_maxid);
   6546     MAKE_ENTRY(nmodes);
   6547     MAKE_ENTRY(maxlocks);
   6548     MAKE_ENTRY(maxlockers);
   6549     MAKE_ENTRY(maxobjects);
   6550     MAKE_ENTRY(nlocks);
   6551     MAKE_ENTRY(maxnlocks);
   6552     MAKE_ENTRY(nlockers);
   6553     MAKE_ENTRY(maxnlockers);
   6554     MAKE_ENTRY(nobjects);
   6555     MAKE_ENTRY(maxnobjects);
   6556     MAKE_ENTRY(nrequests);
   6557     MAKE_ENTRY(nreleases);
   6558 #if (DBVER >= 44)
   6559     MAKE_ENTRY(nupgrade);
   6560     MAKE_ENTRY(ndowngrade);
   6561 #endif
   6562 #if (DBVER < 44)
   6563     MAKE_ENTRY(nnowaits);       /* these were renamed in 4.4 */
   6564     MAKE_ENTRY(nconflicts);
   6565 #else
   6566     MAKE_ENTRY(lock_nowait);
   6567     MAKE_ENTRY(lock_wait);
   6568 #endif
   6569     MAKE_ENTRY(ndeadlocks);
   6570     MAKE_ENTRY(locktimeout);
   6571     MAKE_ENTRY(txntimeout);
   6572     MAKE_ENTRY(nlocktimeouts);
   6573     MAKE_ENTRY(ntxntimeouts);
   6574 #if (DBVER >= 46)
   6575     MAKE_ENTRY(objs_wait);
   6576     MAKE_ENTRY(objs_nowait);
   6577     MAKE_ENTRY(lockers_wait);
   6578     MAKE_ENTRY(lockers_nowait);
   6579 #if (DBVER >= 47)
   6580     MAKE_ENTRY(lock_wait);
   6581     MAKE_ENTRY(lock_nowait);
   6582 #else
   6583     MAKE_ENTRY(locks_wait);
   6584     MAKE_ENTRY(locks_nowait);
   6585 #endif
   6586     MAKE_ENTRY(hash_len);
   6587 #endif
   6588     MAKE_ENTRY(regsize);
   6589     MAKE_ENTRY(region_wait);
   6590     MAKE_ENTRY(region_nowait);
   6591 
   6592 #undef MAKE_ENTRY
   6593     free(sp);
   6594     return d;
   6595 }
   6596 
   6597 static PyObject*
   6598 DBEnv_lock_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6599 {
   6600     int err;
   6601     int flags=0;
   6602     static char* kwnames[] = { "flags", NULL };
   6603 
   6604     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:lock_stat_print",
   6605                 kwnames, &flags))
   6606     {
   6607         return NULL;
   6608     }
   6609     CHECK_ENV_NOT_CLOSED(self);
   6610     MYDB_BEGIN_ALLOW_THREADS;
   6611     err = self->db_env->lock_stat_print(self->db_env, flags);
   6612     MYDB_END_ALLOW_THREADS;
   6613     RETURN_IF_ERR();
   6614     RETURN_NONE();
   6615 }
   6616 
   6617 
   6618 static PyObject*
   6619 DBEnv_log_cursor(DBEnvObject* self)
   6620 {
   6621     int err;
   6622     DB_LOGC* dblogc;
   6623 
   6624     CHECK_ENV_NOT_CLOSED(self);
   6625 
   6626     MYDB_BEGIN_ALLOW_THREADS;
   6627     err = self->db_env->log_cursor(self->db_env, &dblogc, 0);
   6628     MYDB_END_ALLOW_THREADS;
   6629     RETURN_IF_ERR();
   6630     return (PyObject*) newDBLogCursorObject(dblogc, self);
   6631 }
   6632 
   6633 
   6634 static PyObject*
   6635 DBEnv_log_flush(DBEnvObject* self)
   6636 {
   6637     int err;
   6638 
   6639     CHECK_ENV_NOT_CLOSED(self);
   6640 
   6641     MYDB_BEGIN_ALLOW_THREADS
   6642     err = self->db_env->log_flush(self->db_env, NULL);
   6643     MYDB_END_ALLOW_THREADS
   6644 
   6645     RETURN_IF_ERR();
   6646     RETURN_NONE();
   6647 }
   6648 
   6649 static PyObject*
   6650 DBEnv_log_file(DBEnvObject* self, PyObject* args)
   6651 {
   6652     int err;
   6653     DB_LSN lsn = {0, 0};
   6654     int size = 20;
   6655     char *name = NULL;
   6656     PyObject *retval;
   6657 
   6658     if (!PyArg_ParseTuple(args, "(ii):log_file", &lsn.file, &lsn.offset))
   6659         return NULL;
   6660 
   6661     CHECK_ENV_NOT_CLOSED(self);
   6662 
   6663     do {
   6664         name = malloc(size);
   6665         if (!name) {
   6666             PyErr_NoMemory();
   6667             return NULL;
   6668         }
   6669         MYDB_BEGIN_ALLOW_THREADS;
   6670         err = self->db_env->log_file(self->db_env, &lsn, name, size);
   6671         MYDB_END_ALLOW_THREADS;
   6672         if (err == EINVAL) {
   6673             free(name);
   6674             size *= 2;
   6675         } else if (err) {
   6676             free(name);
   6677             RETURN_IF_ERR();
   6678             assert(0);  /* Unreachable... supposely */
   6679             return NULL;
   6680         }
   6681 /*
   6682 ** If the final buffer we try is too small, we will
   6683 ** get this exception:
   6684 ** DBInvalidArgError:
   6685 **    (22, 'Invalid argument -- DB_ENV->log_file: name buffer is too short')
   6686 */
   6687     } while ((err == EINVAL) && (size<(1<<17)));
   6688 
   6689     RETURN_IF_ERR();  /* Maybe the size is not the problem */
   6690 
   6691     retval = Py_BuildValue("s", name);
   6692     free(name);
   6693     return retval;
   6694 }
   6695 
   6696 
   6697 #if (DBVER >= 44)
   6698 static PyObject*
   6699 DBEnv_log_printf(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6700 {
   6701     int err;
   6702     char *string;
   6703     PyObject *txnobj = NULL;
   6704     DB_TXN *txn = NULL;
   6705     static char* kwnames[] = {"string", "txn", NULL };
   6706 
   6707     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O:log_printf", kwnames,
   6708                 &string, &txnobj))
   6709         return NULL;
   6710 
   6711     CHECK_ENV_NOT_CLOSED(self);
   6712 
   6713     if (!checkTxnObj(txnobj, &txn))
   6714         return NULL;
   6715 
   6716     /*
   6717     ** Do not use the format string directly, to avoid attacks.
   6718     */
   6719     MYDB_BEGIN_ALLOW_THREADS;
   6720     err = self->db_env->log_printf(self->db_env, txn, "%s", string);
   6721     MYDB_END_ALLOW_THREADS;
   6722 
   6723     RETURN_IF_ERR();
   6724     RETURN_NONE();
   6725 }
   6726 #endif
   6727 
   6728 
   6729 static PyObject*
   6730 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
   6731 {
   6732     int flags=0;
   6733     int err;
   6734     char **log_list = NULL;
   6735     PyObject* list;
   6736     PyObject* item = NULL;
   6737 
   6738     if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
   6739         return NULL;
   6740 
   6741     CHECK_ENV_NOT_CLOSED(self);
   6742     MYDB_BEGIN_ALLOW_THREADS;
   6743     err = self->db_env->log_archive(self->db_env, &log_list, flags);
   6744     MYDB_END_ALLOW_THREADS;
   6745     RETURN_IF_ERR();
   6746 
   6747     list = PyList_New(0);
   6748     if (list == NULL) {
   6749         if (log_list)
   6750             free(log_list);
   6751         return NULL;
   6752     }
   6753 
   6754     if (log_list) {
   6755         char **log_list_start;
   6756         for (log_list_start = log_list; *log_list != NULL; ++log_list) {
   6757             item = PyBytes_FromString (*log_list);
   6758             if (item == NULL) {
   6759                 Py_DECREF(list);
   6760                 list = NULL;
   6761                 break;
   6762             }
   6763             if (PyList_Append(list, item)) {
   6764                 Py_DECREF(list);
   6765                 list = NULL;
   6766                 Py_DECREF(item);
   6767                 break;
   6768             }
   6769             Py_DECREF(item);
   6770         }
   6771         free(log_list_start);
   6772     }
   6773     return list;
   6774 }
   6775 
   6776 
   6777 #if (DBVER >= 52)
   6778 static PyObject*
   6779 DBEnv_repmgr_site(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6780 {
   6781     int err;
   6782     DB_SITE* site;
   6783     char *host;
   6784     u_int port;
   6785     static char* kwnames[] = {"host", "port", NULL};
   6786 
   6787     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si:repmgr_site", kwnames,
   6788                                      &host, &port))
   6789         return NULL;
   6790 
   6791     CHECK_ENV_NOT_CLOSED(self);
   6792 
   6793     MYDB_BEGIN_ALLOW_THREADS;
   6794     err = self->db_env->repmgr_site(self->db_env, host, port, &site, 0);
   6795     MYDB_END_ALLOW_THREADS;
   6796     RETURN_IF_ERR();
   6797     return (PyObject*) newDBSiteObject(site, self);
   6798 }
   6799 
   6800 static PyObject*
   6801 DBEnv_repmgr_site_by_eid(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6802 {
   6803     int err;
   6804     DB_SITE* site;
   6805     int eid;
   6806     static char* kwnames[] = {"eid", NULL};
   6807 
   6808     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:repmgr_site_by_eid",
   6809                 kwnames, &eid))
   6810         return NULL;
   6811 
   6812     CHECK_ENV_NOT_CLOSED(self);
   6813 
   6814     MYDB_BEGIN_ALLOW_THREADS;
   6815     err = self->db_env->repmgr_site_by_eid(self->db_env, eid, &site);
   6816     MYDB_END_ALLOW_THREADS;
   6817     RETURN_IF_ERR();
   6818     return (PyObject*) newDBSiteObject(site, self);
   6819 }
   6820 #endif
   6821 
   6822 
   6823 #if (DBVER >= 44)
   6824 static PyObject*
   6825 DBEnv_mutex_stat(DBEnvObject* self, PyObject* args)
   6826 {
   6827     int err;
   6828     DB_MUTEX_STAT* statp = NULL;
   6829     PyObject* d = NULL;
   6830     u_int32_t flags = 0;
   6831 
   6832     if (!PyArg_ParseTuple(args, "|i:mutex_stat", &flags))
   6833         return NULL;
   6834     CHECK_ENV_NOT_CLOSED(self);
   6835 
   6836     MYDB_BEGIN_ALLOW_THREADS;
   6837     err = self->db_env->mutex_stat(self->db_env, &statp, flags);
   6838     MYDB_END_ALLOW_THREADS;
   6839     RETURN_IF_ERR();
   6840 
   6841     /* Turn the stat structure into a dictionary */
   6842     d = PyDict_New();
   6843     if (d == NULL) {
   6844         if (statp)
   6845             free(statp);
   6846         return NULL;
   6847     }
   6848 
   6849 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, statp->st_##name)
   6850 
   6851     MAKE_ENTRY(mutex_align);
   6852     MAKE_ENTRY(mutex_tas_spins);
   6853     MAKE_ENTRY(mutex_cnt);
   6854     MAKE_ENTRY(mutex_free);
   6855     MAKE_ENTRY(mutex_inuse);
   6856     MAKE_ENTRY(mutex_inuse_max);
   6857     MAKE_ENTRY(regsize);
   6858     MAKE_ENTRY(region_wait);
   6859     MAKE_ENTRY(region_nowait);
   6860 
   6861 #undef MAKE_ENTRY
   6862     free(statp);
   6863     return d;
   6864 }
   6865 #endif
   6866 
   6867 
   6868 #if (DBVER >= 44)
   6869 static PyObject*
   6870 DBEnv_mutex_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6871 {
   6872     int err;
   6873     int flags=0;
   6874     static char* kwnames[] = { "flags", NULL };
   6875 
   6876     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:mutex_stat_print",
   6877                 kwnames, &flags))
   6878     {
   6879         return NULL;
   6880     }
   6881     CHECK_ENV_NOT_CLOSED(self);
   6882     MYDB_BEGIN_ALLOW_THREADS;
   6883     err = self->db_env->mutex_stat_print(self->db_env, flags);
   6884     MYDB_END_ALLOW_THREADS;
   6885     RETURN_IF_ERR();
   6886     RETURN_NONE();
   6887 }
   6888 #endif
   6889 
   6890 
   6891 static PyObject*
   6892 DBEnv_txn_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   6893 {
   6894     int err;
   6895     int flags=0;
   6896     static char* kwnames[] = { "flags", NULL };
   6897 
   6898     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
   6899                 kwnames, &flags))
   6900     {
   6901         return NULL;
   6902     }
   6903 
   6904     CHECK_ENV_NOT_CLOSED(self);
   6905 
   6906     MYDB_BEGIN_ALLOW_THREADS;
   6907     err = self->db_env->txn_stat_print(self->db_env, flags);
   6908     MYDB_END_ALLOW_THREADS;
   6909     RETURN_IF_ERR();
   6910     RETURN_NONE();
   6911 }
   6912 
   6913 
   6914 static PyObject*
   6915 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
   6916 {
   6917     int err;
   6918     DB_TXN_STAT* sp;
   6919     PyObject* d = NULL;
   6920     u_int32_t flags=0;
   6921 
   6922     if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
   6923         return NULL;
   6924     CHECK_ENV_NOT_CLOSED(self);
   6925 
   6926     MYDB_BEGIN_ALLOW_THREADS;
   6927     err = self->db_env->txn_stat(self->db_env, &sp, flags);
   6928     MYDB_END_ALLOW_THREADS;
   6929     RETURN_IF_ERR();
   6930 
   6931     /* Turn the stat structure into a dictionary */
   6932     d = PyDict_New();
   6933     if (d == NULL) {
   6934         free(sp);
   6935         return NULL;
   6936     }
   6937 
   6938 #define MAKE_ENTRY(name)        _addIntToDict(d, #name, sp->st_##name)
   6939 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
   6940 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
   6941 
   6942     MAKE_DB_LSN_ENTRY(last_ckp);
   6943     MAKE_TIME_T_ENTRY(time_ckp);
   6944     MAKE_ENTRY(last_txnid);
   6945     MAKE_ENTRY(maxtxns);
   6946     MAKE_ENTRY(nactive);
   6947     MAKE_ENTRY(maxnactive);
   6948 #if (DBVER >= 45)
   6949     MAKE_ENTRY(nsnapshot);
   6950     MAKE_ENTRY(maxnsnapshot);
   6951 #endif
   6952     MAKE_ENTRY(nbegins);
   6953     MAKE_ENTRY(naborts);
   6954     MAKE_ENTRY(ncommits);
   6955     MAKE_ENTRY(nrestores);
   6956     MAKE_ENTRY(regsize);
   6957     MAKE_ENTRY(region_wait);
   6958     MAKE_ENTRY(region_nowait);
   6959 
   6960 #undef MAKE_DB_LSN_ENTRY
   6961 #undef MAKE_ENTRY
   6962 #undef MAKE_TIME_T_ENTRY
   6963     free(sp);
   6964     return d;
   6965 }
   6966 
   6967 
   6968 static PyObject*
   6969 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
   6970 {
   6971     int flags=0;
   6972     int oldValue=0;
   6973 
   6974     if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
   6975         return NULL;
   6976     CHECK_ENV_NOT_CLOSED(self);
   6977 
   6978     if (self->moduleFlags.getReturnsNone)
   6979         ++oldValue;
   6980     if (self->moduleFlags.cursorSetReturnsNone)
   6981         ++oldValue;
   6982     self->moduleFlags.getReturnsNone = (flags >= 1);
   6983     self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
   6984     return NUMBER_FromLong(oldValue);
   6985 }
   6986 
   6987 static PyObject*
   6988 DBEnv_get_private(DBEnvObject* self)
   6989 {
   6990     /* We can give out the private field even if dbenv is closed */
   6991     Py_INCREF(self->private_obj);
   6992     return self->private_obj;
   6993 }
   6994 
   6995 static PyObject*
   6996 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
   6997 {
   6998     /* We can set the private field even if dbenv is closed */
   6999     Py_INCREF(private_obj);
   7000     Py_SETREF(self->private_obj, private_obj);
   7001     RETURN_NONE();
   7002 }
   7003 
   7004 #if (DBVER >= 47)
   7005 static PyObject*
   7006 DBEnv_set_intermediate_dir_mode(DBEnvObject* self, PyObject* args)
   7007 {
   7008     int err;
   7009     const char *mode;
   7010 
   7011     if (!PyArg_ParseTuple(args,"s:set_intermediate_dir_mode", &mode))
   7012         return NULL;
   7013 
   7014     CHECK_ENV_NOT_CLOSED(self);
   7015 
   7016     MYDB_BEGIN_ALLOW_THREADS;
   7017     err = self->db_env->set_intermediate_dir_mode(self->db_env, mode);
   7018     MYDB_END_ALLOW_THREADS;
   7019     RETURN_IF_ERR();
   7020     RETURN_NONE();
   7021 }
   7022 
   7023 static PyObject*
   7024 DBEnv_get_intermediate_dir_mode(DBEnvObject* self)
   7025 {
   7026     int err;
   7027     const char *mode;
   7028 
   7029     CHECK_ENV_NOT_CLOSED(self);
   7030 
   7031     MYDB_BEGIN_ALLOW_THREADS;
   7032     err = self->db_env->get_intermediate_dir_mode(self->db_env, &mode);
   7033     MYDB_END_ALLOW_THREADS;
   7034     RETURN_IF_ERR();
   7035     return Py_BuildValue("s", mode);
   7036 }
   7037 #endif
   7038 
   7039 #if (DBVER < 47)
   7040 static PyObject*
   7041 DBEnv_set_intermediate_dir(DBEnvObject* self, PyObject* args)
   7042 {
   7043     int err;
   7044     int mode;
   7045     u_int32_t flags;
   7046 
   7047     if (!PyArg_ParseTuple(args, "iI:set_intermediate_dir", &mode, &flags))
   7048         return NULL;
   7049 
   7050     CHECK_ENV_NOT_CLOSED(self);
   7051 
   7052     MYDB_BEGIN_ALLOW_THREADS;
   7053     err = self->db_env->set_intermediate_dir(self->db_env, mode, flags);
   7054     MYDB_END_ALLOW_THREADS;
   7055     RETURN_IF_ERR();
   7056     RETURN_NONE();
   7057 }
   7058 #endif
   7059 
   7060 static PyObject*
   7061 DBEnv_get_open_flags(DBEnvObject* self)
   7062 {
   7063     int err;
   7064     unsigned int flags;
   7065 
   7066     CHECK_ENV_NOT_CLOSED(self);
   7067 
   7068     MYDB_BEGIN_ALLOW_THREADS;
   7069     err = self->db_env->get_open_flags(self->db_env, &flags);
   7070     MYDB_END_ALLOW_THREADS;
   7071     RETURN_IF_ERR();
   7072     return NUMBER_FromLong(flags);
   7073 }
   7074 
   7075 #if (DBVER < 48)
   7076 static PyObject*
   7077 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   7078 {
   7079     int err;
   7080     char *host;
   7081     long cl_timeout=0, sv_timeout=0;
   7082 
   7083     static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
   7084 
   7085     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
   7086                                      &host, &cl_timeout, &sv_timeout))
   7087         return NULL;
   7088     CHECK_ENV_NOT_CLOSED(self);
   7089 
   7090     MYDB_BEGIN_ALLOW_THREADS;
   7091     err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
   7092             sv_timeout, 0);
   7093     MYDB_END_ALLOW_THREADS;
   7094     RETURN_IF_ERR();
   7095     RETURN_NONE();
   7096 }
   7097 #endif
   7098 
   7099 static PyObject*
   7100 DBEnv_set_mp_max_openfd(DBEnvObject* self, PyObject* args)
   7101 {
   7102     int err;
   7103     int maxopenfd;
   7104 
   7105     if (!PyArg_ParseTuple(args, "i:set_mp_max_openfd", &maxopenfd)) {
   7106         return NULL;
   7107     }
   7108     CHECK_ENV_NOT_CLOSED(self);
   7109     MYDB_BEGIN_ALLOW_THREADS;
   7110     err = self->db_env->set_mp_max_openfd(self->db_env, maxopenfd);
   7111     MYDB_END_ALLOW_THREADS;
   7112     RETURN_IF_ERR();
   7113     RETURN_NONE();
   7114 }
   7115 
   7116 static PyObject*
   7117 DBEnv_get_mp_max_openfd(DBEnvObject* self)
   7118 {
   7119     int err;
   7120     int maxopenfd;
   7121 
   7122     CHECK_ENV_NOT_CLOSED(self);
   7123 
   7124     MYDB_BEGIN_ALLOW_THREADS;
   7125     err = self->db_env->get_mp_max_openfd(self->db_env, &maxopenfd);
   7126     MYDB_END_ALLOW_THREADS;
   7127     RETURN_IF_ERR();
   7128     return NUMBER_FromLong(maxopenfd);
   7129 }
   7130 
   7131 
   7132 static PyObject*
   7133 DBEnv_set_mp_max_write(DBEnvObject* self, PyObject* args)
   7134 {
   7135     int err;
   7136     int maxwrite, maxwrite_sleep;
   7137 
   7138     if (!PyArg_ParseTuple(args, "ii:set_mp_max_write", &maxwrite,
   7139                 &maxwrite_sleep)) {
   7140         return NULL;
   7141     }
   7142     CHECK_ENV_NOT_CLOSED(self);
   7143     MYDB_BEGIN_ALLOW_THREADS;
   7144     err = self->db_env->set_mp_max_write(self->db_env, maxwrite,
   7145             maxwrite_sleep);
   7146     MYDB_END_ALLOW_THREADS;
   7147     RETURN_IF_ERR();
   7148     RETURN_NONE();
   7149 }
   7150 
   7151 static PyObject*
   7152 DBEnv_get_mp_max_write(DBEnvObject* self)
   7153 {
   7154     int err;
   7155     int maxwrite;
   7156 #if (DBVER >= 46)
   7157     db_timeout_t maxwrite_sleep;
   7158 #else
   7159     int maxwrite_sleep;
   7160 #endif
   7161 
   7162     CHECK_ENV_NOT_CLOSED(self);
   7163 
   7164     MYDB_BEGIN_ALLOW_THREADS;
   7165     err = self->db_env->get_mp_max_write(self->db_env, &maxwrite,
   7166             &maxwrite_sleep);
   7167     MYDB_END_ALLOW_THREADS;
   7168     RETURN_IF_ERR();
   7169 
   7170     return Py_BuildValue("(ii)", maxwrite, (int)maxwrite_sleep);
   7171 }
   7172 
   7173 
   7174 static PyObject*
   7175 DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
   7176 {
   7177     int err;
   7178     int which, onoff;
   7179 
   7180     if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
   7181         return NULL;
   7182     }
   7183     CHECK_ENV_NOT_CLOSED(self);
   7184     MYDB_BEGIN_ALLOW_THREADS;
   7185     err = self->db_env->set_verbose(self->db_env, which, onoff);
   7186     MYDB_END_ALLOW_THREADS;
   7187     RETURN_IF_ERR();
   7188     RETURN_NONE();
   7189 }
   7190 
   7191 static PyObject*
   7192 DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
   7193 {
   7194     int err;
   7195     int which;
   7196     int verbose;
   7197 
   7198     if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
   7199         return NULL;
   7200     }
   7201     CHECK_ENV_NOT_CLOSED(self);
   7202     MYDB_BEGIN_ALLOW_THREADS;
   7203     err = self->db_env->get_verbose(self->db_env, which, &verbose);
   7204     MYDB_END_ALLOW_THREADS;
   7205     RETURN_IF_ERR();
   7206     return PyBool_FromLong(verbose);
   7207 }
   7208 
   7209 #if (DBVER >= 45)
   7210 static void
   7211 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
   7212 {
   7213     DBEnvObject *dbenv;
   7214     PyObject* callback;
   7215     PyObject* args;
   7216     PyObject* result = NULL;
   7217 
   7218     MYDB_BEGIN_BLOCK_THREADS;
   7219     dbenv = (DBEnvObject *)db_env->app_private;
   7220     callback = dbenv->event_notifyCallback;
   7221     if (callback) {
   7222         if (event == DB_EVENT_REP_NEWMASTER) {
   7223             args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
   7224         } else {
   7225             args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
   7226         }
   7227         if (args) {
   7228             result = PyEval_CallObject(callback, args);
   7229         }
   7230         if ((!args) || (!result)) {
   7231             PyErr_Print();
   7232         }
   7233         Py_XDECREF(args);
   7234         Py_XDECREF(result);
   7235     }
   7236     MYDB_END_BLOCK_THREADS;
   7237 }
   7238 #endif
   7239 
   7240 #if (DBVER >= 45)
   7241 static PyObject*
   7242 DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
   7243 {
   7244     int err;
   7245 
   7246     CHECK_ENV_NOT_CLOSED(self);
   7247 
   7248     if (!PyCallable_Check(notifyFunc)) {
   7249             makeTypeError("Callable", notifyFunc);
   7250             return NULL;
   7251     }
   7252 
   7253     Py_INCREF(notifyFunc);
   7254     Py_XSETREF(self->event_notifyCallback, notifyFunc);
   7255 
   7256     /* This is to workaround a problem with un-initialized threads (see
   7257        comment in DB_associate) */
   7258 #ifdef WITH_THREAD
   7259     PyEval_InitThreads();
   7260 #endif
   7261 
   7262     MYDB_BEGIN_ALLOW_THREADS;
   7263     err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
   7264     MYDB_END_ALLOW_THREADS;
   7265 
   7266     if (err) {
   7267             Py_DECREF(notifyFunc);
   7268             self->event_notifyCallback = NULL;
   7269     }
   7270 
   7271     RETURN_IF_ERR();
   7272     RETURN_NONE();
   7273 }
   7274 #endif
   7275 
   7276 
   7277 /* --------------------------------------------------------------------- */
   7278 /* REPLICATION METHODS: Base Replication */
   7279 
   7280 
   7281 static PyObject*
   7282 DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
   7283 {
   7284     int err;
   7285     PyObject *control_py, *rec_py;
   7286     DBT control, rec;
   7287     int envid;
   7288     DB_LSN lsn;
   7289 
   7290     if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
   7291                 &rec_py, &envid))
   7292         return NULL;
   7293     CHECK_ENV_NOT_CLOSED(self);
   7294 
   7295     if (!make_dbt(control_py, &control))
   7296         return NULL;
   7297     if (!make_dbt(rec_py, &rec))
   7298         return NULL;
   7299 
   7300     MYDB_BEGIN_ALLOW_THREADS;
   7301 #if (DBVER >= 46)
   7302     err = self->db_env->rep_process_message(self->db_env, &control, &rec,
   7303             envid, &lsn);
   7304 #else
   7305     err = self->db_env->rep_process_message(self->db_env, &control, &rec,
   7306             &envid, &lsn);
   7307 #endif
   7308     MYDB_END_ALLOW_THREADS;
   7309     switch (err) {
   7310         case DB_REP_NEWMASTER :
   7311           return Py_BuildValue("(iO)", envid, Py_None);
   7312           break;
   7313 
   7314         case DB_REP_DUPMASTER :
   7315         case DB_REP_HOLDELECTION :
   7316 #if (DBVER >= 44)
   7317         case DB_REP_IGNORE :
   7318         case DB_REP_JOIN_FAILURE :
   7319 #endif
   7320             return Py_BuildValue("(iO)", err, Py_None);
   7321             break;
   7322         case DB_REP_NEWSITE :
   7323             {
   7324                 PyObject *tmp, *r;
   7325 
   7326                 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
   7327                     return NULL;
   7328                 }
   7329 
   7330                 r = Py_BuildValue("(iO)", err, tmp);
   7331                 Py_DECREF(tmp);
   7332                 return r;
   7333                 break;
   7334             }
   7335         case DB_REP_NOTPERM :
   7336         case DB_REP_ISPERM :
   7337             return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
   7338             break;
   7339     }
   7340     RETURN_IF_ERR();
   7341     return PyTuple_Pack(2, Py_None, Py_None);
   7342 }
   7343 
   7344 static int
   7345 _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
   7346         const DB_LSN *lsn, int envid, u_int32_t flags)
   7347 {
   7348     DBEnvObject *dbenv;
   7349     PyObject* rep_transport;
   7350     PyObject* args;
   7351     PyObject *a, *b;
   7352     PyObject* result = NULL;
   7353     int ret=0;
   7354 
   7355     MYDB_BEGIN_BLOCK_THREADS;
   7356     dbenv = (DBEnvObject *)db_env->app_private;
   7357     rep_transport = dbenv->rep_transport;
   7358 
   7359     /*
   7360     ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
   7361     */
   7362     a = PyBytes_FromStringAndSize(control->data, control->size);
   7363     b = PyBytes_FromStringAndSize(rec->data, rec->size);
   7364 
   7365     args = Py_BuildValue(
   7366             "(OOO(ll)iI)",
   7367             dbenv,
   7368             a, b,
   7369             lsn->file, lsn->offset, envid, flags);
   7370     if (args) {
   7371         result = PyEval_CallObject(rep_transport, args);
   7372     }
   7373 
   7374     if ((!args) || (!result)) {
   7375         PyErr_Print();
   7376         ret = -1;
   7377     }
   7378     Py_XDECREF(a);
   7379     Py_XDECREF(b);
   7380     Py_XDECREF(args);
   7381     Py_XDECREF(result);
   7382     MYDB_END_BLOCK_THREADS;
   7383     return ret;
   7384 }
   7385 
   7386 static PyObject*
   7387 DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
   7388 {
   7389     int err;
   7390     int envid;
   7391     PyObject *rep_transport;
   7392 
   7393     if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
   7394         return NULL;
   7395     CHECK_ENV_NOT_CLOSED(self);
   7396     if (!PyCallable_Check(rep_transport)) {
   7397         makeTypeError("Callable", rep_transport);
   7398         return NULL;
   7399     }
   7400 
   7401     MYDB_BEGIN_ALLOW_THREADS;
   7402 #if (DBVER >=45)
   7403     err = self->db_env->rep_set_transport(self->db_env, envid,
   7404             &_DBEnv_rep_transportCallback);
   7405 #else
   7406     err = self->db_env->set_rep_transport(self->db_env, envid,
   7407             &_DBEnv_rep_transportCallback);
   7408 #endif
   7409     MYDB_END_ALLOW_THREADS;
   7410     RETURN_IF_ERR();
   7411 
   7412     Py_INCREF(rep_transport);
   7413     Py_SETREF(self->rep_transport, rep_transport);
   7414     RETURN_NONE();
   7415 }
   7416 
   7417 #if (DBVER >= 47)
   7418 static PyObject*
   7419 DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
   7420 {
   7421     int err;
   7422     unsigned int minimum, maximum;
   7423 
   7424     if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
   7425         return NULL;
   7426     CHECK_ENV_NOT_CLOSED(self);
   7427 
   7428     MYDB_BEGIN_ALLOW_THREADS;
   7429     err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
   7430     MYDB_END_ALLOW_THREADS;
   7431     RETURN_IF_ERR();
   7432     RETURN_NONE();
   7433 }
   7434 
   7435 static PyObject*
   7436 DBEnv_rep_get_request(DBEnvObject* self)
   7437 {
   7438     int err;
   7439     u_int32_t minimum, maximum;
   7440 
   7441     CHECK_ENV_NOT_CLOSED(self);
   7442     MYDB_BEGIN_ALLOW_THREADS;
   7443     err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
   7444     MYDB_END_ALLOW_THREADS;
   7445     RETURN_IF_ERR();
   7446     return Py_BuildValue("II", minimum, maximum);
   7447 }
   7448 #endif
   7449 
   7450 #if (DBVER >= 45)
   7451 static PyObject*
   7452 DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
   7453 {
   7454     int err;
   7455     int limit;
   7456 
   7457     if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
   7458         return NULL;
   7459     CHECK_ENV_NOT_CLOSED(self);
   7460 
   7461     MYDB_BEGIN_ALLOW_THREADS;
   7462     err = self->db_env->rep_set_limit(self->db_env, 0, limit);
   7463     MYDB_END_ALLOW_THREADS;
   7464     RETURN_IF_ERR();
   7465     RETURN_NONE();
   7466 }
   7467 
   7468 static PyObject*
   7469 DBEnv_rep_get_limit(DBEnvObject* self)
   7470 {
   7471     int err;
   7472     u_int32_t gbytes, bytes;
   7473 
   7474     CHECK_ENV_NOT_CLOSED(self);
   7475     MYDB_BEGIN_ALLOW_THREADS;
   7476     err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
   7477     MYDB_END_ALLOW_THREADS;
   7478     RETURN_IF_ERR();
   7479     return NUMBER_FromLong(bytes);
   7480 }
   7481 #endif
   7482 
   7483 #if (DBVER >= 44)
   7484 static PyObject*
   7485 DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
   7486 {
   7487     int err;
   7488     int which;
   7489     int onoff;
   7490 
   7491     if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
   7492         return NULL;
   7493     CHECK_ENV_NOT_CLOSED(self);
   7494 
   7495     MYDB_BEGIN_ALLOW_THREADS;
   7496     err = self->db_env->rep_set_config(self->db_env, which, onoff);
   7497     MYDB_END_ALLOW_THREADS;
   7498     RETURN_IF_ERR();
   7499     RETURN_NONE();
   7500 }
   7501 
   7502 static PyObject*
   7503 DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
   7504 {
   7505     int err;
   7506     int which;
   7507     int onoff;
   7508 
   7509     if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
   7510         return NULL;
   7511     }
   7512     CHECK_ENV_NOT_CLOSED(self);
   7513     MYDB_BEGIN_ALLOW_THREADS;
   7514     err = self->db_env->rep_get_config(self->db_env, which, &onoff);
   7515     MYDB_END_ALLOW_THREADS;
   7516     RETURN_IF_ERR();
   7517     return PyBool_FromLong(onoff);
   7518 }
   7519 #endif
   7520 
   7521 #if (DBVER >= 46)
   7522 static PyObject*
   7523 DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
   7524 {
   7525     int err;
   7526     u_int32_t nsites, nvotes;
   7527 
   7528     if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
   7529         return NULL;
   7530     }
   7531     CHECK_ENV_NOT_CLOSED(self);
   7532     MYDB_BEGIN_ALLOW_THREADS;
   7533     err = self->db_env->rep_elect(self->db_env, nsites, nvotes, 0);
   7534     MYDB_END_ALLOW_THREADS;
   7535     RETURN_IF_ERR();
   7536     RETURN_NONE();
   7537 }
   7538 #endif
   7539 
   7540 static PyObject*
   7541 DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
   7542 {
   7543     int err;
   7544     PyObject *cdata_py = Py_None;
   7545     DBT cdata;
   7546     int flags;
   7547     static char* kwnames[] = {"flags","cdata", NULL};
   7548 
   7549     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
   7550                 "i|O:rep_start", kwnames, &flags, &cdata_py))
   7551     {
   7552             return NULL;
   7553     }
   7554     CHECK_ENV_NOT_CLOSED(self);
   7555 
   7556     if (!make_dbt(cdata_py, &cdata))
   7557         return NULL;
   7558 
   7559     MYDB_BEGIN_ALLOW_THREADS;
   7560     err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
   7561             flags);
   7562     MYDB_END_ALLOW_THREADS;
   7563     RETURN_IF_ERR();
   7564     RETURN_NONE();
   7565 }
   7566 
   7567 #if (DBVER >= 44)
   7568 static PyObject*
   7569 DBEnv_rep_sync(DBEnvObject* self)
   7570 {
   7571     int err;
   7572 
   7573     CHECK_ENV_NOT_CLOSED(self);
   7574     MYDB_BEGIN_ALLOW_THREADS;
   7575     err = self->db_env->rep_sync(self->db_env, 0);
   7576     MYDB_END_ALLOW_THREADS;
   7577     RETURN_IF_ERR();
   7578     RETURN_NONE();
   7579 }
   7580 #endif
   7581 
   7582 
   7583 #if (DBVER >= 45)
   7584 static PyObject*
   7585 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
   7586 {
   7587     int err;
   7588     int nsites;
   7589 
   7590     if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
   7591         return NULL;
   7592     }
   7593     CHECK_ENV_NOT_CLOSED(self);
   7594     MYDB_BEGIN_ALLOW_THREADS;
   7595     err = self->db_env->rep_set_nsites(self->db_env, nsites);
   7596     MYDB_END_ALLOW_THREADS;
   7597     RETURN_IF_ERR();
   7598     RETURN_NONE();
   7599 }
   7600 
   7601 static PyObject*
   7602 DBEnv_rep_get_nsites(DBEnvObject* self)
   7603 {
   7604     int err;
   7605 #if (DBVER >= 47)
   7606     u_int32_t nsites;
   7607 #else
   7608     int nsites;
   7609 #endif
   7610 
   7611     CHECK_ENV_NOT_CLOSED(self);
   7612     MYDB_BEGIN_ALLOW_THREADS;
   7613     err = self->db_env->rep_get_nsites(self->db_env, &nsites);
   7614     MYDB_END_ALLOW_THREADS;
   7615     RETURN_IF_ERR();
   7616     return NUMBER_FromLong(nsites);
   7617 }
   7618 
   7619 static PyObject*
   7620 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
   7621 {
   7622     int err;
   7623     int priority;
   7624 
   7625     if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
   7626         return NULL;
   7627     }
   7628     CHECK_ENV_NOT_CLOSED(self);
   7629     MYDB_BEGIN_ALLOW_THREADS;
   7630     err = self->db_env->rep_set_priority(self->db_env, priority);
   7631     MYDB_END_ALLOW_THREADS;
   7632     RETURN_IF_ERR();
   7633     RETURN_NONE();
   7634 }
   7635 
   7636 static PyObject*
   7637 DBEnv_rep_get_priority(DBEnvObject* self)
   7638 {
   7639     int err;
   7640 #if (DBVER >= 47)
   7641     u_int32_t priority;
   7642 #else
   7643     int priority;
   7644 #endif
   7645 
   7646     CHECK_ENV_NOT_CLOSED(self);
   7647     MYDB_BEGIN_ALLOW_THREADS;
   7648     err = self->db_env->rep_get_priority(self->db_env, &priority);
   7649     MYDB_END_ALLOW_THREADS;
   7650     RETURN_IF_ERR();
   7651     return NUMBER_FromLong(priority);
   7652 }
   7653 
   7654 static PyObject*
   7655 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
   7656 {
   7657     int err;
   7658     int which, timeout;
   7659 
   7660     if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
   7661         return NULL;
   7662     }
   7663     CHECK_ENV_NOT_CLOSED(self);
   7664     MYDB_BEGIN_ALLOW_THREADS;
   7665     err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
   7666     MYDB_END_ALLOW_THREADS;
   7667     RETURN_IF_ERR();
   7668     RETURN_NONE();
   7669 }
   7670 
   7671 static PyObject*
   7672 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
   7673 {
   7674     int err;
   7675     int which;
   7676     u_int32_t timeout;
   7677 
   7678     if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
   7679         return NULL;
   7680     }
   7681     CHECK_ENV_NOT_CLOSED(self);
   7682     MYDB_BEGIN_ALLOW_THREADS;
   7683     err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
   7684     MYDB_END_ALLOW_THREADS;
   7685     RETURN_IF_ERR();
   7686     return NUMBER_FromLong(timeout);
   7687 }
   7688 #endif
   7689 
   7690 
   7691 #if (DBVER >= 47)
   7692 static PyObject*
   7693 DBEnv_rep_set_clockskew(DBEnvObject* self, PyObject* args)
   7694 {
   7695     int err;
   7696     unsigned int fast, slow;
   7697 
   7698     if (!PyArg_ParseTuple(args,"II:rep_set_clockskew", &fast, &slow))
   7699         return NULL;
   7700 
   7701     CHECK_ENV_NOT_CLOSED(self);
   7702 
   7703     MYDB_BEGIN_ALLOW_THREADS;
   7704     err = self->db_env->rep_set_clockskew(self->db_env, fast, slow);
   7705     MYDB_END_ALLOW_THREADS;
   7706     RETURN_IF_ERR();
   7707     RETURN_NONE();
   7708 }
   7709 
   7710 static PyObject*
   7711 DBEnv_rep_get_clockskew(DBEnvObject* self)
   7712 {
   7713     int err;
   7714     unsigned int fast, slow;
   7715 
   7716     CHECK_ENV_NOT_CLOSED(self);
   7717     MYDB_BEGIN_ALLOW_THREADS;
   7718     err = self->db_env->rep_get_clockskew(self->db_env, &fast, &slow);
   7719     MYDB_END_ALLOW_THREADS;
   7720     RETURN_IF_ERR();
   7721     return Py_BuildValue("(II)", fast, slow);
   7722 }
   7723 #endif
   7724 
   7725 static PyObject*
   7726 DBEnv_rep_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   7727 {
   7728     int err;
   7729     int flags=0;
   7730     static char* kwnames[] = { "flags", NULL };
   7731 
   7732     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat_print",
   7733                 kwnames, &flags))
   7734     {
   7735         return NULL;
   7736     }
   7737     CHECK_ENV_NOT_CLOSED(self);
   7738     MYDB_BEGIN_ALLOW_THREADS;
   7739     err = self->db_env->rep_stat_print(self->db_env, flags);
   7740     MYDB_END_ALLOW_THREADS;
   7741     RETURN_IF_ERR();
   7742     RETURN_NONE();
   7743 }
   7744 
   7745 static PyObject*
   7746 DBEnv_rep_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   7747 {
   7748     int err;
   7749     int flags=0;
   7750     DB_REP_STAT *statp;
   7751     PyObject *stats;
   7752     static char* kwnames[] = { "flags", NULL };
   7753 
   7754     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat",
   7755                 kwnames, &flags))
   7756     {
   7757         return NULL;
   7758     }
   7759     CHECK_ENV_NOT_CLOSED(self);
   7760     MYDB_BEGIN_ALLOW_THREADS;
   7761     err = self->db_env->rep_stat(self->db_env, &statp, flags);
   7762     MYDB_END_ALLOW_THREADS;
   7763     RETURN_IF_ERR();
   7764 
   7765     stats=PyDict_New();
   7766     if (stats == NULL) {
   7767         free(statp);
   7768         return NULL;
   7769     }
   7770 
   7771 #define MAKE_ENTRY(name)  _addIntToDict(stats, #name, statp->st_##name)
   7772 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(stats , #name, statp->st_##name)
   7773 
   7774 #if (DBVER >= 44)
   7775     MAKE_ENTRY(bulk_fills);
   7776     MAKE_ENTRY(bulk_overflows);
   7777     MAKE_ENTRY(bulk_records);
   7778     MAKE_ENTRY(bulk_transfers);
   7779     MAKE_ENTRY(client_rerequests);
   7780     MAKE_ENTRY(client_svc_miss);
   7781     MAKE_ENTRY(client_svc_req);
   7782 #endif
   7783     MAKE_ENTRY(dupmasters);
   7784     MAKE_ENTRY(egen);
   7785     MAKE_ENTRY(election_nvotes);
   7786     MAKE_ENTRY(startup_complete);
   7787     MAKE_ENTRY(pg_duplicated);
   7788     MAKE_ENTRY(pg_records);
   7789     MAKE_ENTRY(pg_requested);
   7790     MAKE_ENTRY(next_pg);
   7791     MAKE_ENTRY(waiting_pg);
   7792     MAKE_ENTRY(election_cur_winner);
   7793     MAKE_ENTRY(election_gen);
   7794     MAKE_DB_LSN_ENTRY(election_lsn);
   7795     MAKE_ENTRY(election_nsites);
   7796     MAKE_ENTRY(election_priority);
   7797 #if (DBVER >= 44)
   7798     MAKE_ENTRY(election_sec);
   7799     MAKE_ENTRY(election_usec);
   7800 #endif
   7801     MAKE_ENTRY(election_status);
   7802     MAKE_ENTRY(election_tiebreaker);
   7803     MAKE_ENTRY(election_votes);
   7804     MAKE_ENTRY(elections);
   7805     MAKE_ENTRY(elections_won);
   7806     MAKE_ENTRY(env_id);
   7807     MAKE_ENTRY(env_priority);
   7808     MAKE_ENTRY(gen);
   7809     MAKE_ENTRY(log_duplicated);
   7810     MAKE_ENTRY(log_queued);
   7811     MAKE_ENTRY(log_queued_max);
   7812     MAKE_ENTRY(log_queued_total);
   7813     MAKE_ENTRY(log_records);
   7814     MAKE_ENTRY(log_requested);
   7815     MAKE_ENTRY(master);
   7816     MAKE_ENTRY(master_changes);
   7817 #if (DBVER >= 47)
   7818     MAKE_ENTRY(max_lease_sec);
   7819     MAKE_ENTRY(max_lease_usec);
   7820     MAKE_DB_LSN_ENTRY(max_perm_lsn);
   7821 #endif
   7822     MAKE_ENTRY(msgs_badgen);
   7823     MAKE_ENTRY(msgs_processed);
   7824     MAKE_ENTRY(msgs_recover);
   7825     MAKE_ENTRY(msgs_send_failures);
   7826     MAKE_ENTRY(msgs_sent);
   7827     MAKE_ENTRY(newsites);
   7828     MAKE_DB_LSN_ENTRY(next_lsn);
   7829     MAKE_ENTRY(nsites);
   7830     MAKE_ENTRY(nthrottles);
   7831     MAKE_ENTRY(outdated);
   7832 #if (DBVER >= 46)
   7833     MAKE_ENTRY(startsync_delayed);
   7834 #endif
   7835     MAKE_ENTRY(status);
   7836     MAKE_ENTRY(txns_applied);
   7837     MAKE_DB_LSN_ENTRY(waiting_lsn);
   7838 
   7839 #undef MAKE_DB_LSN_ENTRY
   7840 #undef MAKE_ENTRY
   7841 
   7842     free(statp);
   7843     return stats;
   7844 }
   7845 
   7846 /* --------------------------------------------------------------------- */
   7847 /* REPLICATION METHODS: Replication Manager */
   7848 
   7849 #if (DBVER >= 45)
   7850 static PyObject*
   7851 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
   7852         kwargs)
   7853 {
   7854     int err;
   7855     int nthreads, flags;
   7856     static char* kwnames[] = {"nthreads","flags", NULL};
   7857 
   7858     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
   7859                 "ii:repmgr_start", kwnames, &nthreads, &flags))
   7860     {
   7861             return NULL;
   7862     }
   7863     CHECK_ENV_NOT_CLOSED(self);
   7864     MYDB_BEGIN_ALLOW_THREADS;
   7865     err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
   7866     MYDB_END_ALLOW_THREADS;
   7867     RETURN_IF_ERR();
   7868     RETURN_NONE();
   7869 }
   7870 
   7871 #if (DBVER < 52)
   7872 static PyObject*
   7873 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
   7874         kwargs)
   7875 {
   7876     int err;
   7877     char *host;
   7878     int port;
   7879     int flags = 0;
   7880     static char* kwnames[] = {"host", "port", "flags", NULL};
   7881 
   7882     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
   7883                 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
   7884     {
   7885             return NULL;
   7886     }
   7887     CHECK_ENV_NOT_CLOSED(self);
   7888     MYDB_BEGIN_ALLOW_THREADS;
   7889     err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
   7890     MYDB_END_ALLOW_THREADS;
   7891     RETURN_IF_ERR();
   7892     RETURN_NONE();
   7893 }
   7894 
   7895 static PyObject*
   7896 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
   7897         kwargs)
   7898 {
   7899     int err;
   7900     char *host;
   7901     int port;
   7902     int flags = 0;
   7903     int eidp;
   7904     static char* kwnames[] = {"host", "port", "flags", NULL};
   7905 
   7906     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
   7907                 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
   7908     {
   7909             return NULL;
   7910     }
   7911     CHECK_ENV_NOT_CLOSED(self);
   7912     MYDB_BEGIN_ALLOW_THREADS;
   7913     err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
   7914     MYDB_END_ALLOW_THREADS;
   7915     RETURN_IF_ERR();
   7916     return NUMBER_FromLong(eidp);
   7917 }
   7918 #endif
   7919 
   7920 static PyObject*
   7921 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
   7922 {
   7923     int err;
   7924     int ack_policy;
   7925 
   7926     if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
   7927     {
   7928             return NULL;
   7929     }
   7930     CHECK_ENV_NOT_CLOSED(self);
   7931     MYDB_BEGIN_ALLOW_THREADS;
   7932     err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
   7933     MYDB_END_ALLOW_THREADS;
   7934     RETURN_IF_ERR();
   7935     RETURN_NONE();
   7936 }
   7937 
   7938 static PyObject*
   7939 DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
   7940 {
   7941     int err;
   7942     int ack_policy;
   7943 
   7944     CHECK_ENV_NOT_CLOSED(self);
   7945     MYDB_BEGIN_ALLOW_THREADS;
   7946     err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
   7947     MYDB_END_ALLOW_THREADS;
   7948     RETURN_IF_ERR();
   7949     return NUMBER_FromLong(ack_policy);
   7950 }
   7951 
   7952 static PyObject*
   7953 DBEnv_repmgr_site_list(DBEnvObject* self)
   7954 {
   7955     int err;
   7956     unsigned int countp;
   7957     DB_REPMGR_SITE *listp;
   7958     PyObject *stats, *key, *tuple;
   7959 
   7960     CHECK_ENV_NOT_CLOSED(self);
   7961     MYDB_BEGIN_ALLOW_THREADS;
   7962     err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
   7963     MYDB_END_ALLOW_THREADS;
   7964     RETURN_IF_ERR();
   7965 
   7966     stats=PyDict_New();
   7967     if (stats == NULL) {
   7968         free(listp);
   7969         return NULL;
   7970     }
   7971 
   7972     for(;countp--;) {
   7973         key=NUMBER_FromLong(listp[countp].eid);
   7974         if(!key) {
   7975             Py_DECREF(stats);
   7976             free(listp);
   7977             return NULL;
   7978         }
   7979         tuple=Py_BuildValue("(sII)", listp[countp].host,
   7980                 listp[countp].port, listp[countp].status);
   7981         if(!tuple) {
   7982             Py_DECREF(key);
   7983             Py_DECREF(stats);
   7984             free(listp);
   7985             return NULL;
   7986         }
   7987         if(PyDict_SetItem(stats, key, tuple)) {
   7988             Py_DECREF(key);
   7989             Py_DECREF(tuple);
   7990             Py_DECREF(stats);
   7991             free(listp);
   7992             return NULL;
   7993         }
   7994         Py_DECREF(key);
   7995         Py_DECREF(tuple);
   7996     }
   7997     free(listp);
   7998     return stats;
   7999 }
   8000 #endif
   8001 
   8002 #if (DBVER >= 46)
   8003 static PyObject*
   8004 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   8005 {
   8006     int err;
   8007     int flags=0;
   8008     static char* kwnames[] = { "flags", NULL };
   8009 
   8010     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
   8011                 kwnames, &flags))
   8012     {
   8013         return NULL;
   8014     }
   8015     CHECK_ENV_NOT_CLOSED(self);
   8016     MYDB_BEGIN_ALLOW_THREADS;
   8017     err = self->db_env->repmgr_stat_print(self->db_env, flags);
   8018     MYDB_END_ALLOW_THREADS;
   8019     RETURN_IF_ERR();
   8020     RETURN_NONE();
   8021 }
   8022 
   8023 static PyObject*
   8024 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
   8025 {
   8026     int err;
   8027     int flags=0;
   8028     DB_REPMGR_STAT *statp;
   8029     PyObject *stats;
   8030     static char* kwnames[] = { "flags", NULL };
   8031 
   8032     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
   8033                 kwnames, &flags))
   8034     {
   8035         return NULL;
   8036     }
   8037     CHECK_ENV_NOT_CLOSED(self);
   8038     MYDB_BEGIN_ALLOW_THREADS;
   8039     err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
   8040     MYDB_END_ALLOW_THREADS;
   8041     RETURN_IF_ERR();
   8042 
   8043     stats=PyDict_New();
   8044     if (stats == NULL) {
   8045         free(statp);
   8046         return NULL;
   8047     }
   8048 
   8049 #define MAKE_ENTRY(name)  _addIntToDict(stats, #name, statp->st_##name)
   8050 
   8051     MAKE_ENTRY(perm_failed);
   8052     MAKE_ENTRY(msgs_queued);
   8053     MAKE_ENTRY(msgs_dropped);
   8054     MAKE_ENTRY(connection_drop);
   8055     MAKE_ENTRY(connect_fail);
   8056 
   8057 #undef MAKE_ENTRY
   8058 
   8059     free(statp);
   8060     return stats;
   8061 }
   8062 #endif
   8063 
   8064 
   8065 /* --------------------------------------------------------------------- */
   8066 /* DBTxn methods */
   8067 
   8068 
   8069 static void _close_transaction_cursors(DBTxnObject* txn)
   8070 {
   8071     PyObject *dummy;
   8072 
   8073     while(txn->children_cursors) {
   8074         PyErr_Warn(PyExc_RuntimeWarning,
   8075             "Must close cursors before resolving a transaction.");
   8076         dummy=DBC_close_internal(txn->children_cursors);
   8077         Py_XDECREF(dummy);
   8078     }
   8079 }
   8080 
   8081 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
   8082 {
   8083     DBObject *db;
   8084     DBSequenceObject *dbs;
   8085 
   8086     while (txn->children_dbs) {
   8087         db=txn->children_dbs;
   8088         EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
   8089         if (txn->parent_txn) {
   8090             INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
   8091             db->txn=txn->parent_txn;
   8092         } else {
   8093             /* The db is already linked to its environment,
   8094             ** so nothing to do.
   8095             */
   8096             db->txn=NULL;
   8097         }
   8098     }
   8099 
   8100     while (txn->children_sequences) {
   8101         dbs=txn->children_sequences;
   8102         EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
   8103         if (txn->parent_txn) {
   8104             INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
   8105             dbs->txn=txn->parent_txn;
   8106         } else {
   8107             /* The sequence is already linked to its
   8108             ** parent db. Nothing to do.
   8109             */
   8110             dbs->txn=NULL;
   8111         }
   8112     }
   8113 }
   8114 
   8115 
   8116 static PyObject*
   8117 DBTxn_commit(DBTxnObject* self, PyObject* args)
   8118 {
   8119     int flags=0, err;
   8120     DB_TXN *txn;
   8121 
   8122     if (!PyArg_ParseTuple(args, "|i:commit", &flags))
   8123         return NULL;
   8124 
   8125     _close_transaction_cursors(self);
   8126 
   8127     if (!self->txn) {
   8128         PyObject *t =  Py_BuildValue("(is)", 0, "DBTxn must not be used "
   8129                                      "after txn_commit, txn_abort "
   8130                                      "or txn_discard");
   8131         if (t) {
   8132             PyErr_SetObject(DBError, t);
   8133             Py_DECREF(t);
   8134         }
   8135         return NULL;
   8136     }
   8137     self->flag_prepare=0;
   8138     txn = self->txn;
   8139     self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
   8140 
   8141     EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
   8142 
   8143     MYDB_BEGIN_ALLOW_THREADS;
   8144     err = txn->commit(txn, flags);
   8145     MYDB_END_ALLOW_THREADS;
   8146 
   8147     _promote_transaction_dbs_and_sequences(self);
   8148 
   8149     RETURN_IF_ERR();
   8150     RETURN_NONE();
   8151 }
   8152 
   8153 static PyObject*
   8154 DBTxn_prepare(DBTxnObject* self, PyObject* args)
   8155 {
   8156     int err;
   8157     char* gid=NULL;
   8158     int   gid_size=0;
   8159 
   8160     if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
   8161         return NULL;
   8162 
   8163     if (gid_size != DB_GID_SIZE) {
   8164         PyErr_SetString(PyExc_TypeError,
   8165                         "gid must be DB_GID_SIZE bytes long");
   8166         return NULL;
   8167     }
   8168 
   8169     if (!self->txn) {
   8170         PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
   8171                                     "after txn_commit, txn_abort "
   8172                                     "or txn_discard");
   8173         if (t) {
   8174             PyErr_SetObject(DBError, t);
   8175             Py_DECREF(t);
   8176         }
   8177         return NULL;
   8178     }
   8179     self->flag_prepare=1;  /* Prepare state */
   8180     MYDB_BEGIN_ALLOW_THREADS;
   8181     err = self->txn->prepare(self->txn, (u_int8_t*)gid);
   8182     MYDB_END_ALLOW_THREADS;
   8183     RETURN_IF_ERR();
   8184     RETURN_NONE();
   8185 }
   8186 
   8187 
   8188 static PyObject*
   8189 DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
   8190 {
   8191     PyObject *dummy;
   8192     int err=0;
   8193     DB_TXN *txn;
   8194 
   8195     if (!self->txn) {
   8196         PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
   8197                                     "after txn_commit, txn_abort "
   8198                                     "or txn_discard");
   8199         if (t) {
   8200             PyErr_SetObject(DBError, t);
   8201             Py_DECREF(t);
   8202         }
   8203         return NULL;
   8204     }
   8205     txn = self->txn;
   8206     self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
   8207 
   8208     _close_transaction_cursors(self);
   8209     while (self->children_sequences) {
   8210         dummy=DBSequence_close_internal(self->children_sequences,0,0);
   8211         Py_XDECREF(dummy);
   8212     }
   8213     while (self->children_dbs) {
   8214         dummy=DB_close_internal(self->children_dbs, 0, 0);
   8215         Py_XDECREF(dummy);
   8216     }
   8217 
   8218     EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
   8219 
   8220     MYDB_BEGIN_ALLOW_THREADS;
   8221     if (discard) {
   8222         assert(!self->flag_prepare);
   8223         err = txn->discard(txn,0);
   8224     } else {
   8225         /*
   8226         ** If the transaction is in the "prepare" or "recover" state,
   8227         ** we better do not implicitly abort it.
   8228         */
   8229         if (!self->flag_prepare) {
   8230             err = txn->abort(txn);
   8231         }
   8232     }
   8233     MYDB_END_ALLOW_THREADS;
   8234     RETURN_IF_ERR();
   8235     RETURN_NONE();
   8236 }
   8237 
   8238 static PyObject*
   8239 DBTxn_abort(DBTxnObject* self)
   8240 {
   8241     self->flag_prepare=0;
   8242     _close_transaction_cursors(self);
   8243 
   8244     return DBTxn_abort_discard_internal(self,0);
   8245 }
   8246 
   8247 static PyObject*
   8248 DBTxn_discard(DBTxnObject* self)
   8249 {
   8250     self->flag_prepare=0;
   8251     _close_transaction_cursors(self);
   8252 
   8253     return DBTxn_abort_discard_internal(self,1);
   8254 }
   8255 
   8256 
   8257 static PyObject*
   8258 DBTxn_id(DBTxnObject* self)
   8259 {
   8260     int id;
   8261 
   8262     if (!self->txn) {
   8263         PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
   8264                                     "after txn_commit, txn_abort "
   8265                                     "or txn_discard");
   8266         if (t) {
   8267             PyErr_SetObject(DBError, t);
   8268             Py_DECREF(t);
   8269         }
   8270         return NULL;
   8271     }
   8272     MYDB_BEGIN_ALLOW_THREADS;
   8273     id = self->txn->id(self->txn);
   8274     MYDB_END_ALLOW_THREADS;
   8275     return NUMBER_FromLong(id);
   8276 }
   8277 
   8278 
   8279 static PyObject*
   8280 DBTxn_set_timeout(DBTxnObject* self, PyObject* args, PyObject* kwargs)
   8281 {
   8282     int err;
   8283     u_int32_t flags=0;
   8284     u_int32_t timeout = 0;
   8285     static char* kwnames[] = { "timeout", "flags", NULL };
   8286 
   8287     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
   8288                 &timeout, &flags)) {
   8289         return NULL;
   8290     }
   8291 
   8292     MYDB_BEGIN_ALLOW_THREADS;
   8293     err = self->txn->set_timeout(self->txn, (db_timeout_t)timeout, flags);
   8294     MYDB_END_ALLOW_THREADS;
   8295 
   8296     RETURN_IF_ERR();
   8297     RETURN_NONE();
   8298 }
   8299 
   8300 
   8301 #if (DBVER >= 44)
   8302 static PyObject*
   8303 DBTxn_set_name(DBTxnObject* self, PyObject* args)
   8304 {
   8305     int err;
   8306     const char *name;
   8307 
   8308     if (!PyArg_ParseTuple(args, "s:set_name", &name))
   8309         return NULL;
   8310 
   8311     MYDB_BEGIN_ALLOW_THREADS;
   8312     err = self->txn->set_name(self->txn, name);
   8313     MYDB_END_ALLOW_THREADS;
   8314 
   8315     RETURN_IF_ERR();
   8316     RETURN_NONE();
   8317 }
   8318 #endif
   8319 
   8320 
   8321 #if (DBVER >= 44)
   8322 static PyObject*
   8323 DBTxn_get_name(DBTxnObject* self)
   8324 {
   8325     int err;
   8326     const char *name;
   8327 
   8328     MYDB_BEGIN_ALLOW_THREADS;
   8329     err = self->txn->get_name(self->txn, &name);
   8330     MYDB_END_ALLOW_THREADS;
   8331 
   8332     RETURN_IF_ERR();
   8333 #if (PY_VERSION_HEX < 0x03000000)
   8334     if (!name) {
   8335         return PyString_FromString("");
   8336     }
   8337     return PyString_FromString(name);
   8338 #else
   8339     if (!name) {
   8340         return PyUnicode_FromString("");
   8341     }
   8342     return PyUnicode_FromString(name);
   8343 #endif
   8344 }
   8345 #endif
   8346 
   8347 
   8348 /* --------------------------------------------------------------------- */
   8349 /* DBSequence methods */
   8350 
   8351 
   8352 static PyObject*
   8353 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
   8354 {
   8355     int err=0;
   8356 
   8357     if (self->sequence!=NULL) {
   8358         EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
   8359         if (self->txn) {
   8360             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
   8361             self->txn=NULL;
   8362         }
   8363 
   8364         /*
   8365         ** "do_not_close" is used to dispose all related objects in the
   8366         ** tree, without actually releasing the "root" object.
   8367         ** This is done, for example, because function calls like
   8368         ** "DBSequence.remove()" implicitly close the underlying handle. So
   8369         ** the handle doesn't need to be closed, but related objects
   8370         ** must be cleaned up.
   8371         */
   8372         if (!do_not_close) {
   8373             MYDB_BEGIN_ALLOW_THREADS
   8374             err = self->sequence->close(self->sequence, flags);
   8375             MYDB_END_ALLOW_THREADS
   8376         }
   8377         self->sequence = NULL;
   8378 
   8379         RETURN_IF_ERR();
   8380     }
   8381 
   8382     RETURN_NONE();
   8383 }
   8384 
   8385 static PyObject*
   8386 DBSequence_close(DBSequenceObject* self, PyObject* args)
   8387 {
   8388     int flags=0;
   8389     if (!PyArg_ParseTuple(args,"|i:close", &flags))
   8390         return NULL;
   8391 
   8392     return DBSequence_close_internal(self,flags,0);
   8393 }
   8394 
   8395 static PyObject*
   8396 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
   8397 {
   8398     int err, flags = 0;
   8399     int delta = 1;
   8400     db_seq_t value;
   8401     PyObject *txnobj = NULL;
   8402     DB_TXN *txn = NULL;
   8403     static char* kwnames[] = {"delta", "txn", "flags", NULL };
   8404     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
   8405         return NULL;
   8406     CHECK_SEQUENCE_NOT_CLOSED(self)
   8407 
   8408     if (!checkTxnObj(txnobj, &txn))
   8409         return NULL;
   8410 
   8411     MYDB_BEGIN_ALLOW_THREADS
   8412     err = self->sequence->get(self->sequence, txn, delta, &value, flags);
   8413     MYDB_END_ALLOW_THREADS
   8414 
   8415     RETURN_IF_ERR();
   8416     return PyLong_FromLongLong(value);
   8417 }
   8418 
   8419 static PyObject*
   8420 DBSequence_get_dbp(DBSequenceObject* self)
   8421 {
   8422     CHECK_SEQUENCE_NOT_CLOSED(self)
   8423     Py_INCREF(self->mydb);
   8424     return (PyObject* )self->mydb;
   8425 }
   8426 
   8427 static PyObject*
   8428 DBSequence_get_key(DBSequenceObject* self)
   8429 {
   8430     int err;
   8431     DBT key;
   8432     PyObject *retval = NULL;
   8433 
   8434     key.flags = DB_DBT_MALLOC;
   8435     CHECK_SEQUENCE_NOT_CLOSED(self)
   8436     MYDB_BEGIN_ALLOW_THREADS
   8437     err = self->sequence->get_key(self->sequence, &key);
   8438     MYDB_END_ALLOW_THREADS
   8439 
   8440     if (!err)
   8441         retval = Build_PyString(key.data, key.size);
   8442 
   8443     FREE_DBT(key);
   8444     RETURN_IF_ERR();
   8445 
   8446     return retval;
   8447 }
   8448 
   8449 static PyObject*
   8450 DBSequence_initial_value(DBSequenceObject* self, PyObject* args)
   8451 {
   8452     int err;
   8453     PY_LONG_LONG value;
   8454     db_seq_t value2;
   8455     if (!PyArg_ParseTuple(args,"L:initial_value", &value))
   8456         return NULL;
   8457     CHECK_SEQUENCE_NOT_CLOSED(self)
   8458 
   8459     value2=value; /* If truncation, compiler should show a warning */
   8460     MYDB_BEGIN_ALLOW_THREADS
   8461     err = self->sequence->initial_value(self->sequence, value2);
   8462     MYDB_END_ALLOW_THREADS
   8463 
   8464     RETURN_IF_ERR();
   8465 
   8466     RETURN_NONE();
   8467 }
   8468 
   8469 static PyObject*
   8470 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
   8471 {
   8472     int err, flags = 0;
   8473     PyObject* keyobj;
   8474     PyObject *txnobj = NULL;
   8475     DB_TXN *txn = NULL;
   8476     DBT key;
   8477 
   8478     static char* kwnames[] = {"key", "txn", "flags", NULL };
   8479     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
   8480         return NULL;
   8481 
   8482     if (!checkTxnObj(txnobj, &txn))
   8483         return NULL;
   8484 
   8485     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
   8486         return NULL;
   8487 
   8488     MYDB_BEGIN_ALLOW_THREADS
   8489     err = self->sequence->open(self->sequence, txn, &key, flags);
   8490     MYDB_END_ALLOW_THREADS
   8491 
   8492     FREE_DBT(key);
   8493     RETURN_IF_ERR();
   8494 
   8495     if (txn) {
   8496         INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
   8497         self->txn=(DBTxnObject *)txnobj;
   8498     }
   8499 
   8500     RETURN_NONE();
   8501 }
   8502 
   8503 static PyObject*
   8504 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
   8505 {
   8506     PyObject *dummy;
   8507     int err, flags = 0;
   8508     PyObject *txnobj = NULL;
   8509     DB_TXN *txn = NULL;
   8510 
   8511     static char* kwnames[] = {"txn", "flags", NULL };
   8512     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
   8513         return NULL;
   8514 
   8515     if (!checkTxnObj(txnobj, &txn))
   8516         return NULL;
   8517 
   8518     CHECK_SEQUENCE_NOT_CLOSED(self)
   8519 
   8520     MYDB_BEGIN_ALLOW_THREADS
   8521     err = self->sequence->remove(self->sequence, txn, flags);
   8522     MYDB_END_ALLOW_THREADS
   8523 
   8524     dummy=DBSequence_close_internal(self,flags,1);
   8525     Py_XDECREF(dummy);
   8526 
   8527     RETURN_IF_ERR();
   8528     RETURN_NONE();
   8529 }
   8530 
   8531 static PyObject*
   8532 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
   8533 {
   8534     int err, size;
   8535     if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
   8536         return NULL;
   8537     CHECK_SEQUENCE_NOT_CLOSED(self)
   8538 
   8539     MYDB_BEGIN_ALLOW_THREADS
   8540     err = self->sequence->set_cachesize(self->sequence, size);
   8541     MYDB_END_ALLOW_THREADS
   8542 
   8543     RETURN_IF_ERR();
   8544     RETURN_NONE();
   8545 }
   8546 
   8547 static PyObject*
   8548 DBSequence_get_cachesize(DBSequenceObject* self)
   8549 {
   8550     int err, size;
   8551 
   8552     CHECK_SEQUENCE_NOT_CLOSED(self)
   8553 
   8554     MYDB_BEGIN_ALLOW_THREADS
   8555     err = self->sequence->get_cachesize(self->sequence, &size);
   8556     MYDB_END_ALLOW_THREADS
   8557 
   8558     RETURN_IF_ERR();
   8559     return NUMBER_FromLong(size);
   8560 }
   8561 
   8562 static PyObject*
   8563 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
   8564 {
   8565     int err, flags = 0;
   8566     if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
   8567         return NULL;
   8568     CHECK_SEQUENCE_NOT_CLOSED(self)
   8569 
   8570     MYDB_BEGIN_ALLOW_THREADS
   8571     err = self->sequence->set_flags(self->sequence, flags);
   8572     MYDB_END_ALLOW_THREADS
   8573 
   8574     RETURN_IF_ERR();
   8575     RETURN_NONE();
   8576 }
   8577 
   8578 static PyObject*
   8579 DBSequence_get_flags(DBSequenceObject* self)
   8580 {
   8581     unsigned int flags;
   8582     int err;
   8583 
   8584     CHECK_SEQUENCE_NOT_CLOSED(self)
   8585 
   8586     MYDB_BEGIN_ALLOW_THREADS
   8587     err = self->sequence->get_flags(self->sequence, &flags);
   8588     MYDB_END_ALLOW_THREADS
   8589 
   8590     RETURN_IF_ERR();
   8591     return NUMBER_FromLong((int)flags);
   8592 }
   8593 
   8594 static PyObject*
   8595 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
   8596 {
   8597     int err;
   8598     PY_LONG_LONG min, max;
   8599     db_seq_t min2, max2;
   8600     if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
   8601         return NULL;
   8602     CHECK_SEQUENCE_NOT_CLOSED(self)
   8603 
   8604     min2=min;  /* If truncation, compiler should show a warning */
   8605     max2=max;
   8606     MYDB_BEGIN_ALLOW_THREADS
   8607     err = self->sequence->set_range(self->sequence, min2, max2);
   8608     MYDB_END_ALLOW_THREADS
   8609 
   8610     RETURN_IF_ERR();
   8611     RETURN_NONE();
   8612 }
   8613 
   8614 static PyObject*
   8615 DBSequence_get_range(DBSequenceObject* self)
   8616 {
   8617     int err;
   8618     PY_LONG_LONG min, max;
   8619     db_seq_t min2, max2;
   8620 
   8621     CHECK_SEQUENCE_NOT_CLOSED(self)
   8622 
   8623     MYDB_BEGIN_ALLOW_THREADS
   8624     err = self->sequence->get_range(self->sequence, &min2, &max2);
   8625     MYDB_END_ALLOW_THREADS
   8626 
   8627     RETURN_IF_ERR();
   8628     min=min2;  /* If truncation, compiler should show a warning */
   8629     max=max2;
   8630     return Py_BuildValue("(LL)", min, max);
   8631 }
   8632 
   8633 
   8634 static PyObject*
   8635 DBSequence_stat_print(DBSequenceObject* self, PyObject* args, PyObject *kwargs)
   8636 {
   8637     int err;
   8638     int flags=0;
   8639     static char* kwnames[] = { "flags", NULL };
   8640 
   8641     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
   8642                 kwnames, &flags))
   8643     {
   8644         return NULL;
   8645     }
   8646 
   8647     CHECK_SEQUENCE_NOT_CLOSED(self);
   8648 
   8649     MYDB_BEGIN_ALLOW_THREADS;
   8650     err = self->sequence->stat_print(self->sequence, flags);
   8651     MYDB_END_ALLOW_THREADS;
   8652     RETURN_IF_ERR();
   8653     RETURN_NONE();
   8654 }
   8655 
   8656 static PyObject*
   8657 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
   8658 {
   8659     int err, flags = 0;
   8660     DB_SEQUENCE_STAT* sp = NULL;
   8661     PyObject* dict_stat;
   8662     static char* kwnames[] = {"flags", NULL };
   8663     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
   8664         return NULL;
   8665     CHECK_SEQUENCE_NOT_CLOSED(self);
   8666 
   8667     MYDB_BEGIN_ALLOW_THREADS;
   8668     err = self->sequence->stat(self->sequence, &sp, flags);
   8669     MYDB_END_ALLOW_THREADS;
   8670     RETURN_IF_ERR();
   8671 
   8672     if ((dict_stat = PyDict_New()) == NULL) {
   8673         free(sp);
   8674         return NULL;
   8675     }
   8676 
   8677 
   8678 #define MAKE_INT_ENTRY(name)  _addIntToDict(dict_stat, #name, sp->st_##name)
   8679 #define MAKE_LONG_LONG_ENTRY(name)  _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
   8680 
   8681     MAKE_INT_ENTRY(wait);
   8682     MAKE_INT_ENTRY(nowait);
   8683     MAKE_LONG_LONG_ENTRY(current);
   8684     MAKE_LONG_LONG_ENTRY(value);
   8685     MAKE_LONG_LONG_ENTRY(last_value);
   8686     MAKE_LONG_LONG_ENTRY(min);
   8687     MAKE_LONG_LONG_ENTRY(max);
   8688     MAKE_INT_ENTRY(cache_size);
   8689     MAKE_INT_ENTRY(flags);
   8690 
   8691 #undef MAKE_INT_ENTRY
   8692 #undef MAKE_LONG_LONG_ENTRY
   8693 
   8694     free(sp);
   8695     return dict_stat;
   8696 }
   8697 
   8698 
   8699 /* --------------------------------------------------------------------- */
   8700 /* Method definition tables and type objects */
   8701 
   8702 static PyMethodDef DB_methods[] = {
   8703     {"append",          (PyCFunction)DB_append,         METH_VARARGS|METH_KEYWORDS},
   8704     {"associate",       (PyCFunction)DB_associate,      METH_VARARGS|METH_KEYWORDS},
   8705     {"close",           (PyCFunction)DB_close,          METH_VARARGS},
   8706 #if (DBVER >= 47)
   8707     {"compact",         (PyCFunction)DB_compact,        METH_VARARGS|METH_KEYWORDS},
   8708 #endif
   8709     {"consume",         (PyCFunction)DB_consume,        METH_VARARGS|METH_KEYWORDS},
   8710     {"consume_wait",    (PyCFunction)DB_consume_wait,   METH_VARARGS|METH_KEYWORDS},
   8711     {"cursor",          (PyCFunction)DB_cursor,         METH_VARARGS|METH_KEYWORDS},
   8712     {"delete",          (PyCFunction)DB_delete,         METH_VARARGS|METH_KEYWORDS},
   8713     {"fd",              (PyCFunction)DB_fd,             METH_NOARGS},
   8714 #if (DBVER >= 46)
   8715     {"exists",          (PyCFunction)DB_exists,
   8716         METH_VARARGS|METH_KEYWORDS},
   8717 #endif
   8718     {"get",             (PyCFunction)DB_get,            METH_VARARGS|METH_KEYWORDS},
   8719     {"pget",            (PyCFunction)DB_pget,           METH_VARARGS|METH_KEYWORDS},
   8720     {"get_both",        (PyCFunction)DB_get_both,       METH_VARARGS|METH_KEYWORDS},
   8721     {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
   8722     {"get_size",        (PyCFunction)DB_get_size,       METH_VARARGS|METH_KEYWORDS},
   8723     {"get_type",        (PyCFunction)DB_get_type,       METH_NOARGS},
   8724     {"join",            (PyCFunction)DB_join,           METH_VARARGS},
   8725     {"key_range",       (PyCFunction)DB_key_range,      METH_VARARGS|METH_KEYWORDS},
   8726     {"has_key",         (PyCFunction)DB_has_key,        METH_VARARGS|METH_KEYWORDS},
   8727     {"items",           (PyCFunction)DB_items,          METH_VARARGS},
   8728     {"keys",            (PyCFunction)DB_keys,           METH_VARARGS},
   8729     {"open",            (PyCFunction)DB_open,           METH_VARARGS|METH_KEYWORDS},
   8730     {"put",             (PyCFunction)DB_put,            METH_VARARGS|METH_KEYWORDS},
   8731     {"remove",          (PyCFunction)DB_remove,         METH_VARARGS|METH_KEYWORDS},
   8732     {"rename",          (PyCFunction)DB_rename,         METH_VARARGS},
   8733     {"set_bt_minkey",   (PyCFunction)DB_set_bt_minkey,  METH_VARARGS},
   8734     {"get_bt_minkey",   (PyCFunction)DB_get_bt_minkey,  METH_NOARGS},
   8735     {"set_bt_compare",  (PyCFunction)DB_set_bt_compare, METH_O},
   8736     {"set_cachesize",   (PyCFunction)DB_set_cachesize,  METH_VARARGS},
   8737     {"get_cachesize",   (PyCFunction)DB_get_cachesize,  METH_NOARGS},
   8738     {"set_dup_compare", (PyCFunction)DB_set_dup_compare, METH_O},
   8739     {"set_encrypt",     (PyCFunction)DB_set_encrypt,    METH_VARARGS|METH_KEYWORDS},
   8740     {"get_encrypt_flags", (PyCFunction)DB_get_encrypt_flags, METH_NOARGS},
   8741     {"set_flags",       (PyCFunction)DB_set_flags,      METH_VARARGS},
   8742     {"get_flags",       (PyCFunction)DB_get_flags,      METH_NOARGS},
   8743     {"get_transactional", (PyCFunction)DB_get_transactional, METH_NOARGS},
   8744     {"set_h_ffactor",   (PyCFunction)DB_set_h_ffactor,  METH_VARARGS},
   8745     {"get_h_ffactor",   (PyCFunction)DB_get_h_ffactor,  METH_NOARGS},
   8746     {"set_h_nelem",     (PyCFunction)DB_set_h_nelem,    METH_VARARGS},
   8747     {"get_h_nelem",     (PyCFunction)DB_get_h_nelem,    METH_NOARGS},
   8748     {"set_lorder",      (PyCFunction)DB_set_lorder,     METH_VARARGS},
   8749     {"get_lorder",      (PyCFunction)DB_get_lorder,     METH_NOARGS},
   8750     {"set_pagesize",    (PyCFunction)DB_set_pagesize,   METH_VARARGS},
   8751     {"get_pagesize",    (PyCFunction)DB_get_pagesize,   METH_NOARGS},
   8752     {"set_re_delim",    (PyCFunction)DB_set_re_delim,   METH_VARARGS},
   8753     {"get_re_delim",    (PyCFunction)DB_get_re_delim,   METH_NOARGS},
   8754     {"set_re_len",      (PyCFunction)DB_set_re_len,     METH_VARARGS},
   8755     {"get_re_len",      (PyCFunction)DB_get_re_len,     METH_NOARGS},
   8756     {"set_re_pad",      (PyCFunction)DB_set_re_pad,     METH_VARARGS},
   8757     {"get_re_pad",      (PyCFunction)DB_get_re_pad,     METH_NOARGS},
   8758     {"set_re_source",   (PyCFunction)DB_set_re_source,  METH_VARARGS},
   8759     {"get_re_source",   (PyCFunction)DB_get_re_source,  METH_NOARGS},
   8760     {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
   8761     {"get_q_extentsize",(PyCFunction)DB_get_q_extentsize, METH_NOARGS},
   8762     {"set_private",     (PyCFunction)DB_set_private,    METH_O},
   8763     {"get_private",     (PyCFunction)DB_get_private,    METH_NOARGS},
   8764 #if (DBVER >= 46)
   8765     {"set_priority",    (PyCFunction)DB_set_priority,   METH_VARARGS},
   8766     {"get_priority",    (PyCFunction)DB_get_priority,   METH_NOARGS},
   8767 #endif
   8768     {"get_dbname",      (PyCFunction)DB_get_dbname,     METH_NOARGS},
   8769     {"get_open_flags",  (PyCFunction)DB_get_open_flags, METH_NOARGS},
   8770     {"stat",            (PyCFunction)DB_stat,           METH_VARARGS|METH_KEYWORDS},
   8771     {"stat_print",      (PyCFunction)DB_stat_print,
   8772         METH_VARARGS|METH_KEYWORDS},
   8773     {"sync",            (PyCFunction)DB_sync,           METH_VARARGS},
   8774     {"truncate",        (PyCFunction)DB_truncate,       METH_VARARGS|METH_KEYWORDS},
   8775     {"type",            (PyCFunction)DB_get_type,       METH_NOARGS},
   8776     {"upgrade",         (PyCFunction)DB_upgrade,        METH_VARARGS},
   8777     {"values",          (PyCFunction)DB_values,         METH_VARARGS},
   8778     {"verify",          (PyCFunction)DB_verify,         METH_VARARGS|METH_KEYWORDS},
   8779     {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none,      METH_VARARGS},
   8780     {NULL,      NULL}       /* sentinel */
   8781 };
   8782 
   8783 
   8784 /* We need this to support __contains__() */
   8785 static PySequenceMethods DB_sequence = {
   8786     0, /* sq_length, mapping wins here */
   8787     0, /* sq_concat */
   8788     0, /* sq_repeat */
   8789     0, /* sq_item */
   8790     0, /* sq_slice */
   8791     0, /* sq_ass_item */
   8792     0, /* sq_ass_slice */
   8793     (objobjproc)DB_contains, /* sq_contains */
   8794     0, /* sq_inplace_concat */
   8795     0, /* sq_inplace_repeat */
   8796 };
   8797 
   8798 static PyMappingMethods DB_mapping = {
   8799         DB_length,                   /*mp_length*/
   8800         (binaryfunc)DB_subscript,    /*mp_subscript*/
   8801         (objobjargproc)DB_ass_sub,   /*mp_ass_subscript*/
   8802 };
   8803 
   8804 
   8805 static PyMethodDef DBCursor_methods[] = {
   8806     {"close",           (PyCFunction)DBC_close,         METH_NOARGS},
   8807     {"count",           (PyCFunction)DBC_count,         METH_VARARGS},
   8808     {"current",         (PyCFunction)DBC_current,       METH_VARARGS|METH_KEYWORDS},
   8809     {"delete",          (PyCFunction)DBC_delete,        METH_VARARGS},
   8810     {"dup",             (PyCFunction)DBC_dup,           METH_VARARGS},
   8811     {"first",           (PyCFunction)DBC_first,         METH_VARARGS|METH_KEYWORDS},
   8812     {"get",             (PyCFunction)DBC_get,           METH_VARARGS|METH_KEYWORDS},
   8813     {"pget",            (PyCFunction)DBC_pget,          METH_VARARGS|METH_KEYWORDS},
   8814     {"get_recno",       (PyCFunction)DBC_get_recno,     METH_NOARGS},
   8815     {"last",            (PyCFunction)DBC_last,          METH_VARARGS|METH_KEYWORDS},
   8816     {"next",            (PyCFunction)DBC_next,          METH_VARARGS|METH_KEYWORDS},
   8817     {"prev",            (PyCFunction)DBC_prev,          METH_VARARGS|METH_KEYWORDS},
   8818     {"put",             (PyCFunction)DBC_put,           METH_VARARGS|METH_KEYWORDS},
   8819     {"set",             (PyCFunction)DBC_set,           METH_VARARGS|METH_KEYWORDS},
   8820     {"set_range",       (PyCFunction)DBC_set_range,     METH_VARARGS|METH_KEYWORDS},
   8821     {"get_both",        (PyCFunction)DBC_get_both,      METH_VARARGS},
   8822     {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
   8823     {"set_both",        (PyCFunction)DBC_set_both,      METH_VARARGS},
   8824     {"set_recno",       (PyCFunction)DBC_set_recno,     METH_VARARGS|METH_KEYWORDS},
   8825     {"consume",         (PyCFunction)DBC_consume,       METH_VARARGS|METH_KEYWORDS},
   8826     {"next_dup",        (PyCFunction)DBC_next_dup,      METH_VARARGS|METH_KEYWORDS},
   8827     {"next_nodup",      (PyCFunction)DBC_next_nodup,    METH_VARARGS|METH_KEYWORDS},
   8828 #if (DBVER >= 46)
   8829     {"prev_dup",        (PyCFunction)DBC_prev_dup,
   8830         METH_VARARGS|METH_KEYWORDS},
   8831 #endif
   8832     {"prev_nodup",      (PyCFunction)DBC_prev_nodup,    METH_VARARGS|METH_KEYWORDS},
   8833     {"join_item",       (PyCFunction)DBC_join_item,     METH_VARARGS},
   8834 #if (DBVER >= 46)
   8835     {"set_priority",    (PyCFunction)DBC_set_priority,
   8836         METH_VARARGS|METH_KEYWORDS},
   8837     {"get_priority",    (PyCFunction)DBC_get_priority, METH_NOARGS},
   8838 #endif
   8839     {NULL,      NULL}       /* sentinel */
   8840 };
   8841 
   8842 
   8843 static PyMethodDef DBLogCursor_methods[] = {
   8844     {"close",   (PyCFunction)DBLogCursor_close,     METH_NOARGS},
   8845     {"current", (PyCFunction)DBLogCursor_current,   METH_NOARGS},
   8846     {"first",   (PyCFunction)DBLogCursor_first,     METH_NOARGS},
   8847     {"last",    (PyCFunction)DBLogCursor_last,      METH_NOARGS},
   8848     {"next",    (PyCFunction)DBLogCursor_next,      METH_NOARGS},
   8849     {"prev",    (PyCFunction)DBLogCursor_prev,      METH_NOARGS},
   8850     {"set",     (PyCFunction)DBLogCursor_set,       METH_VARARGS},
   8851     {NULL,      NULL}       /* sentinel */
   8852 };
   8853 
   8854 #if (DBVER >= 52)
   8855 static PyMethodDef DBSite_methods[] = {
   8856     {"get_config",  (PyCFunction)DBSite_get_config,
   8857         METH_VARARGS | METH_KEYWORDS},
   8858     {"set_config",  (PyCFunction)DBSite_set_config,
   8859         METH_VARARGS | METH_KEYWORDS},
   8860     {"remove",      (PyCFunction)DBSite_remove,     METH_NOARGS},
   8861     {"get_eid",     (PyCFunction)DBSite_get_eid,    METH_NOARGS},
   8862     {"get_address", (PyCFunction)DBSite_get_address,    METH_NOARGS},
   8863     {"close",       (PyCFunction)DBSite_close,      METH_NOARGS},
   8864     {NULL,      NULL}       /* sentinel */
   8865 };
   8866 #endif
   8867 
   8868 static PyMethodDef DBEnv_methods[] = {
   8869     {"close",           (PyCFunction)DBEnv_close,            METH_VARARGS},
   8870     {"open",            (PyCFunction)DBEnv_open,             METH_VARARGS},
   8871     {"remove",          (PyCFunction)DBEnv_remove,           METH_VARARGS},
   8872     {"dbremove",        (PyCFunction)DBEnv_dbremove,         METH_VARARGS|METH_KEYWORDS},
   8873     {"dbrename",        (PyCFunction)DBEnv_dbrename,         METH_VARARGS|METH_KEYWORDS},
   8874 #if (DBVER >= 46)
   8875     {"set_thread_count", (PyCFunction)DBEnv_set_thread_count, METH_VARARGS},
   8876     {"get_thread_count", (PyCFunction)DBEnv_get_thread_count, METH_NOARGS},
   8877 #endif
   8878     {"set_encrypt",     (PyCFunction)DBEnv_set_encrypt,      METH_VARARGS|METH_KEYWORDS},
   8879     {"get_encrypt_flags", (PyCFunction)DBEnv_get_encrypt_flags, METH_NOARGS},
   8880     {"get_timeout",     (PyCFunction)DBEnv_get_timeout,
   8881         METH_VARARGS|METH_KEYWORDS},
   8882     {"set_timeout",     (PyCFunction)DBEnv_set_timeout,     METH_VARARGS|METH_KEYWORDS},
   8883     {"set_shm_key",     (PyCFunction)DBEnv_set_shm_key,     METH_VARARGS},
   8884     {"get_shm_key",     (PyCFunction)DBEnv_get_shm_key,     METH_NOARGS},
   8885 #if (DBVER >= 46)
   8886     {"set_cache_max",   (PyCFunction)DBEnv_set_cache_max,   METH_VARARGS},
   8887     {"get_cache_max",   (PyCFunction)DBEnv_get_cache_max,   METH_NOARGS},
   8888 #endif
   8889     {"set_cachesize",   (PyCFunction)DBEnv_set_cachesize,   METH_VARARGS},
   8890     {"get_cachesize",   (PyCFunction)DBEnv_get_cachesize,   METH_NOARGS},
   8891     {"memp_trickle",    (PyCFunction)DBEnv_memp_trickle,    METH_VARARGS},
   8892     {"memp_sync",       (PyCFunction)DBEnv_memp_sync,       METH_VARARGS},
   8893     {"memp_stat",       (PyCFunction)DBEnv_memp_stat,
   8894         METH_VARARGS|METH_KEYWORDS},
   8895     {"memp_stat_print", (PyCFunction)DBEnv_memp_stat_print,
   8896         METH_VARARGS|METH_KEYWORDS},
   8897 #if (DBVER >= 44)
   8898     {"mutex_set_max",   (PyCFunction)DBEnv_mutex_set_max,   METH_VARARGS},
   8899     {"mutex_get_max",   (PyCFunction)DBEnv_mutex_get_max,   METH_NOARGS},
   8900     {"mutex_set_align", (PyCFunction)DBEnv_mutex_set_align, METH_VARARGS},
   8901     {"mutex_get_align", (PyCFunction)DBEnv_mutex_get_align, METH_NOARGS},
   8902     {"mutex_set_increment", (PyCFunction)DBEnv_mutex_set_increment,
   8903         METH_VARARGS},
   8904     {"mutex_get_increment", (PyCFunction)DBEnv_mutex_get_increment,
   8905         METH_NOARGS},
   8906     {"mutex_set_tas_spins", (PyCFunction)DBEnv_mutex_set_tas_spins,
   8907         METH_VARARGS},
   8908     {"mutex_get_tas_spins", (PyCFunction)DBEnv_mutex_get_tas_spins,
   8909         METH_NOARGS},
   8910     {"mutex_stat",      (PyCFunction)DBEnv_mutex_stat,      METH_VARARGS},
   8911 #if (DBVER >= 44)
   8912     {"mutex_stat_print", (PyCFunction)DBEnv_mutex_stat_print,
   8913                                          METH_VARARGS|METH_KEYWORDS},
   8914 #endif
   8915 #endif
   8916     {"set_data_dir",    (PyCFunction)DBEnv_set_data_dir,    METH_VARARGS},
   8917     {"get_data_dirs",   (PyCFunction)DBEnv_get_data_dirs,   METH_NOARGS},
   8918     {"get_flags",       (PyCFunction)DBEnv_get_flags,       METH_NOARGS},
   8919     {"set_flags",       (PyCFunction)DBEnv_set_flags,       METH_VARARGS},
   8920 #if (DBVER >= 47)
   8921     {"log_set_config",  (PyCFunction)DBEnv_log_set_config,  METH_VARARGS},
   8922     {"log_get_config",  (PyCFunction)DBEnv_log_get_config,  METH_VARARGS},
   8923 #endif
   8924     {"set_lg_bsize",    (PyCFunction)DBEnv_set_lg_bsize,    METH_VARARGS},
   8925     {"get_lg_bsize",    (PyCFunction)DBEnv_get_lg_bsize,    METH_NOARGS},
   8926     {"set_lg_dir",      (PyCFunction)DBEnv_set_lg_dir,      METH_VARARGS},
   8927     {"get_lg_dir",      (PyCFunction)DBEnv_get_lg_dir,      METH_NOARGS},
   8928     {"set_lg_max",      (PyCFunction)DBEnv_set_lg_max,      METH_VARARGS},
   8929     {"get_lg_max",      (PyCFunction)DBEnv_get_lg_max,      METH_NOARGS},
   8930     {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
   8931     {"get_lg_regionmax",(PyCFunction)DBEnv_get_lg_regionmax, METH_NOARGS},
   8932 #if (DBVER >= 44)
   8933     {"set_lg_filemode", (PyCFunction)DBEnv_set_lg_filemode, METH_VARARGS},
   8934     {"get_lg_filemode", (PyCFunction)DBEnv_get_lg_filemode, METH_NOARGS},
   8935 #endif
   8936 #if (DBVER >= 47)
   8937     {"set_lk_partitions", (PyCFunction)DBEnv_set_lk_partitions, METH_VARARGS},
   8938     {"get_lk_partitions", (PyCFunction)DBEnv_get_lk_partitions, METH_NOARGS},
   8939 #endif
   8940     {"set_lk_detect",   (PyCFunction)DBEnv_set_lk_detect,   METH_VARARGS},
   8941     {"get_lk_detect",   (PyCFunction)DBEnv_get_lk_detect,   METH_NOARGS},
   8942 #if (DBVER < 45)
   8943     {"set_lk_max",      (PyCFunction)DBEnv_set_lk_max,      METH_VARARGS},
   8944 #endif
   8945     {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
   8946     {"get_lk_max_locks", (PyCFunction)DBEnv_get_lk_max_locks, METH_NOARGS},
   8947     {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
   8948     {"get_lk_max_lockers", (PyCFunction)DBEnv_get_lk_max_lockers, METH_NOARGS},
   8949     {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
   8950     {"get_lk_max_objects", (PyCFunction)DBEnv_get_lk_max_objects, METH_NOARGS},
   8951     {"stat_print",          (PyCFunction)DBEnv_stat_print,
   8952         METH_VARARGS|METH_KEYWORDS},
   8953     {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
   8954     {"get_mp_mmapsize", (PyCFunction)DBEnv_get_mp_mmapsize, METH_NOARGS},
   8955     {"set_tmp_dir",     (PyCFunction)DBEnv_set_tmp_dir,     METH_VARARGS},
   8956     {"get_tmp_dir",     (PyCFunction)DBEnv_get_tmp_dir,     METH_NOARGS},
   8957     {"txn_begin",       (PyCFunction)DBEnv_txn_begin,       METH_VARARGS|METH_KEYWORDS},
   8958     {"txn_checkpoint",  (PyCFunction)DBEnv_txn_checkpoint,  METH_VARARGS},
   8959     {"txn_stat",        (PyCFunction)DBEnv_txn_stat,        METH_VARARGS},
   8960     {"txn_stat_print",  (PyCFunction)DBEnv_txn_stat_print,
   8961         METH_VARARGS|METH_KEYWORDS},
   8962     {"get_tx_max",      (PyCFunction)DBEnv_get_tx_max,      METH_NOARGS},
   8963     {"get_tx_timestamp", (PyCFunction)DBEnv_get_tx_timestamp, METH_NOARGS},
   8964     {"set_tx_max",      (PyCFunction)DBEnv_set_tx_max,      METH_VARARGS},
   8965     {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
   8966     {"lock_detect",     (PyCFunction)DBEnv_lock_detect,     METH_VARARGS},
   8967     {"lock_get",        (PyCFunction)DBEnv_lock_get,        METH_VARARGS},
   8968     {"lock_id",         (PyCFunction)DBEnv_lock_id,         METH_NOARGS},
   8969     {"lock_id_free",    (PyCFunction)DBEnv_lock_id_free,    METH_VARARGS},
   8970     {"lock_put",        (PyCFunction)DBEnv_lock_put,        METH_VARARGS},
   8971     {"lock_stat",       (PyCFunction)DBEnv_lock_stat,       METH_VARARGS},
   8972     {"lock_stat_print", (PyCFunction)DBEnv_lock_stat_print,
   8973         METH_VARARGS|METH_KEYWORDS},
   8974     {"log_cursor",      (PyCFunction)DBEnv_log_cursor,      METH_NOARGS},
   8975     {"log_file",        (PyCFunction)DBEnv_log_file,        METH_VARARGS},
   8976 #if (DBVER >= 44)
   8977     {"log_printf",      (PyCFunction)DBEnv_log_printf,
   8978         METH_VARARGS|METH_KEYWORDS},
   8979 #endif
   8980     {"log_archive",     (PyCFunction)DBEnv_log_archive,     METH_VARARGS},
   8981     {"log_flush",       (PyCFunction)DBEnv_log_flush,       METH_NOARGS},
   8982     {"log_stat",        (PyCFunction)DBEnv_log_stat,        METH_VARARGS},
   8983     {"log_stat_print",  (PyCFunction)DBEnv_log_stat_print,
   8984         METH_VARARGS|METH_KEYWORDS},
   8985 #if (DBVER >= 44)
   8986     {"fileid_reset",    (PyCFunction)DBEnv_fileid_reset,    METH_VARARGS|METH_KEYWORDS},
   8987     {"lsn_reset",       (PyCFunction)DBEnv_lsn_reset,       METH_VARARGS|METH_KEYWORDS},
   8988 #endif
   8989     {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
   8990     {"txn_recover",     (PyCFunction)DBEnv_txn_recover,     METH_NOARGS},
   8991 #if (DBVER < 48)
   8992     {"set_rpc_server",  (PyCFunction)DBEnv_set_rpc_server,
   8993         METH_VARARGS|METH_KEYWORDS},
   8994 #endif
   8995     {"set_mp_max_openfd", (PyCFunction)DBEnv_set_mp_max_openfd, METH_VARARGS},
   8996     {"get_mp_max_openfd", (PyCFunction)DBEnv_get_mp_max_openfd, METH_NOARGS},
   8997     {"set_mp_max_write", (PyCFunction)DBEnv_set_mp_max_write, METH_VARARGS},
   8998     {"get_mp_max_write", (PyCFunction)DBEnv_get_mp_max_write, METH_NOARGS},
   8999     {"set_verbose",     (PyCFunction)DBEnv_set_verbose,     METH_VARARGS},
   9000     {"get_verbose",     (PyCFunction)DBEnv_get_verbose,     METH_VARARGS},
   9001     {"set_private",     (PyCFunction)DBEnv_set_private,     METH_O},
   9002     {"get_private",     (PyCFunction)DBEnv_get_private,     METH_NOARGS},
   9003     {"get_open_flags",  (PyCFunction)DBEnv_get_open_flags,  METH_NOARGS},
   9004 #if (DBVER >= 47)
   9005     {"set_intermediate_dir_mode", (PyCFunction)DBEnv_set_intermediate_dir_mode,
   9006         METH_VARARGS},
   9007     {"get_intermediate_dir_mode", (PyCFunction)DBEnv_get_intermediate_dir_mode,
   9008         METH_NOARGS},
   9009 #endif
   9010 #if (DBVER < 47)
   9011     {"set_intermediate_dir", (PyCFunction)DBEnv_set_intermediate_dir,
   9012         METH_VARARGS},
   9013 #endif
   9014     {"rep_start",       (PyCFunction)DBEnv_rep_start,
   9015         METH_VARARGS|METH_KEYWORDS},
   9016     {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
   9017     {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
   9018         METH_VARARGS},
   9019 #if (DBVER >= 46)
   9020     {"rep_elect",       (PyCFunction)DBEnv_rep_elect,         METH_VARARGS},
   9021 #endif
   9022 #if (DBVER >= 44)
   9023     {"rep_set_config",  (PyCFunction)DBEnv_rep_set_config,    METH_VARARGS},
   9024     {"rep_get_config",  (PyCFunction)DBEnv_rep_get_config,    METH_VARARGS},
   9025     {"rep_sync",        (PyCFunction)DBEnv_rep_sync,          METH_NOARGS},
   9026 #endif
   9027 #if (DBVER >= 45)
   9028     {"rep_set_limit",   (PyCFunction)DBEnv_rep_set_limit,     METH_VARARGS},
   9029     {"rep_get_limit",   (PyCFunction)DBEnv_rep_get_limit,     METH_NOARGS},
   9030 #endif
   9031 #if (DBVER >= 47)
   9032     {"rep_set_request", (PyCFunction)DBEnv_rep_set_request,   METH_VARARGS},
   9033     {"rep_get_request", (PyCFunction)DBEnv_rep_get_request,   METH_NOARGS},
   9034 #endif
   9035 #if (DBVER >= 45)
   9036     {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
   9037 #endif
   9038 #if (DBVER >= 45)
   9039     {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
   9040     {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
   9041     {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
   9042     {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
   9043     {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
   9044     {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
   9045 #endif
   9046 #if (DBVER >= 47)
   9047     {"rep_set_clockskew", (PyCFunction)DBEnv_rep_set_clockskew, METH_VARARGS},
   9048     {"rep_get_clockskew", (PyCFunction)DBEnv_rep_get_clockskew, METH_VARARGS},
   9049 #endif
   9050     {"rep_stat", (PyCFunction)DBEnv_rep_stat,
   9051         METH_VARARGS|METH_KEYWORDS},
   9052     {"rep_stat_print", (PyCFunction)DBEnv_rep_stat_print,
   9053         METH_VARARGS|METH_KEYWORDS},
   9054 
   9055 #if (DBVER >= 45)
   9056     {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
   9057         METH_VARARGS|METH_KEYWORDS},
   9058 #if (DBVER < 52)
   9059     {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
   9060         METH_VARARGS|METH_KEYWORDS},
   9061     {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
   9062         METH_VARARGS|METH_KEYWORDS},
   9063 #endif
   9064     {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
   9065         METH_VARARGS},
   9066     {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
   9067         METH_NOARGS},
   9068     {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
   9069         METH_NOARGS},
   9070 #endif
   9071 #if (DBVER >= 46)
   9072     {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
   9073         METH_VARARGS|METH_KEYWORDS},
   9074     {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
   9075         METH_VARARGS|METH_KEYWORDS},
   9076 #endif
   9077 #if (DBVER >= 52)
   9078     {"repmgr_site", (PyCFunction)DBEnv_repmgr_site,
   9079         METH_VARARGS | METH_KEYWORDS},
   9080     {"repmgr_site_by_eid",  (PyCFunction)DBEnv_repmgr_site_by_eid,
   9081         METH_VARARGS | METH_KEYWORDS},
   9082 #endif
   9083     {NULL,      NULL}       /* sentinel */
   9084 };
   9085 
   9086 
   9087 static PyMethodDef DBTxn_methods[] = {
   9088     {"commit",          (PyCFunction)DBTxn_commit,      METH_VARARGS},
   9089     {"prepare",         (PyCFunction)DBTxn_prepare,     METH_VARARGS},
   9090     {"discard",         (PyCFunction)DBTxn_discard,     METH_NOARGS},
   9091     {"abort",           (PyCFunction)DBTxn_abort,       METH_NOARGS},
   9092     {"id",              (PyCFunction)DBTxn_id,          METH_NOARGS},
   9093     {"set_timeout",     (PyCFunction)DBTxn_set_timeout,
   9094         METH_VARARGS|METH_KEYWORDS},
   9095 #if (DBVER >= 44)
   9096     {"set_name",        (PyCFunction)DBTxn_set_name, METH_VARARGS},
   9097     {"get_name",        (PyCFunction)DBTxn_get_name, METH_NOARGS},
   9098 #endif
   9099     {NULL,      NULL}       /* sentinel */
   9100 };
   9101 
   9102 
   9103 static PyMethodDef DBSequence_methods[] = {
   9104     {"close",           (PyCFunction)DBSequence_close,          METH_VARARGS},
   9105     {"get",             (PyCFunction)DBSequence_get,            METH_VARARGS|METH_KEYWORDS},
   9106     {"get_dbp",         (PyCFunction)DBSequence_get_dbp,        METH_NOARGS},
   9107     {"get_key",         (PyCFunction)DBSequence_get_key,        METH_NOARGS},
   9108     {"initial_value",   (PyCFunction)DBSequence_initial_value,  METH_VARARGS},
   9109     {"open",            (PyCFunction)DBSequence_open,           METH_VARARGS|METH_KEYWORDS},
   9110     {"remove",          (PyCFunction)DBSequence_remove,         METH_VARARGS|METH_KEYWORDS},
   9111     {"set_cachesize",   (PyCFunction)DBSequence_set_cachesize,  METH_VARARGS},
   9112     {"get_cachesize",   (PyCFunction)DBSequence_get_cachesize,  METH_NOARGS},
   9113     {"set_flags",       (PyCFunction)DBSequence_set_flags,      METH_VARARGS},
   9114     {"get_flags",       (PyCFunction)DBSequence_get_flags,      METH_NOARGS},
   9115     {"set_range",       (PyCFunction)DBSequence_set_range,      METH_VARARGS},
   9116     {"get_range",       (PyCFunction)DBSequence_get_range,      METH_NOARGS},
   9117     {"stat",            (PyCFunction)DBSequence_stat,           METH_VARARGS|METH_KEYWORDS},
   9118     {"stat_print",      (PyCFunction)DBSequence_stat_print,
   9119         METH_VARARGS|METH_KEYWORDS},
   9120     {NULL,      NULL}       /* sentinel */
   9121 };
   9122 
   9123 
   9124 static PyObject*
   9125 DBEnv_db_home_get(DBEnvObject* self)
   9126 {
   9127     const char *home = NULL;
   9128 
   9129     CHECK_ENV_NOT_CLOSED(self);
   9130 
   9131     MYDB_BEGIN_ALLOW_THREADS;
   9132     self->db_env->get_home(self->db_env, &home);
   9133     MYDB_END_ALLOW_THREADS;
   9134 
   9135     if (home == NULL) {
   9136         RETURN_NONE();
   9137     }
   9138     return PyBytes_FromString(home);
   9139 }
   9140 
   9141 static PyGetSetDef DBEnv_getsets[] = {
   9142     {"db_home", (getter)DBEnv_db_home_get, NULL,},
   9143     {NULL}
   9144 };
   9145 
   9146 
   9147 statichere PyTypeObject DB_Type = {
   9148 #if (PY_VERSION_HEX < 0x03000000)
   9149     PyObject_HEAD_INIT(NULL)
   9150     0,                  /*ob_size*/
   9151 #else
   9152     PyVarObject_HEAD_INIT(NULL, 0)
   9153 #endif
   9154     "DB",               /*tp_name*/
   9155     sizeof(DBObject),   /*tp_basicsize*/
   9156     0,                  /*tp_itemsize*/
   9157     /* methods */
   9158     (destructor)DB_dealloc, /*tp_dealloc*/
   9159     0,          /*tp_print*/
   9160     0,          /*tp_getattr*/
   9161     0,          /*tp_setattr*/
   9162     0,          /*tp_compare*/
   9163     0,          /*tp_repr*/
   9164     0,          /*tp_as_number*/
   9165     &DB_sequence,/*tp_as_sequence*/
   9166     &DB_mapping,/*tp_as_mapping*/
   9167     0,          /*tp_hash*/
   9168     0,                  /* tp_call */
   9169     0,                  /* tp_str */
   9170     0,                  /* tp_getattro */
   9171     0,          /* tp_setattro */
   9172     0,                  /* tp_as_buffer */
   9173 #if (PY_VERSION_HEX < 0x03000000)
   9174     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9175 #else
   9176     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9177 #endif
   9178     0,          /* tp_doc */
   9179     0,              /* tp_traverse */
   9180     0,                  /* tp_clear */
   9181     0,                  /* tp_richcompare */
   9182     offsetof(DBObject, in_weakreflist),   /* tp_weaklistoffset */
   9183     0,          /*tp_iter*/
   9184     0,          /*tp_iternext*/
   9185     DB_methods, /*tp_methods*/
   9186     0, /*tp_members*/
   9187 };
   9188 
   9189 
   9190 statichere PyTypeObject DBCursor_Type = {
   9191 #if (PY_VERSION_HEX < 0x03000000)
   9192     PyObject_HEAD_INIT(NULL)
   9193     0,                  /*ob_size*/
   9194 #else
   9195     PyVarObject_HEAD_INIT(NULL, 0)
   9196 #endif
   9197     "DBCursor",         /*tp_name*/
   9198     sizeof(DBCursorObject),  /*tp_basicsize*/
   9199     0,          /*tp_itemsize*/
   9200     /* methods */
   9201     (destructor)DBCursor_dealloc,/*tp_dealloc*/
   9202     0,          /*tp_print*/
   9203     0,          /*tp_getattr*/
   9204     0,          /*tp_setattr*/
   9205     0,          /*tp_compare*/
   9206     0,          /*tp_repr*/
   9207     0,          /*tp_as_number*/
   9208     0,          /*tp_as_sequence*/
   9209     0,          /*tp_as_mapping*/
   9210     0,          /*tp_hash*/
   9211     0,          /*tp_call*/
   9212     0,          /*tp_str*/
   9213     0,          /*tp_getattro*/
   9214     0,          /*tp_setattro*/
   9215     0,          /*tp_as_buffer*/
   9216 #if (PY_VERSION_HEX < 0x03000000)
   9217     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9218 #else
   9219     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9220 #endif
   9221     0,          /* tp_doc */
   9222     0,          /* tp_traverse */
   9223     0,          /* tp_clear */
   9224     0,          /* tp_richcompare */
   9225     offsetof(DBCursorObject, in_weakreflist),   /* tp_weaklistoffset */
   9226     0,          /*tp_iter*/
   9227     0,          /*tp_iternext*/
   9228     DBCursor_methods, /*tp_methods*/
   9229     0,          /*tp_members*/
   9230 };
   9231 
   9232 
   9233 statichere PyTypeObject DBLogCursor_Type = {
   9234 #if (PY_VERSION_HEX < 0x03000000)
   9235     PyObject_HEAD_INIT(NULL)
   9236     0,                  /*ob_size*/
   9237 #else
   9238     PyVarObject_HEAD_INIT(NULL, 0)
   9239 #endif
   9240     "DBLogCursor",         /*tp_name*/
   9241     sizeof(DBLogCursorObject),  /*tp_basicsize*/
   9242     0,          /*tp_itemsize*/
   9243     /* methods */
   9244     (destructor)DBLogCursor_dealloc,/*tp_dealloc*/
   9245     0,          /*tp_print*/
   9246     0,          /*tp_getattr*/
   9247     0,          /*tp_setattr*/
   9248     0,          /*tp_compare*/
   9249     0,          /*tp_repr*/
   9250     0,          /*tp_as_number*/
   9251     0,          /*tp_as_sequence*/
   9252     0,          /*tp_as_mapping*/
   9253     0,          /*tp_hash*/
   9254     0,          /*tp_call*/
   9255     0,          /*tp_str*/
   9256     0,          /*tp_getattro*/
   9257     0,          /*tp_setattro*/
   9258     0,          /*tp_as_buffer*/
   9259 #if (PY_VERSION_HEX < 0x03000000)
   9260     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9261 #else
   9262     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9263 #endif
   9264     0,          /* tp_doc */
   9265     0,          /* tp_traverse */
   9266     0,          /* tp_clear */
   9267     0,          /* tp_richcompare */
   9268     offsetof(DBLogCursorObject, in_weakreflist),   /* tp_weaklistoffset */
   9269     0,          /*tp_iter*/
   9270     0,          /*tp_iternext*/
   9271     DBLogCursor_methods, /*tp_methods*/
   9272     0,          /*tp_members*/
   9273 };
   9274 
   9275 #if (DBVER >= 52)
   9276 statichere PyTypeObject DBSite_Type = {
   9277 #if (PY_VERSION_HEX < 0x03000000)
   9278     PyObject_HEAD_INIT(NULL)
   9279     0,                  /*ob_size*/
   9280 #else
   9281     PyVarObject_HEAD_INIT(NULL, 0)
   9282 #endif
   9283     "DBSite",         /*tp_name*/
   9284     sizeof(DBSiteObject),  /*tp_basicsize*/
   9285     0,          /*tp_itemsize*/
   9286     /* methods */
   9287     (destructor)DBSite_dealloc,/*tp_dealloc*/
   9288     0,          /*tp_print*/
   9289     0,          /*tp_getattr*/
   9290     0,          /*tp_setattr*/
   9291     0,          /*tp_compare*/
   9292     0,          /*tp_repr*/
   9293     0,          /*tp_as_number*/
   9294     0,          /*tp_as_sequence*/
   9295     0,          /*tp_as_mapping*/
   9296     0,          /*tp_hash*/
   9297     0,          /*tp_call*/
   9298     0,          /*tp_str*/
   9299     0,          /*tp_getattro*/
   9300     0,          /*tp_setattro*/
   9301     0,          /*tp_as_buffer*/
   9302 #if (PY_VERSION_HEX < 0x03000000)
   9303     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9304 #else
   9305     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9306 #endif
   9307     0,          /* tp_doc */
   9308     0,          /* tp_traverse */
   9309     0,          /* tp_clear */
   9310     0,          /* tp_richcompare */
   9311     offsetof(DBSiteObject, in_weakreflist),   /* tp_weaklistoffset */
   9312     0,          /*tp_iter*/
   9313     0,          /*tp_iternext*/
   9314     DBSite_methods, /*tp_methods*/
   9315     0,          /*tp_members*/
   9316 };
   9317 #endif
   9318 
   9319 statichere PyTypeObject DBEnv_Type = {
   9320 #if (PY_VERSION_HEX < 0x03000000)
   9321     PyObject_HEAD_INIT(NULL)
   9322     0,                  /*ob_size*/
   9323 #else
   9324     PyVarObject_HEAD_INIT(NULL, 0)
   9325 #endif
   9326     "DBEnv",            /*tp_name*/
   9327     sizeof(DBEnvObject),    /*tp_basicsize*/
   9328     0,          /*tp_itemsize*/
   9329     /* methods */
   9330     (destructor)DBEnv_dealloc, /*tp_dealloc*/
   9331     0,          /*tp_print*/
   9332     0,          /*tp_getattr*/
   9333     0,          /*tp_setattr*/
   9334     0,          /*tp_compare*/
   9335     0,          /*tp_repr*/
   9336     0,          /*tp_as_number*/
   9337     0,          /*tp_as_sequence*/
   9338     0,          /*tp_as_mapping*/
   9339     0,          /*tp_hash*/
   9340     0,                  /* tp_call */
   9341     0,                  /* tp_str */
   9342     0,                  /* tp_getattro */
   9343     0,          /* tp_setattro */
   9344     0,                  /* tp_as_buffer */
   9345 #if (PY_VERSION_HEX < 0x03000000)
   9346     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9347 #else
   9348     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9349 #endif
   9350     0,          /* tp_doc */
   9351     0,              /* tp_traverse */
   9352     0,                  /* tp_clear */
   9353     0,                  /* tp_richcompare */
   9354     offsetof(DBEnvObject, in_weakreflist),   /* tp_weaklistoffset */
   9355     0,          /* tp_iter */
   9356     0,          /* tp_iternext */
   9357     DBEnv_methods,      /* tp_methods */
   9358     0,          /* tp_members */
   9359     DBEnv_getsets,      /* tp_getsets */
   9360 };
   9361 
   9362 statichere PyTypeObject DBTxn_Type = {
   9363 #if (PY_VERSION_HEX < 0x03000000)
   9364     PyObject_HEAD_INIT(NULL)
   9365     0,                  /*ob_size*/
   9366 #else
   9367     PyVarObject_HEAD_INIT(NULL, 0)
   9368 #endif
   9369     "DBTxn",    /*tp_name*/
   9370     sizeof(DBTxnObject),  /*tp_basicsize*/
   9371     0,          /*tp_itemsize*/
   9372     /* methods */
   9373     (destructor)DBTxn_dealloc, /*tp_dealloc*/
   9374     0,          /*tp_print*/
   9375     0,          /*tp_getattr*/
   9376     0,          /*tp_setattr*/
   9377     0,          /*tp_compare*/
   9378     0,          /*tp_repr*/
   9379     0,          /*tp_as_number*/
   9380     0,          /*tp_as_sequence*/
   9381     0,          /*tp_as_mapping*/
   9382     0,          /*tp_hash*/
   9383     0,                  /* tp_call */
   9384     0,                  /* tp_str */
   9385     0,                  /* tp_getattro */
   9386     0,          /* tp_setattro */
   9387     0,                  /* tp_as_buffer */
   9388 #if (PY_VERSION_HEX < 0x03000000)
   9389     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9390 #else
   9391     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9392 #endif
   9393     0,          /* tp_doc */
   9394     0,          /* tp_traverse */
   9395     0,                  /* tp_clear */
   9396     0,                  /* tp_richcompare */
   9397     offsetof(DBTxnObject, in_weakreflist),   /* tp_weaklistoffset */
   9398     0,          /*tp_iter*/
   9399     0,          /*tp_iternext*/
   9400     DBTxn_methods, /*tp_methods*/
   9401     0,          /*tp_members*/
   9402 };
   9403 
   9404 
   9405 statichere PyTypeObject DBLock_Type = {
   9406 #if (PY_VERSION_HEX < 0x03000000)
   9407     PyObject_HEAD_INIT(NULL)
   9408     0,                  /*ob_size*/
   9409 #else
   9410     PyVarObject_HEAD_INIT(NULL, 0)
   9411 #endif
   9412     "DBLock",   /*tp_name*/
   9413     sizeof(DBLockObject),  /*tp_basicsize*/
   9414     0,          /*tp_itemsize*/
   9415     /* methods */
   9416     (destructor)DBLock_dealloc, /*tp_dealloc*/
   9417     0,          /*tp_print*/
   9418     0,          /*tp_getattr*/
   9419     0,          /*tp_setattr*/
   9420     0,          /*tp_compare*/
   9421     0,          /*tp_repr*/
   9422     0,          /*tp_as_number*/
   9423     0,          /*tp_as_sequence*/
   9424     0,          /*tp_as_mapping*/
   9425     0,          /*tp_hash*/
   9426     0,                  /* tp_call */
   9427     0,                  /* tp_str */
   9428     0,                  /* tp_getattro */
   9429     0,          /* tp_setattro */
   9430     0,                  /* tp_as_buffer */
   9431 #if (PY_VERSION_HEX < 0x03000000)
   9432     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9433 #else
   9434     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9435 #endif
   9436     0,          /* tp_doc */
   9437     0,              /* tp_traverse */
   9438     0,                  /* tp_clear */
   9439     0,                  /* tp_richcompare */
   9440     offsetof(DBLockObject, in_weakreflist),   /* tp_weaklistoffset */
   9441 };
   9442 
   9443 statichere PyTypeObject DBSequence_Type = {
   9444 #if (PY_VERSION_HEX < 0x03000000)
   9445     PyObject_HEAD_INIT(NULL)
   9446     0,                  /*ob_size*/
   9447 #else
   9448     PyVarObject_HEAD_INIT(NULL, 0)
   9449 #endif
   9450     "DBSequence",                   /*tp_name*/
   9451     sizeof(DBSequenceObject),       /*tp_basicsize*/
   9452     0,          /*tp_itemsize*/
   9453     /* methods */
   9454     (destructor)DBSequence_dealloc, /*tp_dealloc*/
   9455     0,          /*tp_print*/
   9456     0,          /*tp_getattr*/
   9457     0,          /*tp_setattr*/
   9458     0,          /*tp_compare*/
   9459     0,          /*tp_repr*/
   9460     0,          /*tp_as_number*/
   9461     0,          /*tp_as_sequence*/
   9462     0,          /*tp_as_mapping*/
   9463     0,          /*tp_hash*/
   9464     0,                  /* tp_call */
   9465     0,                  /* tp_str */
   9466     0,                  /* tp_getattro */
   9467     0,          /* tp_setattro */
   9468     0,                  /* tp_as_buffer */
   9469 #if (PY_VERSION_HEX < 0x03000000)
   9470     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
   9471 #else
   9472     Py_TPFLAGS_DEFAULT,      /* tp_flags */
   9473 #endif
   9474     0,          /* tp_doc */
   9475     0,              /* tp_traverse */
   9476     0,                  /* tp_clear */
   9477     0,                  /* tp_richcompare */
   9478     offsetof(DBSequenceObject, in_weakreflist),   /* tp_weaklistoffset */
   9479     0,          /*tp_iter*/
   9480     0,          /*tp_iternext*/
   9481     DBSequence_methods, /*tp_methods*/
   9482     0,          /*tp_members*/
   9483 };
   9484 
   9485 /* --------------------------------------------------------------------- */
   9486 /* Module-level functions */
   9487 
   9488 static PyObject*
   9489 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
   9490 {
   9491     PyObject* dbenvobj = NULL;
   9492     int flags = 0;
   9493     static char* kwnames[] = { "dbEnv", "flags", NULL};
   9494 
   9495     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
   9496                                      &dbenvobj, &flags))
   9497         return NULL;
   9498     if (dbenvobj == Py_None)
   9499         dbenvobj = NULL;
   9500     else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
   9501         makeTypeError("DBEnv", dbenvobj);
   9502         return NULL;
   9503     }
   9504 
   9505     return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
   9506 }
   9507 
   9508 
   9509 static PyObject*
   9510 DBEnv_construct(PyObject* self, PyObject* args)
   9511 {
   9512     int flags = 0;
   9513     if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
   9514     return (PyObject* )newDBEnvObject(flags);
   9515 }
   9516 
   9517 static PyObject*
   9518 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
   9519 {
   9520     PyObject* dbobj;
   9521     int flags = 0;
   9522     static char* kwnames[] = { "db", "flags", NULL};
   9523 
   9524     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
   9525         return NULL;
   9526     if (!DBObject_Check(dbobj)) {
   9527         makeTypeError("DB", dbobj);
   9528         return NULL;
   9529     }
   9530     return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
   9531 }
   9532 
   9533 static char bsddb_version_doc[] =
   9534 "Returns a tuple of major, minor, and patch release numbers of the\n\
   9535 underlying DB library.";
   9536 
   9537 static PyObject*
   9538 bsddb_version(PyObject* self)
   9539 {
   9540     int major, minor, patch;
   9541 
   9542     /* This should be instantaneous, no need to release the GIL */
   9543     db_version(&major, &minor, &patch);
   9544     return Py_BuildValue("(iii)", major, minor, patch);
   9545 }
   9546 
   9547 #if (DBVER >= 50)
   9548 static PyObject*
   9549 bsddb_version_full(PyObject* self)
   9550 {
   9551     char *version_string;
   9552     int family, release, major, minor, patch;
   9553 
   9554     /* This should be instantaneous, no need to release the GIL */
   9555     version_string = db_full_version(&family, &release, &major, &minor, &patch);
   9556     return Py_BuildValue("(siiiii)",
   9557             version_string, family, release, major, minor, patch);
   9558 }
   9559 #endif
   9560 
   9561 
   9562 /* List of functions defined in the module */
   9563 static PyMethodDef bsddb_methods[] = {
   9564     {"DB",          (PyCFunction)DB_construct,          METH_VARARGS | METH_KEYWORDS },
   9565     {"DBEnv",       (PyCFunction)DBEnv_construct,       METH_VARARGS},
   9566     {"DBSequence",  (PyCFunction)DBSequence_construct,  METH_VARARGS | METH_KEYWORDS },
   9567     {"version",     (PyCFunction)bsddb_version,         METH_NOARGS, bsddb_version_doc},
   9568 #if (DBVER >= 50)
   9569     {"full_version", (PyCFunction)bsddb_version_full, METH_NOARGS},
   9570 #endif
   9571     {NULL,      NULL}       /* sentinel */
   9572 };
   9573 
   9574 
   9575 /* API structure */
   9576 static BSDDB_api bsddb_api;
   9577 
   9578 
   9579 /* --------------------------------------------------------------------- */
   9580 /* Module initialization */
   9581 
   9582 
   9583 /* Convenience routine to export an integer value.
   9584  * Errors are silently ignored, for better or for worse...
   9585  */
   9586 #define ADD_INT(dict, NAME)         _addIntToDict(dict, #NAME, NAME)
   9587 
   9588 /*
   9589 ** We can rename the module at import time, so the string allocated
   9590 ** must be big enough, and any use of the name must use this particular
   9591 ** string.
   9592 */
   9593 #define MODULE_NAME_MAX_LEN     11
   9594 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
   9595 
   9596 #if (PY_VERSION_HEX >= 0x03000000)
   9597 static struct PyModuleDef bsddbmodule = {
   9598     PyModuleDef_HEAD_INIT,
   9599     _bsddbModuleName,   /* Name of module */
   9600     NULL,               /* module documentation, may be NULL */
   9601     -1,                 /* size of per-interpreter state of the module,
   9602                             or -1 if the module keeps state in global variables. */
   9603     bsddb_methods,
   9604     NULL,   /* Reload */
   9605     NULL,   /* Traverse */
   9606     NULL,   /* Clear */
   9607     NULL    /* Free */
   9608 };
   9609 #endif
   9610 
   9611 
   9612 #if (PY_VERSION_HEX < 0x03000000)
   9613 DL_EXPORT(void) init_bsddb(void)
   9614 #else
   9615 PyMODINIT_FUNC  PyInit__bsddb(void)    /* Note the two underscores */
   9616 #endif
   9617 {
   9618     PyObject* m;
   9619     PyObject* d;
   9620     PyObject* py_api;
   9621     PyObject* pybsddb_version_s;
   9622     PyObject* db_version_s;
   9623     PyObject* cvsid_s;
   9624 
   9625 #if (PY_VERSION_HEX < 0x03000000)
   9626     pybsddb_version_s = PyString_FromString(PY_BSDDB_VERSION);
   9627     db_version_s = PyString_FromString(DB_VERSION_STRING);
   9628     cvsid_s = PyString_FromString(rcs_id);
   9629 #else
   9630     /* This data should be ascii, so UTF-8 conversion is fine */
   9631     pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
   9632     db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
   9633     cvsid_s = PyUnicode_FromString(rcs_id);
   9634 #endif
   9635 
   9636     /* Initialize object types */
   9637     if ((PyType_Ready(&DB_Type) < 0)
   9638         || (PyType_Ready(&DBCursor_Type) < 0)
   9639         || (PyType_Ready(&DBLogCursor_Type) < 0)
   9640         || (PyType_Ready(&DBEnv_Type) < 0)
   9641         || (PyType_Ready(&DBTxn_Type) < 0)
   9642         || (PyType_Ready(&DBLock_Type) < 0)
   9643         || (PyType_Ready(&DBSequence_Type) < 0)
   9644 #if (DBVER >= 52)
   9645         || (PyType_Ready(&DBSite_Type) < 0)
   9646 #endif
   9647         ) {
   9648 #if (PY_VERSION_HEX < 0x03000000)
   9649         return;
   9650 #else
   9651         return NULL;
   9652 #endif
   9653     }
   9654 
   9655     /* Create the module and add the functions */
   9656 #if (PY_VERSION_HEX < 0x03000000)
   9657     m = Py_InitModule(_bsddbModuleName, bsddb_methods);
   9658 #else
   9659     m=PyModule_Create(&bsddbmodule);
   9660 #endif
   9661     if (m == NULL) {
   9662 #if (PY_VERSION_HEX < 0x03000000)
   9663         return;
   9664 #else
   9665         return NULL;
   9666 #endif
   9667     }
   9668 
   9669     /* Add some symbolic constants to the module */
   9670     d = PyModule_GetDict(m);
   9671     PyDict_SetItemString(d, "__version__", pybsddb_version_s);
   9672     PyDict_SetItemString(d, "cvsid", cvsid_s);
   9673     PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
   9674     Py_DECREF(pybsddb_version_s);
   9675     pybsddb_version_s = NULL;
   9676     Py_DECREF(cvsid_s);
   9677     cvsid_s = NULL;
   9678     Py_DECREF(db_version_s);
   9679     db_version_s = NULL;
   9680 
   9681     ADD_INT(d, DB_VERSION_MAJOR);
   9682     ADD_INT(d, DB_VERSION_MINOR);
   9683     ADD_INT(d, DB_VERSION_PATCH);
   9684 
   9685     ADD_INT(d, DB_MAX_PAGES);
   9686     ADD_INT(d, DB_MAX_RECORDS);
   9687 
   9688 #if (DBVER < 48)
   9689     ADD_INT(d, DB_RPCCLIENT);
   9690 #endif
   9691 
   9692 #if (DBVER < 48)
   9693     ADD_INT(d, DB_XA_CREATE);
   9694 #endif
   9695 
   9696     ADD_INT(d, DB_CREATE);
   9697     ADD_INT(d, DB_NOMMAP);
   9698     ADD_INT(d, DB_THREAD);
   9699 #if (DBVER >= 45)
   9700     ADD_INT(d, DB_MULTIVERSION);
   9701 #endif
   9702 
   9703     ADD_INT(d, DB_FORCE);
   9704     ADD_INT(d, DB_INIT_CDB);
   9705     ADD_INT(d, DB_INIT_LOCK);
   9706     ADD_INT(d, DB_INIT_LOG);
   9707     ADD_INT(d, DB_INIT_MPOOL);
   9708     ADD_INT(d, DB_INIT_TXN);
   9709     ADD_INT(d, DB_JOINENV);
   9710 
   9711 #if (DBVER >= 48)
   9712     ADD_INT(d, DB_GID_SIZE);
   9713 #else
   9714     ADD_INT(d, DB_XIDDATASIZE);
   9715     /* Allow new code to work in old BDB releases */
   9716     _addIntToDict(d, "DB_GID_SIZE", DB_XIDDATASIZE);
   9717 #endif
   9718 
   9719     ADD_INT(d, DB_RECOVER);
   9720     ADD_INT(d, DB_RECOVER_FATAL);
   9721     ADD_INT(d, DB_TXN_NOSYNC);
   9722     ADD_INT(d, DB_USE_ENVIRON);
   9723     ADD_INT(d, DB_USE_ENVIRON_ROOT);
   9724 
   9725     ADD_INT(d, DB_LOCKDOWN);
   9726     ADD_INT(d, DB_PRIVATE);
   9727     ADD_INT(d, DB_SYSTEM_MEM);
   9728 
   9729     ADD_INT(d, DB_TXN_SYNC);
   9730     ADD_INT(d, DB_TXN_NOWAIT);
   9731 
   9732 #if (DBVER >= 51)
   9733     ADD_INT(d, DB_TXN_BULK);
   9734 #endif
   9735 
   9736 #if (DBVER >= 48)
   9737     ADD_INT(d, DB_CURSOR_BULK);
   9738 #endif
   9739 
   9740 #if (DBVER >= 46)
   9741     ADD_INT(d, DB_TXN_WAIT);
   9742 #endif
   9743 
   9744     ADD_INT(d, DB_EXCL);
   9745     ADD_INT(d, DB_FCNTL_LOCKING);
   9746     ADD_INT(d, DB_ODDFILESIZE);
   9747     ADD_INT(d, DB_RDWRMASTER);
   9748     ADD_INT(d, DB_RDONLY);
   9749     ADD_INT(d, DB_TRUNCATE);
   9750     ADD_INT(d, DB_EXTENT);
   9751     ADD_INT(d, DB_CDB_ALLDB);
   9752     ADD_INT(d, DB_VERIFY);
   9753     ADD_INT(d, DB_UPGRADE);
   9754 
   9755     ADD_INT(d, DB_PRINTABLE);
   9756     ADD_INT(d, DB_AGGRESSIVE);
   9757     ADD_INT(d, DB_NOORDERCHK);
   9758     ADD_INT(d, DB_ORDERCHKONLY);
   9759     ADD_INT(d, DB_PR_PAGE);
   9760 
   9761     ADD_INT(d, DB_PR_RECOVERYTEST);
   9762     ADD_INT(d, DB_SALVAGE);
   9763 
   9764     ADD_INT(d, DB_LOCK_NORUN);
   9765     ADD_INT(d, DB_LOCK_DEFAULT);
   9766     ADD_INT(d, DB_LOCK_OLDEST);
   9767     ADD_INT(d, DB_LOCK_RANDOM);
   9768     ADD_INT(d, DB_LOCK_YOUNGEST);
   9769     ADD_INT(d, DB_LOCK_MAXLOCKS);
   9770     ADD_INT(d, DB_LOCK_MINLOCKS);
   9771     ADD_INT(d, DB_LOCK_MINWRITE);
   9772 
   9773     ADD_INT(d, DB_LOCK_EXPIRE);
   9774     ADD_INT(d, DB_LOCK_MAXWRITE);
   9775 
   9776     _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
   9777 
   9778     ADD_INT(d, DB_LOCK_DUMP);
   9779     ADD_INT(d, DB_LOCK_GET);
   9780     ADD_INT(d, DB_LOCK_INHERIT);
   9781     ADD_INT(d, DB_LOCK_PUT);
   9782     ADD_INT(d, DB_LOCK_PUT_ALL);
   9783     ADD_INT(d, DB_LOCK_PUT_OBJ);
   9784 
   9785     ADD_INT(d, DB_LOCK_NG);
   9786     ADD_INT(d, DB_LOCK_READ);
   9787     ADD_INT(d, DB_LOCK_WRITE);
   9788     ADD_INT(d, DB_LOCK_NOWAIT);
   9789     ADD_INT(d, DB_LOCK_WAIT);
   9790     ADD_INT(d, DB_LOCK_IWRITE);
   9791     ADD_INT(d, DB_LOCK_IREAD);
   9792     ADD_INT(d, DB_LOCK_IWR);
   9793 #if (DBVER < 44)
   9794     ADD_INT(d, DB_LOCK_DIRTY);
   9795 #else
   9796     ADD_INT(d, DB_LOCK_READ_UNCOMMITTED);  /* renamed in 4.4 */
   9797 #endif
   9798     ADD_INT(d, DB_LOCK_WWRITE);
   9799 
   9800     ADD_INT(d, DB_LOCK_RECORD);
   9801     ADD_INT(d, DB_LOCK_UPGRADE);
   9802     ADD_INT(d, DB_LOCK_SWITCH);
   9803     ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
   9804 
   9805     ADD_INT(d, DB_LOCK_NOWAIT);
   9806     ADD_INT(d, DB_LOCK_RECORD);
   9807     ADD_INT(d, DB_LOCK_UPGRADE);
   9808 
   9809     ADD_INT(d, DB_LSTAT_ABORTED);
   9810     ADD_INT(d, DB_LSTAT_FREE);
   9811     ADD_INT(d, DB_LSTAT_HELD);
   9812 
   9813     ADD_INT(d, DB_LSTAT_PENDING);
   9814     ADD_INT(d, DB_LSTAT_WAITING);
   9815 
   9816     ADD_INT(d, DB_ARCH_ABS);
   9817     ADD_INT(d, DB_ARCH_DATA);
   9818     ADD_INT(d, DB_ARCH_LOG);
   9819     ADD_INT(d, DB_ARCH_REMOVE);
   9820 
   9821     ADD_INT(d, DB_BTREE);
   9822     ADD_INT(d, DB_HASH);
   9823     ADD_INT(d, DB_RECNO);
   9824     ADD_INT(d, DB_QUEUE);
   9825     ADD_INT(d, DB_UNKNOWN);
   9826 
   9827     ADD_INT(d, DB_DUP);
   9828     ADD_INT(d, DB_DUPSORT);
   9829     ADD_INT(d, DB_RECNUM);
   9830     ADD_INT(d, DB_RENUMBER);
   9831     ADD_INT(d, DB_REVSPLITOFF);
   9832     ADD_INT(d, DB_SNAPSHOT);
   9833 
   9834     ADD_INT(d, DB_INORDER);
   9835 
   9836     ADD_INT(d, DB_JOIN_NOSORT);
   9837 
   9838     ADD_INT(d, DB_AFTER);
   9839     ADD_INT(d, DB_APPEND);
   9840     ADD_INT(d, DB_BEFORE);
   9841 #if (DBVER < 45)
   9842     ADD_INT(d, DB_CACHED_COUNTS);
   9843 #endif
   9844 
   9845     ADD_INT(d, DB_CONSUME);
   9846     ADD_INT(d, DB_CONSUME_WAIT);
   9847     ADD_INT(d, DB_CURRENT);
   9848     ADD_INT(d, DB_FAST_STAT);
   9849     ADD_INT(d, DB_FIRST);
   9850     ADD_INT(d, DB_FLUSH);
   9851     ADD_INT(d, DB_GET_BOTH);
   9852     ADD_INT(d, DB_GET_BOTH_RANGE);
   9853     ADD_INT(d, DB_GET_RECNO);
   9854     ADD_INT(d, DB_JOIN_ITEM);
   9855     ADD_INT(d, DB_KEYFIRST);
   9856     ADD_INT(d, DB_KEYLAST);
   9857     ADD_INT(d, DB_LAST);
   9858     ADD_INT(d, DB_NEXT);
   9859     ADD_INT(d, DB_NEXT_DUP);
   9860     ADD_INT(d, DB_NEXT_NODUP);
   9861     ADD_INT(d, DB_NODUPDATA);
   9862     ADD_INT(d, DB_NOOVERWRITE);
   9863     ADD_INT(d, DB_NOSYNC);
   9864     ADD_INT(d, DB_POSITION);
   9865     ADD_INT(d, DB_PREV);
   9866     ADD_INT(d, DB_PREV_NODUP);
   9867 #if (DBVER >= 46)
   9868     ADD_INT(d, DB_PREV_DUP);
   9869 #endif
   9870 #if (DBVER < 45)
   9871     ADD_INT(d, DB_RECORDCOUNT);
   9872 #endif
   9873     ADD_INT(d, DB_SET);
   9874     ADD_INT(d, DB_SET_RANGE);
   9875     ADD_INT(d, DB_SET_RECNO);
   9876     ADD_INT(d, DB_WRITECURSOR);
   9877 
   9878     ADD_INT(d, DB_OPFLAGS_MASK);
   9879     ADD_INT(d, DB_RMW);
   9880     ADD_INT(d, DB_DIRTY_READ);
   9881     ADD_INT(d, DB_MULTIPLE);
   9882     ADD_INT(d, DB_MULTIPLE_KEY);
   9883 
   9884 #if (DBVER >= 44)
   9885     ADD_INT(d, DB_IMMUTABLE_KEY);
   9886     ADD_INT(d, DB_READ_UNCOMMITTED);    /* replaces DB_DIRTY_READ in 4.4 */
   9887     ADD_INT(d, DB_READ_COMMITTED);
   9888 #endif
   9889 
   9890 #if (DBVER >= 44)
   9891     ADD_INT(d, DB_FREELIST_ONLY);
   9892     ADD_INT(d, DB_FREE_SPACE);
   9893 #endif
   9894 
   9895     ADD_INT(d, DB_DONOTINDEX);
   9896 
   9897     ADD_INT(d, DB_KEYEMPTY);
   9898     ADD_INT(d, DB_KEYEXIST);
   9899     ADD_INT(d, DB_LOCK_DEADLOCK);
   9900     ADD_INT(d, DB_LOCK_NOTGRANTED);
   9901     ADD_INT(d, DB_NOSERVER);
   9902 #if (DBVER < 52)
   9903     ADD_INT(d, DB_NOSERVER_HOME);
   9904     ADD_INT(d, DB_NOSERVER_ID);
   9905 #endif
   9906     ADD_INT(d, DB_NOTFOUND);
   9907     ADD_INT(d, DB_OLD_VERSION);
   9908     ADD_INT(d, DB_RUNRECOVERY);
   9909     ADD_INT(d, DB_VERIFY_BAD);
   9910     ADD_INT(d, DB_PAGE_NOTFOUND);
   9911     ADD_INT(d, DB_SECONDARY_BAD);
   9912     ADD_INT(d, DB_STAT_CLEAR);
   9913     ADD_INT(d, DB_REGION_INIT);
   9914     ADD_INT(d, DB_NOLOCKING);
   9915     ADD_INT(d, DB_YIELDCPU);
   9916     ADD_INT(d, DB_PANIC_ENVIRONMENT);
   9917     ADD_INT(d, DB_NOPANIC);
   9918     ADD_INT(d, DB_OVERWRITE);
   9919 
   9920     ADD_INT(d, DB_STAT_SUBSYSTEM);
   9921     ADD_INT(d, DB_STAT_MEMP_HASH);
   9922     ADD_INT(d, DB_STAT_LOCK_CONF);
   9923     ADD_INT(d, DB_STAT_LOCK_LOCKERS);
   9924     ADD_INT(d, DB_STAT_LOCK_OBJECTS);
   9925     ADD_INT(d, DB_STAT_LOCK_PARAMS);
   9926 
   9927 #if (DBVER >= 48)
   9928     ADD_INT(d, DB_OVERWRITE_DUP);
   9929 #endif
   9930 
   9931 #if (DBVER >= 47)
   9932     ADD_INT(d, DB_FOREIGN_ABORT);
   9933     ADD_INT(d, DB_FOREIGN_CASCADE);
   9934     ADD_INT(d, DB_FOREIGN_NULLIFY);
   9935 #endif
   9936 
   9937 #if (DBVER >= 44)
   9938     ADD_INT(d, DB_REGISTER);
   9939 #endif
   9940 
   9941     ADD_INT(d, DB_EID_INVALID);
   9942     ADD_INT(d, DB_EID_BROADCAST);
   9943 
   9944     ADD_INT(d, DB_TIME_NOTGRANTED);
   9945     ADD_INT(d, DB_TXN_NOT_DURABLE);
   9946     ADD_INT(d, DB_TXN_WRITE_NOSYNC);
   9947     ADD_INT(d, DB_DIRECT_DB);
   9948     ADD_INT(d, DB_INIT_REP);
   9949     ADD_INT(d, DB_ENCRYPT);
   9950     ADD_INT(d, DB_CHKSUM);
   9951 
   9952 #if (DBVER < 47)
   9953     ADD_INT(d, DB_LOG_AUTOREMOVE);
   9954     ADD_INT(d, DB_DIRECT_LOG);
   9955 #endif
   9956 
   9957 #if (DBVER >= 47)
   9958     ADD_INT(d, DB_LOG_DIRECT);
   9959     ADD_INT(d, DB_LOG_DSYNC);
   9960     ADD_INT(d, DB_LOG_IN_MEMORY);
   9961     ADD_INT(d, DB_LOG_AUTO_REMOVE);
   9962     ADD_INT(d, DB_LOG_ZERO);
   9963 #endif
   9964 
   9965 #if (DBVER >= 44)
   9966     ADD_INT(d, DB_DSYNC_DB);
   9967 #endif
   9968 
   9969 #if (DBVER >= 45)
   9970     ADD_INT(d, DB_TXN_SNAPSHOT);
   9971 #endif
   9972 
   9973     ADD_INT(d, DB_VERB_DEADLOCK);
   9974 #if (DBVER >= 46)
   9975     ADD_INT(d, DB_VERB_FILEOPS);
   9976     ADD_INT(d, DB_VERB_FILEOPS_ALL);
   9977 #endif
   9978     ADD_INT(d, DB_VERB_RECOVERY);
   9979 #if (DBVER >= 44)
   9980     ADD_INT(d, DB_VERB_REGISTER);
   9981 #endif
   9982     ADD_INT(d, DB_VERB_REPLICATION);
   9983     ADD_INT(d, DB_VERB_WAITSFOR);
   9984 
   9985 #if (DBVER >= 50)
   9986     ADD_INT(d, DB_VERB_REP_SYSTEM);
   9987 #endif
   9988 
   9989 #if (DBVER >= 47)
   9990     ADD_INT(d, DB_VERB_REP_ELECT);
   9991     ADD_INT(d, DB_VERB_REP_LEASE);
   9992     ADD_INT(d, DB_VERB_REP_MISC);
   9993     ADD_INT(d, DB_VERB_REP_MSGS);
   9994     ADD_INT(d, DB_VERB_REP_SYNC);
   9995     ADD_INT(d, DB_VERB_REPMGR_CONNFAIL);
   9996     ADD_INT(d, DB_VERB_REPMGR_MISC);
   9997 #endif
   9998 
   9999 #if (DBVER >= 45)
   10000     ADD_INT(d, DB_EVENT_PANIC);
   10001     ADD_INT(d, DB_EVENT_REP_CLIENT);
   10002 #if (DBVER >= 46)
   10003     ADD_INT(d, DB_EVENT_REP_ELECTED);
   10004 #endif
   10005     ADD_INT(d, DB_EVENT_REP_MASTER);
   10006     ADD_INT(d, DB_EVENT_REP_NEWMASTER);
   10007 #if (DBVER >= 46)
   10008     ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
   10009 #endif
   10010     ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
   10011     ADD_INT(d, DB_EVENT_WRITE_FAILED);
   10012 #endif
   10013 
   10014 #if (DBVER >= 50)
   10015     ADD_INT(d, DB_REPMGR_CONF_ELECTIONS);
   10016     ADD_INT(d, DB_EVENT_REP_MASTER_FAILURE);
   10017     ADD_INT(d, DB_EVENT_REP_DUPMASTER);
   10018     ADD_INT(d, DB_EVENT_REP_ELECTION_FAILED);
   10019 #endif
   10020 #if (DBVER >= 48)
   10021     ADD_INT(d, DB_EVENT_REG_ALIVE);
   10022     ADD_INT(d, DB_EVENT_REG_PANIC);
   10023 #endif
   10024 
   10025 #if (DBVER >=52)
   10026     ADD_INT(d, DB_EVENT_REP_SITE_ADDED);
   10027     ADD_INT(d, DB_EVENT_REP_SITE_REMOVED);
   10028     ADD_INT(d, DB_EVENT_REP_LOCAL_SITE_REMOVED);
   10029     ADD_INT(d, DB_EVENT_REP_CONNECT_BROKEN);
   10030     ADD_INT(d, DB_EVENT_REP_CONNECT_ESTD);
   10031     ADD_INT(d, DB_EVENT_REP_CONNECT_TRY_FAILED);
   10032     ADD_INT(d, DB_EVENT_REP_INIT_DONE);
   10033 
   10034     ADD_INT(d, DB_MEM_LOCK);
   10035     ADD_INT(d, DB_MEM_LOCKOBJECT);
   10036     ADD_INT(d, DB_MEM_LOCKER);
   10037     ADD_INT(d, DB_MEM_LOGID);
   10038     ADD_INT(d, DB_MEM_TRANSACTION);
   10039     ADD_INT(d, DB_MEM_THREAD);
   10040 
   10041     ADD_INT(d, DB_BOOTSTRAP_HELPER);
   10042     ADD_INT(d, DB_GROUP_CREATOR);
   10043     ADD_INT(d, DB_LEGACY);
   10044     ADD_INT(d, DB_LOCAL_SITE);
   10045     ADD_INT(d, DB_REPMGR_PEER);
   10046 #endif
   10047 
   10048     ADD_INT(d, DB_REP_DUPMASTER);
   10049     ADD_INT(d, DB_REP_HOLDELECTION);
   10050 #if (DBVER >= 44)
   10051     ADD_INT(d, DB_REP_IGNORE);
   10052     ADD_INT(d, DB_REP_JOIN_FAILURE);
   10053 #endif
   10054     ADD_INT(d, DB_REP_ISPERM);
   10055     ADD_INT(d, DB_REP_NOTPERM);
   10056     ADD_INT(d, DB_REP_NEWSITE);
   10057 
   10058     ADD_INT(d, DB_REP_MASTER);
   10059     ADD_INT(d, DB_REP_CLIENT);
   10060 
   10061     ADD_INT(d, DB_REP_PERMANENT);
   10062 
   10063 #if (DBVER >= 44)
   10064 #if (DBVER >= 50)
   10065     ADD_INT(d, DB_REP_CONF_AUTOINIT);
   10066 #else
   10067     ADD_INT(d, DB_REP_CONF_NOAUTOINIT);
   10068 #endif /* 5.0 */
   10069 #endif /* 4.4 */
   10070 #if (DBVER >= 44)
   10071     ADD_INT(d, DB_REP_CONF_DELAYCLIENT);
   10072     ADD_INT(d, DB_REP_CONF_BULK);
   10073     ADD_INT(d, DB_REP_CONF_NOWAIT);
   10074     ADD_INT(d, DB_REP_ANYWHERE);
   10075     ADD_INT(d, DB_REP_REREQUEST);
   10076 #endif
   10077 
   10078     ADD_INT(d, DB_REP_NOBUFFER);
   10079 
   10080 #if (DBVER >= 46)
   10081     ADD_INT(d, DB_REP_LEASE_EXPIRED);
   10082     ADD_INT(d, DB_IGNORE_LEASE);
   10083 #endif
   10084 
   10085 #if (DBVER >= 47)
   10086     ADD_INT(d, DB_REP_CONF_LEASE);
   10087     ADD_INT(d, DB_REPMGR_CONF_2SITE_STRICT);
   10088 #endif
   10089 
   10090 #if (DBVER >= 45)
   10091     ADD_INT(d, DB_REP_ELECTION);
   10092 
   10093     ADD_INT(d, DB_REP_ACK_TIMEOUT);
   10094     ADD_INT(d, DB_REP_CONNECTION_RETRY);
   10095     ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
   10096     ADD_INT(d, DB_REP_ELECTION_RETRY);
   10097 #endif
   10098 #if (DBVER >= 46)
   10099     ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
   10100     ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
   10101     ADD_INT(d, DB_REP_LEASE_TIMEOUT);
   10102 #endif
   10103 #if (DBVER >= 47)
   10104     ADD_INT(d, DB_REP_HEARTBEAT_MONITOR);
   10105     ADD_INT(d, DB_REP_HEARTBEAT_SEND);
   10106 #endif
   10107 
   10108 #if (DBVER >= 45)
   10109     ADD_INT(d, DB_REPMGR_PEER);
   10110     ADD_INT(d, DB_REPMGR_ACKS_ALL);
   10111     ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
   10112     ADD_INT(d, DB_REPMGR_ACKS_NONE);
   10113     ADD_INT(d, DB_REPMGR_ACKS_ONE);
   10114     ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
   10115     ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
   10116     ADD_INT(d, DB_REPMGR_CONNECTED);
   10117     ADD_INT(d, DB_REPMGR_DISCONNECTED);
   10118     ADD_INT(d, DB_STAT_ALL);
   10119 #endif
   10120 
   10121 #if (DBVER >= 51)
   10122     ADD_INT(d, DB_REPMGR_ACKS_ALL_AVAILABLE);
   10123 #endif
   10124 
   10125 #if (DBVER >= 48)
   10126     ADD_INT(d, DB_REP_CONF_INMEM);
   10127 #endif
   10128 
   10129     ADD_INT(d, DB_TIMEOUT);
   10130 
   10131 #if (DBVER >= 50)
   10132     ADD_INT(d, DB_FORCESYNC);
   10133 #endif
   10134 
   10135 #if (DBVER >= 48)
   10136     ADD_INT(d, DB_FAILCHK);
   10137 #endif
   10138 
   10139 #if (DBVER >= 51)
   10140     ADD_INT(d, DB_HOTBACKUP_IN_PROGRESS);
   10141 #endif
   10142 
   10143     ADD_INT(d, DB_BUFFER_SMALL);
   10144     ADD_INT(d, DB_SEQ_DEC);
   10145     ADD_INT(d, DB_SEQ_INC);
   10146     ADD_INT(d, DB_SEQ_WRAP);
   10147 
   10148 #if (DBVER < 47)
   10149     ADD_INT(d, DB_LOG_INMEMORY);
   10150     ADD_INT(d, DB_DSYNC_LOG);
   10151 #endif
   10152 
   10153     ADD_INT(d, DB_ENCRYPT_AES);
   10154     ADD_INT(d, DB_AUTO_COMMIT);
   10155     ADD_INT(d, DB_PRIORITY_VERY_LOW);
   10156     ADD_INT(d, DB_PRIORITY_LOW);
   10157     ADD_INT(d, DB_PRIORITY_DEFAULT);
   10158     ADD_INT(d, DB_PRIORITY_HIGH);
   10159     ADD_INT(d, DB_PRIORITY_VERY_HIGH);
   10160 
   10161 #if (DBVER >= 46)
   10162     ADD_INT(d, DB_PRIORITY_UNCHANGED);
   10163 #endif
   10164 
   10165     ADD_INT(d, EINVAL);
   10166     ADD_INT(d, EACCES);
   10167     ADD_INT(d, ENOSPC);
   10168     ADD_INT(d, ENOMEM);
   10169     ADD_INT(d, EAGAIN);
   10170     ADD_INT(d, EBUSY);
   10171     ADD_INT(d, EEXIST);
   10172     ADD_INT(d, ENOENT);
   10173     ADD_INT(d, EPERM);
   10174 
   10175     ADD_INT(d, DB_SET_LOCK_TIMEOUT);
   10176     ADD_INT(d, DB_SET_TXN_TIMEOUT);
   10177 
   10178 #if (DBVER >= 48)
   10179     ADD_INT(d, DB_SET_REG_TIMEOUT);
   10180 #endif
   10181 
   10182     /* The exception name must be correct for pickled exception *
   10183      * objects to unpickle properly.                            */
   10184 #ifdef PYBSDDB_STANDALONE  /* different value needed for standalone pybsddb */
   10185 #define PYBSDDB_EXCEPTION_BASE  "bsddb3.db."
   10186 #else
   10187 #define PYBSDDB_EXCEPTION_BASE  "bsddb.db."
   10188 #endif
   10189 
   10190     /* All the rest of the exceptions derive only from DBError */
   10191 #define MAKE_EX(name)   name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
   10192                         PyDict_SetItemString(d, #name, name)
   10193 
   10194     /* The base exception class is DBError */
   10195     DBError = NULL;     /* used in MAKE_EX so that it derives from nothing */
   10196     MAKE_EX(DBError);
   10197 
   10198 #if (PY_VERSION_HEX < 0x03000000)
   10199     /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
   10200      * from both DBError and KeyError, since the API only supports
   10201      * using one base class. */
   10202     PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
   10203     PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
   10204                  "class DBKeyEmptyError(DBError, KeyError): pass",
   10205                  Py_file_input, d, d);
   10206     DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
   10207     DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
   10208     PyDict_DelItemString(d, "KeyError");
   10209 #else
   10210     /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
   10211     ** derive from several classes. We use this new API only for Python 3.0,
   10212     ** though.
   10213     */
   10214     {
   10215         PyObject* bases;
   10216 
   10217         bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
   10218 
   10219 #define MAKE_EX2(name)   name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
   10220                          PyDict_SetItemString(d, #name, name)
   10221         MAKE_EX2(DBNotFoundError);
   10222         MAKE_EX2(DBKeyEmptyError);
   10223 
   10224 #undef MAKE_EX2
   10225 
   10226         Py_XDECREF(bases);
   10227     }
   10228 #endif
   10229 
   10230     MAKE_EX(DBCursorClosedError);
   10231     MAKE_EX(DBKeyExistError);
   10232     MAKE_EX(DBLockDeadlockError);
   10233     MAKE_EX(DBLockNotGrantedError);
   10234     MAKE_EX(DBOldVersionError);
   10235     MAKE_EX(DBRunRecoveryError);
   10236     MAKE_EX(DBVerifyBadError);
   10237     MAKE_EX(DBNoServerError);
   10238 #if (DBVER < 52)
   10239     MAKE_EX(DBNoServerHomeError);
   10240     MAKE_EX(DBNoServerIDError);
   10241 #endif
   10242     MAKE_EX(DBPageNotFoundError);
   10243     MAKE_EX(DBSecondaryBadError);
   10244 
   10245     MAKE_EX(DBInvalidArgError);
   10246     MAKE_EX(DBAccessError);
   10247     MAKE_EX(DBNoSpaceError);
   10248     MAKE_EX(DBNoMemoryError);
   10249     MAKE_EX(DBAgainError);
   10250     MAKE_EX(DBBusyError);
   10251     MAKE_EX(DBFileExistsError);
   10252     MAKE_EX(DBNoSuchFileError);
   10253     MAKE_EX(DBPermissionsError);
   10254 
   10255     MAKE_EX(DBRepHandleDeadError);
   10256 #if (DBVER >= 44)
   10257     MAKE_EX(DBRepLockoutError);
   10258 #endif
   10259 
   10260     MAKE_EX(DBRepUnavailError);
   10261 
   10262 #if (DBVER >= 46)
   10263     MAKE_EX(DBRepLeaseExpiredError);
   10264 #endif
   10265 
   10266 #if (DBVER >= 47)
   10267         MAKE_EX(DBForeignConflictError);
   10268 #endif
   10269 
   10270 #undef MAKE_EX
   10271 
   10272     /* Initialise the C API structure and add it to the module */
   10273     bsddb_api.api_version      = PYBSDDB_API_VERSION;
   10274     bsddb_api.db_type          = &DB_Type;
   10275     bsddb_api.dbcursor_type    = &DBCursor_Type;
   10276     bsddb_api.dblogcursor_type = &DBLogCursor_Type;
   10277     bsddb_api.dbenv_type       = &DBEnv_Type;
   10278     bsddb_api.dbtxn_type       = &DBTxn_Type;
   10279     bsddb_api.dblock_type      = &DBLock_Type;
   10280     bsddb_api.dbsequence_type  = &DBSequence_Type;
   10281     bsddb_api.makeDBError      = makeDBError;
   10282 
   10283     /*
   10284     ** Capsules exist from Python 2.7 and 3.1.
   10285     ** We don't support Python 3.0 anymore, so...
   10286     ** #if (PY_VERSION_HEX < ((PY_MAJOR_VERSION < 3) ? 0x02070000 : 0x03020000))
   10287     */
   10288 #if (PY_VERSION_HEX < 0x02070000)
   10289     py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
   10290 #else
   10291     {
   10292         /*
   10293         ** The data must outlive the call!!. So, the static definition.
   10294         ** The buffer must be big enough...
   10295         */
   10296         static char py_api_name[MODULE_NAME_MAX_LEN+10];
   10297 
   10298         strcpy(py_api_name, _bsddbModuleName);
   10299         strcat(py_api_name, ".api");
   10300 
   10301         py_api = PyCapsule_New((void*)&bsddb_api, py_api_name, NULL);
   10302     }
   10303 #endif
   10304 
   10305     /* Check error control */
   10306     /*
   10307     ** PyErr_NoMemory();
   10308     ** py_api = NULL;
   10309     */
   10310 
   10311     if (py_api) {
   10312         PyDict_SetItemString(d, "api", py_api);
   10313         Py_DECREF(py_api);
   10314     } else { /* Something bad happened */
   10315         PyErr_WriteUnraisable(m);
   10316         if(PyErr_Warn(PyExc_RuntimeWarning,
   10317                 "_bsddb/_pybsddb C API will be not available")) {
   10318             PyErr_WriteUnraisable(m);
   10319         }
   10320         PyErr_Clear();
   10321     }
   10322 
   10323     /* Check for errors */
   10324     if (PyErr_Occurred()) {
   10325         PyErr_Print();
   10326         Py_FatalError("can't initialize module _bsddb/_pybsddb");
   10327         Py_DECREF(m);
   10328         m = NULL;
   10329     }
   10330 #if (PY_VERSION_HEX < 0x03000000)
   10331     return;
   10332 #else
   10333     return m;
   10334 #endif
   10335 }
   10336 
   10337 /* allow this module to be named _pybsddb so that it can be installed
   10338  * and imported on top of python >= 2.3 that includes its own older
   10339  * copy of the library named _bsddb without importing the old version. */
   10340 #if (PY_VERSION_HEX < 0x03000000)
   10341 DL_EXPORT(void) init_pybsddb(void)
   10342 #else
   10343 PyMODINIT_FUNC PyInit__pybsddb(void)  /* Note the two underscores */
   10344 #endif
   10345 {
   10346     strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
   10347 #if (PY_VERSION_HEX < 0x03000000)
   10348     init_bsddb();
   10349 #else
   10350     return PyInit__bsddb();   /* Note the two underscores */
   10351 #endif
   10352 }
   10353