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