symbian-qemu-0.9.1-12/python-2.6.1/Modules/_bsddb.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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@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@krypto.org> was once again the maintainer.
       
    52  *
       
    53  * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
       
    54  * Jesus Cea licenses this code to PSF under a Contributor Agreement.
       
    55  *
       
    56  * Use the pybsddb-users@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 6 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  *
       
    76  */
       
    77 
       
    78 /* --------------------------------------------------------------------- */
       
    79 
       
    80 /*
       
    81  * Portions of this module, associated unit tests and build scripts are the
       
    82  * result of a contract with The Written Word (http://thewrittenword.com/)
       
    83  * Many thanks go out to them for causing me to raise the bar on quality and
       
    84  * functionality, resulting in a better bsddb3 package for all of us to use.
       
    85  *
       
    86  * --Robin
       
    87  */
       
    88 
       
    89 /* --------------------------------------------------------------------- */
       
    90 
       
    91 #include <stddef.h>   /* for offsetof() */
       
    92 #include <Python.h>
       
    93 
       
    94 #define COMPILING_BSDDB_C
       
    95 #include "bsddb.h"
       
    96 #undef COMPILING_BSDDB_C
       
    97 
       
    98 static char *rcs_id = "$Id: _bsddb.c 66568 2008-09-23 18:54:08Z jesus.cea $";
       
    99 
       
   100 /* --------------------------------------------------------------------- */
       
   101 /* Various macro definitions */
       
   102 
       
   103 #if (PY_VERSION_HEX < 0x02050000)
       
   104 typedef int Py_ssize_t;
       
   105 #endif
       
   106 
       
   107 #if (PY_VERSION_HEX < 0x02060000)  /* really: before python trunk r63675 */
       
   108 /* This code now uses PyBytes* API function names instead of PyString*.
       
   109  * These #defines map to their equivalent on earlier python versions.    */
       
   110 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
       
   111 #define PyBytes_FromString PyString_FromString
       
   112 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
       
   113 #define PyBytes_Check PyString_Check
       
   114 #define PyBytes_GET_SIZE PyString_GET_SIZE
       
   115 #define PyBytes_AS_STRING PyString_AS_STRING
       
   116 #endif
       
   117 
       
   118 #if (PY_VERSION_HEX >= 0x03000000)
       
   119 #define NUMBER_Check    PyLong_Check
       
   120 #define NUMBER_AsLong   PyLong_AsLong
       
   121 #define NUMBER_FromLong PyLong_FromLong
       
   122 #else
       
   123 #define NUMBER_Check    PyInt_Check
       
   124 #define NUMBER_AsLong   PyInt_AsLong
       
   125 #define NUMBER_FromLong PyInt_FromLong
       
   126 #endif
       
   127 
       
   128 #ifdef WITH_THREAD
       
   129 
       
   130 /* These are for when calling Python --> C */
       
   131 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
       
   132 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
       
   133 
       
   134 /* For 2.3, use the PyGILState_ calls */
       
   135 #if (PY_VERSION_HEX >= 0x02030000)
       
   136 #define MYDB_USE_GILSTATE
       
   137 #endif
       
   138 
       
   139 /* and these are for calling C --> Python */
       
   140 #if defined(MYDB_USE_GILSTATE)
       
   141 #define MYDB_BEGIN_BLOCK_THREADS \
       
   142 		PyGILState_STATE __savestate = PyGILState_Ensure();
       
   143 #define MYDB_END_BLOCK_THREADS \
       
   144 		PyGILState_Release(__savestate);
       
   145 #else /* MYDB_USE_GILSTATE */
       
   146 /* Pre GILState API - do it the long old way */
       
   147 static PyInterpreterState* _db_interpreterState = NULL;
       
   148 #define MYDB_BEGIN_BLOCK_THREADS {                              \
       
   149         PyThreadState* prevState;                               \
       
   150         PyThreadState* newState;                                \
       
   151         PyEval_AcquireLock();                                   \
       
   152         newState  = PyThreadState_New(_db_interpreterState);    \
       
   153         prevState = PyThreadState_Swap(newState);
       
   154 
       
   155 #define MYDB_END_BLOCK_THREADS                                  \
       
   156         newState = PyThreadState_Swap(prevState);               \
       
   157         PyThreadState_Clear(newState);                          \
       
   158         PyEval_ReleaseLock();                                   \
       
   159         PyThreadState_Delete(newState);                         \
       
   160         }
       
   161 #endif /* MYDB_USE_GILSTATE */
       
   162 
       
   163 #else
       
   164 /* Compiled without threads - avoid all this cruft */
       
   165 #define MYDB_BEGIN_ALLOW_THREADS
       
   166 #define MYDB_END_ALLOW_THREADS
       
   167 #define MYDB_BEGIN_BLOCK_THREADS
       
   168 #define MYDB_END_BLOCK_THREADS
       
   169 
       
   170 #endif
       
   171 
       
   172 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
       
   173 #define INCOMPLETE_IS_WARNING 1
       
   174 
       
   175 /* --------------------------------------------------------------------- */
       
   176 /* Exceptions */
       
   177 
       
   178 static PyObject* DBError;               /* Base class, all others derive from this */
       
   179 static PyObject* DBCursorClosedError;   /* raised when trying to use a closed cursor object */
       
   180 static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY: also derives from KeyError */
       
   181 static PyObject* DBKeyExistError;       /* DB_KEYEXIST */
       
   182 static PyObject* DBLockDeadlockError;   /* DB_LOCK_DEADLOCK */
       
   183 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
       
   184 static PyObject* DBNotFoundError;       /* DB_NOTFOUND: also derives from KeyError */
       
   185 static PyObject* DBOldVersionError;     /* DB_OLD_VERSION */
       
   186 static PyObject* DBRunRecoveryError;    /* DB_RUNRECOVERY */
       
   187 static PyObject* DBVerifyBadError;      /* DB_VERIFY_BAD */
       
   188 static PyObject* DBNoServerError;       /* DB_NOSERVER */
       
   189 static PyObject* DBNoServerHomeError;   /* DB_NOSERVER_HOME */
       
   190 static PyObject* DBNoServerIDError;     /* DB_NOSERVER_ID */
       
   191 static PyObject* DBPageNotFoundError;   /* DB_PAGE_NOTFOUND */
       
   192 static PyObject* DBSecondaryBadError;   /* DB_SECONDARY_BAD */
       
   193 
       
   194 #if !INCOMPLETE_IS_WARNING
       
   195 static PyObject* DBIncompleteError;     /* DB_INCOMPLETE */
       
   196 #endif
       
   197 
       
   198 static PyObject* DBInvalidArgError;     /* EINVAL */
       
   199 static PyObject* DBAccessError;         /* EACCES */
       
   200 static PyObject* DBNoSpaceError;        /* ENOSPC */
       
   201 static PyObject* DBNoMemoryError;       /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
       
   202 static PyObject* DBAgainError;          /* EAGAIN */
       
   203 static PyObject* DBBusyError;           /* EBUSY  */
       
   204 static PyObject* DBFileExistsError;     /* EEXIST */
       
   205 static PyObject* DBNoSuchFileError;     /* ENOENT */
       
   206 static PyObject* DBPermissionsError;    /* EPERM  */
       
   207 
       
   208 #if (DBVER >= 42)
       
   209 static PyObject* DBRepHandleDeadError;  /* DB_REP_HANDLE_DEAD */
       
   210 #endif
       
   211 
       
   212 static PyObject* DBRepUnavailError;     /* DB_REP_UNAVAIL */
       
   213 
       
   214 #if (DBVER < 43)
       
   215 #define	DB_BUFFER_SMALL		ENOMEM
       
   216 #endif
       
   217 
       
   218 
       
   219 /* --------------------------------------------------------------------- */
       
   220 /* Structure definitions */
       
   221 
       
   222 #if PYTHON_API_VERSION < 1010
       
   223 #error "Python 2.1 or later required"
       
   224 #endif
       
   225 
       
   226 
       
   227 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
       
   228 #define DEFAULT_GET_RETURNS_NONE                1
       
   229 #define DEFAULT_CURSOR_SET_RETURNS_NONE         1   /* 0 in pybsddb < 4.2, python < 2.4 */
       
   230 
       
   231 
       
   232 /* See comment in Python 2.6 "object.h" */
       
   233 #ifndef staticforward
       
   234 #define staticforward static
       
   235 #endif
       
   236 #ifndef statichere
       
   237 #define statichere static
       
   238 #endif
       
   239 
       
   240 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
       
   241               DBLock_Type;
       
   242 #if (DBVER >= 43)
       
   243 staticforward PyTypeObject DBSequence_Type;
       
   244 #endif
       
   245 
       
   246 #ifndef Py_TYPE
       
   247 /* for compatibility with Python 2.5 and earlier */
       
   248 #define Py_TYPE(ob)              (((PyObject*)(ob))->ob_type)
       
   249 #endif
       
   250 
       
   251 #define DBObject_Check(v)           (Py_TYPE(v) == &DB_Type)
       
   252 #define DBCursorObject_Check(v)     (Py_TYPE(v) == &DBCursor_Type)
       
   253 #define DBEnvObject_Check(v)        (Py_TYPE(v) == &DBEnv_Type)
       
   254 #define DBTxnObject_Check(v)        (Py_TYPE(v) == &DBTxn_Type)
       
   255 #define DBLockObject_Check(v)       (Py_TYPE(v) == &DBLock_Type)
       
   256 #if (DBVER >= 43)
       
   257 #define DBSequenceObject_Check(v)   (Py_TYPE(v) == &DBSequence_Type)
       
   258 #endif
       
   259 
       
   260 #if (DBVER < 46)
       
   261   #define _DBC_close(dbc)           dbc->c_close(dbc)
       
   262   #define _DBC_count(dbc,a,b)       dbc->c_count(dbc,a,b)
       
   263   #define _DBC_del(dbc,a)           dbc->c_del(dbc,a)
       
   264   #define _DBC_dup(dbc,a,b)         dbc->c_dup(dbc,a,b)
       
   265   #define _DBC_get(dbc,a,b,c)       dbc->c_get(dbc,a,b,c)
       
   266   #define _DBC_pget(dbc,a,b,c,d)    dbc->c_pget(dbc,a,b,c,d)
       
   267   #define _DBC_put(dbc,a,b,c)       dbc->c_put(dbc,a,b,c)
       
   268 #else
       
   269   #define _DBC_close(dbc)           dbc->close(dbc)
       
   270   #define _DBC_count(dbc,a,b)       dbc->count(dbc,a,b)
       
   271   #define _DBC_del(dbc,a)           dbc->del(dbc,a)
       
   272   #define _DBC_dup(dbc,a,b)         dbc->dup(dbc,a,b)
       
   273   #define _DBC_get(dbc,a,b,c)       dbc->get(dbc,a,b,c)
       
   274   #define _DBC_pget(dbc,a,b,c,d)    dbc->pget(dbc,a,b,c,d)
       
   275   #define _DBC_put(dbc,a,b,c)       dbc->put(dbc,a,b,c)
       
   276 #endif
       
   277 
       
   278 
       
   279 /* --------------------------------------------------------------------- */
       
   280 /* Utility macros and functions */
       
   281 
       
   282 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object)                   \
       
   283     {                                                                   \
       
   284         object->sibling_next=backlink;                                  \
       
   285         object->sibling_prev_p=&(backlink);                             \
       
   286         backlink=object;                                                \
       
   287         if (object->sibling_next) {                                     \
       
   288           object->sibling_next->sibling_prev_p=&(object->sibling_next); \
       
   289         }                                                               \
       
   290     }
       
   291 
       
   292 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object)                          \
       
   293     {                                                                    \
       
   294         if (object->sibling_next) {                                      \
       
   295             object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
       
   296         }                                                                \
       
   297         *(object->sibling_prev_p)=object->sibling_next;                  \
       
   298     }
       
   299 
       
   300 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object)               \
       
   301     {                                                                    \
       
   302         if (object->sibling_next) {                                      \
       
   303             object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
       
   304         }                                                                \
       
   305         if (object->sibling_prev_p) {                                    \
       
   306             *(object->sibling_prev_p)=object->sibling_next;              \
       
   307         }                                                                \
       
   308     }
       
   309 
       
   310 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object)  \
       
   311     {                                                      \
       
   312         object->sibling_next_txn=backlink;                 \
       
   313         object->sibling_prev_p_txn=&(backlink);            \
       
   314         backlink=object;                                   \
       
   315         if (object->sibling_next_txn) {                    \
       
   316             object->sibling_next_txn->sibling_prev_p_txn=  \
       
   317                 &(object->sibling_next_txn);               \
       
   318         }                                                  \
       
   319     }
       
   320 
       
   321 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object)             \
       
   322     {                                                           \
       
   323         if (object->sibling_next_txn) {                         \
       
   324             object->sibling_next_txn->sibling_prev_p_txn=       \
       
   325                 object->sibling_prev_p_txn;                     \
       
   326         }                                                       \
       
   327         *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
       
   328     }
       
   329 
       
   330 
       
   331 #define RETURN_IF_ERR()          \
       
   332     if (makeDBError(err)) {      \
       
   333         return NULL;             \
       
   334     }
       
   335 
       
   336 #define RETURN_NONE()  Py_INCREF(Py_None); return Py_None;
       
   337 
       
   338 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
       
   339     if ((nonNull) == NULL) {          \
       
   340         PyObject *errTuple = NULL;    \
       
   341         errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
       
   342         if (errTuple) { \
       
   343             PyErr_SetObject((pyErrObj), errTuple);  \
       
   344             Py_DECREF(errTuple);          \
       
   345         } \
       
   346         return NULL;                  \
       
   347     }
       
   348 
       
   349 #define CHECK_DB_NOT_CLOSED(dbobj) \
       
   350         _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
       
   351 
       
   352 #define CHECK_ENV_NOT_CLOSED(env) \
       
   353         _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
       
   354 
       
   355 #define CHECK_CURSOR_NOT_CLOSED(curs) \
       
   356         _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
       
   357 
       
   358 #if (DBVER >= 43)
       
   359 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
       
   360         _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
       
   361 #endif
       
   362 
       
   363 #define CHECK_DBFLAG(mydb, flag)    (((mydb)->flags & (flag)) || \
       
   364                                      (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
       
   365 
       
   366 #define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
       
   367 
       
   368 #define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
       
   369                                          dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
       
   370 
       
   371 
       
   372 static int makeDBError(int err);
       
   373 
       
   374 
       
   375 /* Return the access method type of the DBObject */
       
   376 static int _DB_get_type(DBObject* self)
       
   377 {
       
   378     DBTYPE type;
       
   379     int err;
       
   380 
       
   381     err = self->db->get_type(self->db, &type);
       
   382     if (makeDBError(err)) {
       
   383         return -1;
       
   384     }
       
   385     return type;
       
   386 }
       
   387 
       
   388 
       
   389 /* Create a DBT structure (containing key and data values) from Python
       
   390    strings.  Returns 1 on success, 0 on an error. */
       
   391 static int make_dbt(PyObject* obj, DBT* dbt)
       
   392 {
       
   393     CLEAR_DBT(*dbt);
       
   394     if (obj == Py_None) {
       
   395         /* no need to do anything, the structure has already been zeroed */
       
   396     }
       
   397     else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
       
   398         PyErr_SetString(PyExc_TypeError,
       
   399 #if (PY_VERSION_HEX < 0x03000000)
       
   400                         "Data values must be of type string or None.");
       
   401 #else
       
   402                         "Data values must be of type bytes or None.");
       
   403 #endif
       
   404         return 0;
       
   405     }
       
   406     return 1;
       
   407 }
       
   408 
       
   409 
       
   410 /* Recno and Queue DBs can have integer keys.  This function figures out
       
   411    what's been given, verifies that it's allowed, and then makes the DBT.
       
   412 
       
   413    Caller MUST call FREE_DBT(key) when done. */
       
   414 static int
       
   415 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
       
   416 {
       
   417     db_recno_t recno;
       
   418     int type;
       
   419 
       
   420     CLEAR_DBT(*key);
       
   421     if (keyobj == Py_None) {
       
   422         type = _DB_get_type(self);
       
   423         if (type == -1)
       
   424             return 0;
       
   425         if (type == DB_RECNO || type == DB_QUEUE) {
       
   426             PyErr_SetString(
       
   427                 PyExc_TypeError,
       
   428                 "None keys not allowed for Recno and Queue DB's");
       
   429             return 0;
       
   430         }
       
   431         /* no need to do anything, the structure has already been zeroed */
       
   432     }
       
   433 
       
   434     else if (PyBytes_Check(keyobj)) {
       
   435         /* verify access method type */
       
   436         type = _DB_get_type(self);
       
   437         if (type == -1)
       
   438             return 0;
       
   439         if (type == DB_RECNO || type == DB_QUEUE) {
       
   440             PyErr_SetString(
       
   441                 PyExc_TypeError,
       
   442 #if (PY_VERSION_HEX < 0x03000000)
       
   443                 "String keys not allowed for Recno and Queue DB's");
       
   444 #else
       
   445                 "Bytes keys not allowed for Recno and Queue DB's");
       
   446 #endif
       
   447             return 0;
       
   448         }
       
   449 
       
   450         /*
       
   451          * NOTE(gps): I don't like doing a data copy here, it seems
       
   452          * wasteful.  But without a clean way to tell FREE_DBT if it
       
   453          * should free key->data or not we have to.  Other places in
       
   454          * the code check for DB_THREAD and forceably set DBT_MALLOC
       
   455          * when we otherwise would leave flags 0 to indicate that.
       
   456          */
       
   457         key->data = malloc(PyBytes_GET_SIZE(keyobj));
       
   458         if (key->data == NULL) {
       
   459             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
       
   460             return 0;
       
   461         }
       
   462         memcpy(key->data, PyBytes_AS_STRING(keyobj),
       
   463                PyBytes_GET_SIZE(keyobj));
       
   464         key->flags = DB_DBT_REALLOC;
       
   465         key->size = PyBytes_GET_SIZE(keyobj);
       
   466     }
       
   467 
       
   468     else if (NUMBER_Check(keyobj)) {
       
   469         /* verify access method type */
       
   470         type = _DB_get_type(self);
       
   471         if (type == -1)
       
   472             return 0;
       
   473         if (type == DB_BTREE && pflags != NULL) {
       
   474             /* if BTREE then an Integer key is allowed with the
       
   475              * DB_SET_RECNO flag */
       
   476             *pflags |= DB_SET_RECNO;
       
   477         }
       
   478         else if (type != DB_RECNO && type != DB_QUEUE) {
       
   479             PyErr_SetString(
       
   480                 PyExc_TypeError,
       
   481                 "Integer keys only allowed for Recno and Queue DB's");
       
   482             return 0;
       
   483         }
       
   484 
       
   485         /* Make a key out of the requested recno, use allocated space so DB
       
   486          * will be able to realloc room for the real key if needed. */
       
   487         recno = NUMBER_AsLong(keyobj);
       
   488         key->data = malloc(sizeof(db_recno_t));
       
   489         if (key->data == NULL) {
       
   490             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
       
   491             return 0;
       
   492         }
       
   493         key->ulen = key->size = sizeof(db_recno_t);
       
   494         memcpy(key->data, &recno, sizeof(db_recno_t));
       
   495         key->flags = DB_DBT_REALLOC;
       
   496     }
       
   497     else {
       
   498         PyErr_Format(PyExc_TypeError,
       
   499 #if (PY_VERSION_HEX < 0x03000000)
       
   500                      "String or Integer object expected for key, %s found",
       
   501 #else
       
   502                      "Bytes or Integer object expected for key, %s found",
       
   503 #endif
       
   504                      Py_TYPE(keyobj)->tp_name);
       
   505         return 0;
       
   506     }
       
   507 
       
   508     return 1;
       
   509 }
       
   510 
       
   511 
       
   512 /* Add partial record access to an existing DBT data struct.
       
   513    If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
       
   514    and the data storage/retrieval will be done using dlen and doff. */
       
   515 static int add_partial_dbt(DBT* d, int dlen, int doff) {
       
   516     /* if neither were set we do nothing (-1 is the default value) */
       
   517     if ((dlen == -1) && (doff == -1)) {
       
   518         return 1;
       
   519     }
       
   520 
       
   521     if ((dlen < 0) || (doff < 0)) {
       
   522         PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
       
   523         return 0;
       
   524     }
       
   525 
       
   526     d->flags = d->flags | DB_DBT_PARTIAL;
       
   527     d->dlen = (unsigned int) dlen;
       
   528     d->doff = (unsigned int) doff;
       
   529     return 1;
       
   530 }
       
   531 
       
   532 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
       
   533 /* TODO: make this use the native libc strlcpy() when available (BSD)      */
       
   534 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
       
   535 {
       
   536     unsigned int srclen, copylen;
       
   537 
       
   538     srclen = strlen(src);
       
   539     if (n <= 0)
       
   540 	return srclen;
       
   541     copylen = (srclen > n-1) ? n-1 : srclen;
       
   542     /* populate dest[0] thru dest[copylen-1] */
       
   543     memcpy(dest, src, copylen);
       
   544     /* guarantee null termination */
       
   545     dest[copylen] = 0;
       
   546 
       
   547     return srclen;
       
   548 }
       
   549 
       
   550 /* Callback used to save away more information about errors from the DB
       
   551  * library. */
       
   552 static char _db_errmsg[1024];
       
   553 #if (DBVER <= 42)
       
   554 static void _db_errorCallback(const char* prefix, char* msg)
       
   555 #else
       
   556 static void _db_errorCallback(const DB_ENV *db_env,
       
   557 	const char* prefix, const char* msg)
       
   558 #endif
       
   559 {
       
   560     our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
       
   561 }
       
   562 
       
   563 
       
   564 /*
       
   565 ** We need these functions because some results
       
   566 ** are undefined if pointer is NULL. Some other
       
   567 ** give None instead of "".
       
   568 **
       
   569 ** This functions are static and will be
       
   570 ** -I hope- inlined.
       
   571 */
       
   572 static const char *DummyString = "This string is a simple placeholder";
       
   573 static PyObject *Build_PyString(const char *p,int s)
       
   574 {
       
   575   if (!p) {
       
   576     p=DummyString;
       
   577     assert(s==0);
       
   578   }
       
   579   return PyBytes_FromStringAndSize(p,s);
       
   580 }
       
   581 
       
   582 static PyObject *BuildValue_S(const void *p,int s)
       
   583 {
       
   584   if (!p) {
       
   585     p=DummyString;
       
   586     assert(s==0);
       
   587   }
       
   588   return PyBytes_FromStringAndSize(p, s);
       
   589 }
       
   590 
       
   591 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
       
   592 {
       
   593 PyObject *a, *b, *r;
       
   594 
       
   595   if (!p1) {
       
   596     p1=DummyString;
       
   597     assert(s1==0);
       
   598   }
       
   599   if (!p2) {
       
   600     p2=DummyString;
       
   601     assert(s2==0);
       
   602   }
       
   603 
       
   604   if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
       
   605       return NULL;
       
   606   }
       
   607   if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
       
   608       Py_DECREF(a);
       
   609       return NULL;
       
   610   }
       
   611 
       
   612 #if (PY_VERSION_HEX >= 0x02040000)
       
   613   r = PyTuple_Pack(2, a, b) ;
       
   614 #else
       
   615   r = Py_BuildValue("OO", a, b);
       
   616 #endif
       
   617   Py_DECREF(a);
       
   618   Py_DECREF(b);
       
   619   return r;
       
   620 }
       
   621 
       
   622 static PyObject *BuildValue_IS(int i,const void *p,int s)
       
   623 {
       
   624   PyObject *a, *r;
       
   625 
       
   626   if (!p) {
       
   627     p=DummyString;
       
   628     assert(s==0);
       
   629   }
       
   630 
       
   631   if (!(a = PyBytes_FromStringAndSize(p, s))) {
       
   632       return NULL;
       
   633   }
       
   634 
       
   635   r = Py_BuildValue("iO", i, a);
       
   636   Py_DECREF(a);
       
   637   return r;
       
   638 }
       
   639 
       
   640 static PyObject *BuildValue_LS(long l,const void *p,int s)
       
   641 {
       
   642   PyObject *a, *r;
       
   643 
       
   644   if (!p) {
       
   645     p=DummyString;
       
   646     assert(s==0);
       
   647   }
       
   648 
       
   649   if (!(a = PyBytes_FromStringAndSize(p, s))) {
       
   650       return NULL;
       
   651   }
       
   652 
       
   653   r = Py_BuildValue("lO", l, a);
       
   654   Py_DECREF(a);
       
   655   return r;
       
   656 }
       
   657 
       
   658 
       
   659 
       
   660 /* make a nice exception object to raise for errors. */
       
   661 static int makeDBError(int err)
       
   662 {
       
   663     char errTxt[2048];  /* really big, just in case... */
       
   664     PyObject *errObj = NULL;
       
   665     PyObject *errTuple = NULL;
       
   666     int exceptionRaised = 0;
       
   667     unsigned int bytes_left;
       
   668 
       
   669     switch (err) {
       
   670         case 0:                     /* successful, no error */      break;
       
   671 
       
   672 #if (DBVER < 41)
       
   673         case DB_INCOMPLETE:
       
   674 #if INCOMPLETE_IS_WARNING
       
   675             bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
       
   676             /* Ensure that bytes_left never goes negative */
       
   677             if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
       
   678                 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
       
   679 		assert(bytes_left >= 0);
       
   680                 strcat(errTxt, " -- ");
       
   681                 strncat(errTxt, _db_errmsg, bytes_left);
       
   682             }
       
   683             _db_errmsg[0] = 0;
       
   684             exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
       
   685 
       
   686 #else  /* do an exception instead */
       
   687         errObj = DBIncompleteError;
       
   688 #endif
       
   689         break;
       
   690 #endif /* DBVER < 41 */
       
   691 
       
   692         case DB_KEYEMPTY:           errObj = DBKeyEmptyError;       break;
       
   693         case DB_KEYEXIST:           errObj = DBKeyExistError;       break;
       
   694         case DB_LOCK_DEADLOCK:      errObj = DBLockDeadlockError;   break;
       
   695         case DB_LOCK_NOTGRANTED:    errObj = DBLockNotGrantedError; break;
       
   696         case DB_NOTFOUND:           errObj = DBNotFoundError;       break;
       
   697         case DB_OLD_VERSION:        errObj = DBOldVersionError;     break;
       
   698         case DB_RUNRECOVERY:        errObj = DBRunRecoveryError;    break;
       
   699         case DB_VERIFY_BAD:         errObj = DBVerifyBadError;      break;
       
   700         case DB_NOSERVER:           errObj = DBNoServerError;       break;
       
   701         case DB_NOSERVER_HOME:      errObj = DBNoServerHomeError;   break;
       
   702         case DB_NOSERVER_ID:        errObj = DBNoServerIDError;     break;
       
   703         case DB_PAGE_NOTFOUND:      errObj = DBPageNotFoundError;   break;
       
   704         case DB_SECONDARY_BAD:      errObj = DBSecondaryBadError;   break;
       
   705         case DB_BUFFER_SMALL:       errObj = DBNoMemoryError;       break;
       
   706 
       
   707 #if (DBVER >= 43)
       
   708 	/* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
       
   709 	case ENOMEM:  errObj = PyExc_MemoryError;   break;
       
   710 #endif
       
   711         case EINVAL:  errObj = DBInvalidArgError;   break;
       
   712         case EACCES:  errObj = DBAccessError;       break;
       
   713         case ENOSPC:  errObj = DBNoSpaceError;      break;
       
   714         case EAGAIN:  errObj = DBAgainError;        break;
       
   715         case EBUSY :  errObj = DBBusyError;         break;
       
   716         case EEXIST:  errObj = DBFileExistsError;   break;
       
   717         case ENOENT:  errObj = DBNoSuchFileError;   break;
       
   718         case EPERM :  errObj = DBPermissionsError;  break;
       
   719 
       
   720 #if (DBVER >= 42)
       
   721         case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
       
   722 #endif
       
   723 
       
   724         case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
       
   725 
       
   726         default:      errObj = DBError;             break;
       
   727     }
       
   728 
       
   729     if (errObj != NULL) {
       
   730         bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
       
   731         /* Ensure that bytes_left never goes negative */
       
   732         if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
       
   733             bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
       
   734             assert(bytes_left >= 0);
       
   735             strcat(errTxt, " -- ");
       
   736             strncat(errTxt, _db_errmsg, bytes_left);
       
   737         }
       
   738         _db_errmsg[0] = 0;
       
   739 
       
   740         errTuple = Py_BuildValue("(is)", err, errTxt);
       
   741         if (errTuple == NULL) {
       
   742             Py_DECREF(errObj);
       
   743             return !0;
       
   744         }
       
   745         PyErr_SetObject(errObj, errTuple);
       
   746         Py_DECREF(errTuple);
       
   747     }
       
   748 
       
   749     return ((errObj != NULL) || exceptionRaised);
       
   750 }
       
   751 
       
   752 
       
   753 
       
   754 /* set a type exception */
       
   755 static void makeTypeError(char* expected, PyObject* found)
       
   756 {
       
   757     PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
       
   758                  expected, Py_TYPE(found)->tp_name);
       
   759 }
       
   760 
       
   761 
       
   762 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
       
   763 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
       
   764 {
       
   765     if (txnobj == Py_None || txnobj == NULL) {
       
   766         *txn = NULL;
       
   767         return 1;
       
   768     }
       
   769     if (DBTxnObject_Check(txnobj)) {
       
   770         *txn = ((DBTxnObject*)txnobj)->txn;
       
   771         return 1;
       
   772     }
       
   773     else
       
   774         makeTypeError("DBTxn", txnobj);
       
   775     return 0;
       
   776 }
       
   777 
       
   778 
       
   779 /* Delete a key from a database
       
   780   Returns 0 on success, -1 on an error.  */
       
   781 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
       
   782 {
       
   783     int err;
       
   784 
       
   785     MYDB_BEGIN_ALLOW_THREADS;
       
   786     err = self->db->del(self->db, txn, key, 0);
       
   787     MYDB_END_ALLOW_THREADS;
       
   788     if (makeDBError(err)) {
       
   789         return -1;
       
   790     }
       
   791     self->haveStat = 0;
       
   792     return 0;
       
   793 }
       
   794 
       
   795 
       
   796 /* Store a key into a database
       
   797    Returns 0 on success, -1 on an error.  */
       
   798 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
       
   799 {
       
   800     int err;
       
   801 
       
   802     MYDB_BEGIN_ALLOW_THREADS;
       
   803     err = self->db->put(self->db, txn, key, data, flags);
       
   804     MYDB_END_ALLOW_THREADS;
       
   805     if (makeDBError(err)) {
       
   806         return -1;
       
   807     }
       
   808     self->haveStat = 0;
       
   809     return 0;
       
   810 }
       
   811 
       
   812 /* Get a key/data pair from a cursor */
       
   813 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
       
   814 			       PyObject *args, PyObject *kwargs, char *format)
       
   815 {
       
   816     int err;
       
   817     PyObject* retval = NULL;
       
   818     DBT key, data;
       
   819     int dlen = -1;
       
   820     int doff = -1;
       
   821     int flags = 0;
       
   822     static char* kwnames[] = { "flags", "dlen", "doff", NULL };
       
   823 
       
   824     if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
       
   825 				     &flags, &dlen, &doff)) 
       
   826       return NULL;
       
   827 
       
   828     CHECK_CURSOR_NOT_CLOSED(self);
       
   829 
       
   830     flags |= extra_flags;
       
   831     CLEAR_DBT(key);
       
   832     CLEAR_DBT(data);
       
   833     if (!add_partial_dbt(&data, dlen, doff))
       
   834         return NULL;
       
   835 
       
   836     MYDB_BEGIN_ALLOW_THREADS;
       
   837     err = _DBC_get(self->dbc, &key, &data, flags);
       
   838     MYDB_END_ALLOW_THREADS;
       
   839 
       
   840     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
   841 	    && self->mydb->moduleFlags.getReturnsNone) {
       
   842         Py_INCREF(Py_None);
       
   843         retval = Py_None;
       
   844     }
       
   845     else if (makeDBError(err)) {
       
   846         retval = NULL;
       
   847     }
       
   848     else {  /* otherwise, success! */
       
   849 
       
   850         /* if Recno or Queue, return the key as an Int */
       
   851         switch (_DB_get_type(self->mydb)) {
       
   852         case -1:
       
   853             retval = NULL;
       
   854             break;
       
   855 
       
   856         case DB_RECNO:
       
   857         case DB_QUEUE:
       
   858             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
       
   859             break;
       
   860         case DB_HASH:
       
   861         case DB_BTREE:
       
   862         default:
       
   863             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
   864             break;
       
   865         }
       
   866     }
       
   867     return retval;
       
   868 }
       
   869 
       
   870 
       
   871 /* add an integer to a dictionary using the given name as a key */
       
   872 static void _addIntToDict(PyObject* dict, char *name, int value)
       
   873 {
       
   874     PyObject* v = NUMBER_FromLong((long) value);
       
   875     if (!v || PyDict_SetItemString(dict, name, v))
       
   876         PyErr_Clear();
       
   877 
       
   878     Py_XDECREF(v);
       
   879 }
       
   880 
       
   881 /* The same, when the value is a time_t */
       
   882 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
       
   883 {
       
   884     PyObject* v;
       
   885 	/* if the value fits in regular int, use that. */
       
   886 #ifdef PY_LONG_LONG
       
   887 	if (sizeof(time_t) > sizeof(long))
       
   888 		v = PyLong_FromLongLong((PY_LONG_LONG) value);
       
   889 	else
       
   890 #endif
       
   891 		v = NUMBER_FromLong((long) value);
       
   892     if (!v || PyDict_SetItemString(dict, name, v))
       
   893         PyErr_Clear();
       
   894 
       
   895     Py_XDECREF(v);
       
   896 }
       
   897 
       
   898 #if (DBVER >= 43)
       
   899 /* add an db_seq_t to a dictionary using the given name as a key */
       
   900 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
       
   901 {
       
   902     PyObject* v = PyLong_FromLongLong(value);
       
   903     if (!v || PyDict_SetItemString(dict, name, v))
       
   904         PyErr_Clear();
       
   905 
       
   906     Py_XDECREF(v);
       
   907 }
       
   908 #endif
       
   909 
       
   910 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
       
   911 {
       
   912     PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
       
   913     if (!v || PyDict_SetItemString(dict, name, v))
       
   914         PyErr_Clear();
       
   915 
       
   916     Py_XDECREF(v);
       
   917 }
       
   918 
       
   919 /* --------------------------------------------------------------------- */
       
   920 /* Allocators and deallocators */
       
   921 
       
   922 static DBObject*
       
   923 newDBObject(DBEnvObject* arg, int flags)
       
   924 {
       
   925     DBObject* self;
       
   926     DB_ENV* db_env = NULL;
       
   927     int err;
       
   928 
       
   929     self = PyObject_New(DBObject, &DB_Type);
       
   930     if (self == NULL)
       
   931         return NULL;
       
   932 
       
   933     self->haveStat = 0;
       
   934     self->flags = 0;
       
   935     self->setflags = 0;
       
   936     self->myenvobj = NULL;
       
   937     self->db = NULL;
       
   938     self->children_cursors = NULL;
       
   939 #if (DBVER >=43)
       
   940     self->children_sequences = NULL;
       
   941 #endif
       
   942     self->associateCallback = NULL;
       
   943     self->btCompareCallback = NULL;
       
   944     self->primaryDBType = 0;
       
   945     Py_INCREF(Py_None);
       
   946     self->private_obj = Py_None;
       
   947     self->in_weakreflist = NULL;
       
   948 
       
   949     /* keep a reference to our python DBEnv object */
       
   950     if (arg) {
       
   951         Py_INCREF(arg);
       
   952         self->myenvobj = arg;
       
   953         db_env = arg->db_env;
       
   954         INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
       
   955     } else {
       
   956       self->sibling_prev_p=NULL;
       
   957       self->sibling_next=NULL;
       
   958     }
       
   959     self->txn=NULL;
       
   960     self->sibling_prev_p_txn=NULL;
       
   961     self->sibling_next_txn=NULL;
       
   962 
       
   963     if (self->myenvobj)
       
   964         self->moduleFlags = self->myenvobj->moduleFlags;
       
   965     else
       
   966         self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
       
   967         self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
       
   968 
       
   969     MYDB_BEGIN_ALLOW_THREADS;
       
   970     err = db_create(&self->db, db_env, flags);
       
   971     if (self->db != NULL) {
       
   972         self->db->set_errcall(self->db, _db_errorCallback);
       
   973         self->db->app_private = (void*)self;
       
   974     }
       
   975     MYDB_END_ALLOW_THREADS;
       
   976     /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
       
   977      * list so that a DBEnv can refuse to close without aborting any open
       
   978      * DBTxns and closing any open DBs first. */
       
   979     if (makeDBError(err)) {
       
   980         if (self->myenvobj) {
       
   981             Py_DECREF(self->myenvobj);
       
   982             self->myenvobj = NULL;
       
   983         }
       
   984         Py_DECREF(self);
       
   985         self = NULL;
       
   986     }
       
   987     return self;
       
   988 }
       
   989 
       
   990 
       
   991 /* Forward declaration */
       
   992 static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
       
   993 
       
   994 static void
       
   995 DB_dealloc(DBObject* self)
       
   996 {
       
   997   PyObject *dummy;
       
   998 
       
   999     if (self->db != NULL) {
       
  1000         dummy=DB_close_internal(self, 0, 0);
       
  1001         /*
       
  1002         ** Raising exceptions while doing
       
  1003         ** garbage collection is a fatal error.
       
  1004         */
       
  1005         if (dummy)
       
  1006             Py_DECREF(dummy);
       
  1007         else
       
  1008             PyErr_Clear();
       
  1009     }
       
  1010     if (self->in_weakreflist != NULL) {
       
  1011         PyObject_ClearWeakRefs((PyObject *) self);
       
  1012     }
       
  1013     if (self->myenvobj) {
       
  1014         Py_DECREF(self->myenvobj);
       
  1015         self->myenvobj = NULL;
       
  1016     }
       
  1017     if (self->associateCallback != NULL) {
       
  1018         Py_DECREF(self->associateCallback);
       
  1019         self->associateCallback = NULL;
       
  1020     }
       
  1021     if (self->btCompareCallback != NULL) {
       
  1022         Py_DECREF(self->btCompareCallback);
       
  1023         self->btCompareCallback = NULL;
       
  1024     }
       
  1025     Py_DECREF(self->private_obj);
       
  1026     PyObject_Del(self);
       
  1027 }
       
  1028 
       
  1029 static DBCursorObject*
       
  1030 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
       
  1031 {
       
  1032     DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
       
  1033     if (self == NULL)
       
  1034         return NULL;
       
  1035 
       
  1036     self->dbc = dbc;
       
  1037     self->mydb = db;
       
  1038 
       
  1039     INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
       
  1040     if (txn && ((PyObject *)txn!=Py_None)) {
       
  1041 	    INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
       
  1042 	    self->txn=txn;
       
  1043     } else {
       
  1044 	    self->txn=NULL;
       
  1045     }
       
  1046 
       
  1047     self->in_weakreflist = NULL;
       
  1048     Py_INCREF(self->mydb);
       
  1049     return self;
       
  1050 }
       
  1051 
       
  1052 
       
  1053 /* Forward declaration */
       
  1054 static PyObject *DBC_close_internal(DBCursorObject* self);
       
  1055 
       
  1056 static void
       
  1057 DBCursor_dealloc(DBCursorObject* self)
       
  1058 {
       
  1059     PyObject *dummy;
       
  1060 
       
  1061     if (self->dbc != NULL) {
       
  1062         dummy=DBC_close_internal(self);
       
  1063         /*
       
  1064         ** Raising exceptions while doing
       
  1065         ** garbage collection is a fatal error.
       
  1066         */
       
  1067         if (dummy)
       
  1068             Py_DECREF(dummy);
       
  1069         else
       
  1070             PyErr_Clear();
       
  1071     }
       
  1072     if (self->in_weakreflist != NULL) {
       
  1073         PyObject_ClearWeakRefs((PyObject *) self);
       
  1074     }
       
  1075     Py_DECREF(self->mydb);
       
  1076     PyObject_Del(self);
       
  1077 }
       
  1078 
       
  1079 
       
  1080 static DBEnvObject*
       
  1081 newDBEnvObject(int flags)
       
  1082 {
       
  1083     int err;
       
  1084     DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
       
  1085     if (self == NULL)
       
  1086         return NULL;
       
  1087 
       
  1088     self->db_env = NULL;
       
  1089     self->closed = 1;
       
  1090     self->flags = flags;
       
  1091     self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
       
  1092     self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
       
  1093     self->children_dbs = NULL;
       
  1094     self->children_txns = NULL;
       
  1095     Py_INCREF(Py_None);
       
  1096     self->private_obj = Py_None;
       
  1097     Py_INCREF(Py_None);
       
  1098     self->rep_transport = Py_None;
       
  1099     self->in_weakreflist = NULL;
       
  1100     self->event_notifyCallback = NULL;
       
  1101 
       
  1102     MYDB_BEGIN_ALLOW_THREADS;
       
  1103     err = db_env_create(&self->db_env, flags);
       
  1104     MYDB_END_ALLOW_THREADS;
       
  1105     if (makeDBError(err)) {
       
  1106         Py_DECREF(self);
       
  1107         self = NULL;
       
  1108     }
       
  1109     else {
       
  1110         self->db_env->set_errcall(self->db_env, _db_errorCallback);
       
  1111         self->db_env->app_private = self;
       
  1112     }
       
  1113     return self;
       
  1114 }
       
  1115 
       
  1116 /* Forward declaration */
       
  1117 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
       
  1118 
       
  1119 static void
       
  1120 DBEnv_dealloc(DBEnvObject* self)
       
  1121 {
       
  1122   PyObject *dummy;
       
  1123 
       
  1124     if (self->db_env) {
       
  1125         dummy=DBEnv_close_internal(self, 0);
       
  1126         /*
       
  1127         ** Raising exceptions while doing
       
  1128         ** garbage collection is a fatal error.
       
  1129         */
       
  1130         if (dummy)
       
  1131             Py_DECREF(dummy);
       
  1132         else
       
  1133             PyErr_Clear();
       
  1134     }
       
  1135 
       
  1136     Py_XDECREF(self->event_notifyCallback);
       
  1137     self->event_notifyCallback = NULL;
       
  1138 
       
  1139     if (self->in_weakreflist != NULL) {
       
  1140         PyObject_ClearWeakRefs((PyObject *) self);
       
  1141     }
       
  1142     Py_DECREF(self->private_obj);
       
  1143     Py_DECREF(self->rep_transport);
       
  1144     PyObject_Del(self);
       
  1145 }
       
  1146 
       
  1147 
       
  1148 static DBTxnObject*
       
  1149 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
       
  1150 {
       
  1151     int err;
       
  1152     DB_TXN *parent_txn = NULL;
       
  1153 
       
  1154     DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
       
  1155     if (self == NULL)
       
  1156         return NULL;
       
  1157 
       
  1158     self->in_weakreflist = NULL;
       
  1159     self->children_txns = NULL;
       
  1160     self->children_dbs = NULL;
       
  1161     self->children_cursors = NULL;
       
  1162     self->children_sequences = NULL;
       
  1163     self->flag_prepare = 0;
       
  1164     self->parent_txn = NULL;
       
  1165     self->env = NULL;
       
  1166 
       
  1167     if (parent && ((PyObject *)parent!=Py_None)) {
       
  1168         parent_txn = parent->txn;
       
  1169     }
       
  1170 
       
  1171     if (txn) {
       
  1172         self->txn = txn;
       
  1173     } else {
       
  1174         MYDB_BEGIN_ALLOW_THREADS;
       
  1175         err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
       
  1176         MYDB_END_ALLOW_THREADS;
       
  1177 
       
  1178         if (makeDBError(err)) {
       
  1179             Py_DECREF(self);
       
  1180             return NULL;
       
  1181         }
       
  1182     }
       
  1183 
       
  1184     /* Can't use 'parent' because could be 'parent==Py_None' */
       
  1185     if (parent_txn) {
       
  1186         self->parent_txn = parent;
       
  1187         Py_INCREF(parent);
       
  1188         self->env = NULL;
       
  1189         INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
       
  1190     } else {
       
  1191         self->parent_txn = NULL;
       
  1192         Py_INCREF(myenv);
       
  1193         self->env = myenv;
       
  1194         INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
       
  1195     }
       
  1196 
       
  1197     return self;
       
  1198 }
       
  1199 
       
  1200 /* Forward declaration */
       
  1201 static PyObject *
       
  1202 DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
       
  1203 
       
  1204 static void
       
  1205 DBTxn_dealloc(DBTxnObject* self)
       
  1206 {
       
  1207   PyObject *dummy;
       
  1208 
       
  1209     if (self->txn) {
       
  1210         int flag_prepare = self->flag_prepare;
       
  1211 
       
  1212         dummy=DBTxn_abort_discard_internal(self,0);
       
  1213         /*
       
  1214         ** Raising exceptions while doing
       
  1215         ** garbage collection is a fatal error.
       
  1216         */
       
  1217         if (dummy)
       
  1218             Py_DECREF(dummy);
       
  1219         else
       
  1220             PyErr_Clear();
       
  1221 
       
  1222         if (!flag_prepare) {
       
  1223             PyErr_Warn(PyExc_RuntimeWarning,
       
  1224               "DBTxn aborted in destructor.  No prior commit() or abort().");
       
  1225         }
       
  1226     }
       
  1227 
       
  1228     if (self->in_weakreflist != NULL) {
       
  1229         PyObject_ClearWeakRefs((PyObject *) self);
       
  1230     }
       
  1231 
       
  1232     if (self->env) {
       
  1233         Py_DECREF(self->env);
       
  1234     } else {
       
  1235         Py_DECREF(self->parent_txn);
       
  1236     }
       
  1237     PyObject_Del(self);
       
  1238 }
       
  1239 
       
  1240 
       
  1241 static DBLockObject*
       
  1242 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
       
  1243                 db_lockmode_t lock_mode, int flags)
       
  1244 {
       
  1245     int err;
       
  1246     DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
       
  1247     if (self == NULL)
       
  1248         return NULL;
       
  1249     self->in_weakreflist = NULL;
       
  1250 
       
  1251     MYDB_BEGIN_ALLOW_THREADS;
       
  1252     err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
       
  1253                                   &self->lock);
       
  1254     MYDB_END_ALLOW_THREADS;
       
  1255     if (makeDBError(err)) {
       
  1256         Py_DECREF(self);
       
  1257         self = NULL;
       
  1258     }
       
  1259 
       
  1260     return self;
       
  1261 }
       
  1262 
       
  1263 
       
  1264 static void
       
  1265 DBLock_dealloc(DBLockObject* self)
       
  1266 {
       
  1267     if (self->in_weakreflist != NULL) {
       
  1268         PyObject_ClearWeakRefs((PyObject *) self);
       
  1269     }
       
  1270     /* TODO: is this lock held? should we release it? */
       
  1271 
       
  1272     PyObject_Del(self);
       
  1273 }
       
  1274 
       
  1275 
       
  1276 #if (DBVER >= 43)
       
  1277 static DBSequenceObject*
       
  1278 newDBSequenceObject(DBObject* mydb,  int flags)
       
  1279 {
       
  1280     int err;
       
  1281     DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
       
  1282     if (self == NULL)
       
  1283         return NULL;
       
  1284     Py_INCREF(mydb);
       
  1285     self->mydb = mydb;
       
  1286 
       
  1287     INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
       
  1288     self->txn = NULL;
       
  1289 
       
  1290     self->in_weakreflist = NULL;
       
  1291 
       
  1292     MYDB_BEGIN_ALLOW_THREADS;
       
  1293     err = db_sequence_create(&self->sequence, self->mydb->db, flags);
       
  1294     MYDB_END_ALLOW_THREADS;
       
  1295     if (makeDBError(err)) {
       
  1296         Py_DECREF(self);
       
  1297         self = NULL;
       
  1298     }
       
  1299 
       
  1300     return self;
       
  1301 }
       
  1302 
       
  1303 /* Forward declaration */
       
  1304 static PyObject
       
  1305 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
       
  1306 
       
  1307 static void
       
  1308 DBSequence_dealloc(DBSequenceObject* self)
       
  1309 {
       
  1310     PyObject *dummy;
       
  1311 
       
  1312     if (self->sequence != NULL) {
       
  1313         dummy=DBSequence_close_internal(self,0,0);
       
  1314         /*
       
  1315         ** Raising exceptions while doing
       
  1316         ** garbage collection is a fatal error.
       
  1317         */
       
  1318         if (dummy)
       
  1319             Py_DECREF(dummy);
       
  1320         else
       
  1321             PyErr_Clear();
       
  1322     }
       
  1323 
       
  1324     if (self->in_weakreflist != NULL) {
       
  1325         PyObject_ClearWeakRefs((PyObject *) self);
       
  1326     }
       
  1327 
       
  1328     Py_DECREF(self->mydb);
       
  1329     PyObject_Del(self);
       
  1330 }
       
  1331 #endif
       
  1332 
       
  1333 /* --------------------------------------------------------------------- */
       
  1334 /* DB methods */
       
  1335 
       
  1336 static PyObject*
       
  1337 DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1338 {
       
  1339     PyObject* txnobj = NULL;
       
  1340     PyObject* dataobj;
       
  1341     db_recno_t recno;
       
  1342     DBT key, data;
       
  1343     DB_TXN *txn = NULL;
       
  1344     static char* kwnames[] = { "data", "txn", NULL };
       
  1345 
       
  1346     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
       
  1347                                      &dataobj, &txnobj))
       
  1348         return NULL;
       
  1349 
       
  1350     CHECK_DB_NOT_CLOSED(self);
       
  1351 
       
  1352     /* make a dummy key out of a recno */
       
  1353     recno = 0;
       
  1354     CLEAR_DBT(key);
       
  1355     key.data = &recno;
       
  1356     key.size = sizeof(recno);
       
  1357     key.ulen = key.size;
       
  1358     key.flags = DB_DBT_USERMEM;
       
  1359 
       
  1360     if (!make_dbt(dataobj, &data)) return NULL;
       
  1361     if (!checkTxnObj(txnobj, &txn)) return NULL;
       
  1362 
       
  1363     if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
       
  1364         return NULL;
       
  1365 
       
  1366     return NUMBER_FromLong(recno);
       
  1367 }
       
  1368 
       
  1369 
       
  1370 static int
       
  1371 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
       
  1372                       DBT* secKey)
       
  1373 {
       
  1374     int       retval = DB_DONOTINDEX;
       
  1375     DBObject* secondaryDB = (DBObject*)db->app_private;
       
  1376     PyObject* callback = secondaryDB->associateCallback;
       
  1377     int       type = secondaryDB->primaryDBType;
       
  1378     PyObject* args;
       
  1379     PyObject* result = NULL;
       
  1380 
       
  1381 
       
  1382     if (callback != NULL) {
       
  1383         MYDB_BEGIN_BLOCK_THREADS;
       
  1384 
       
  1385         if (type == DB_RECNO || type == DB_QUEUE)
       
  1386             args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
       
  1387         else
       
  1388             args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
       
  1389         if (args != NULL) {
       
  1390                 result = PyEval_CallObject(callback, args);
       
  1391         }
       
  1392         if (args == NULL || result == NULL) {
       
  1393             PyErr_Print();
       
  1394         }
       
  1395         else if (result == Py_None) {
       
  1396             retval = DB_DONOTINDEX;
       
  1397         }
       
  1398         else if (NUMBER_Check(result)) {
       
  1399             retval = NUMBER_AsLong(result);
       
  1400         }
       
  1401         else if (PyBytes_Check(result)) {
       
  1402             char* data;
       
  1403             Py_ssize_t size;
       
  1404 
       
  1405             CLEAR_DBT(*secKey);
       
  1406             PyBytes_AsStringAndSize(result, &data, &size);
       
  1407             secKey->flags = DB_DBT_APPMALLOC;   /* DB will free */
       
  1408             secKey->data = malloc(size);        /* TODO, check this */
       
  1409 	    if (secKey->data) {
       
  1410 		memcpy(secKey->data, data, size);
       
  1411 		secKey->size = size;
       
  1412 		retval = 0;
       
  1413 	    }
       
  1414 	    else {
       
  1415 		PyErr_SetString(PyExc_MemoryError,
       
  1416                                 "malloc failed in _db_associateCallback");
       
  1417 		PyErr_Print();
       
  1418 	    }
       
  1419         }
       
  1420         else {
       
  1421             PyErr_SetString(
       
  1422                PyExc_TypeError,
       
  1423                "DB associate callback should return DB_DONOTINDEX or string.");
       
  1424             PyErr_Print();
       
  1425         }
       
  1426 
       
  1427         Py_XDECREF(args);
       
  1428         Py_XDECREF(result);
       
  1429 
       
  1430         MYDB_END_BLOCK_THREADS;
       
  1431     }
       
  1432     return retval;
       
  1433 }
       
  1434 
       
  1435 
       
  1436 static PyObject*
       
  1437 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1438 {
       
  1439     int err, flags=0;
       
  1440     DBObject* secondaryDB;
       
  1441     PyObject* callback;
       
  1442 #if (DBVER >= 41)
       
  1443     PyObject *txnobj = NULL;
       
  1444     DB_TXN *txn = NULL;
       
  1445     static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
       
  1446                                     NULL};
       
  1447 #else
       
  1448     static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
       
  1449 #endif
       
  1450 
       
  1451 #if (DBVER >= 41)
       
  1452     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
       
  1453                                      &secondaryDB, &callback, &flags,
       
  1454                                      &txnobj)) {
       
  1455 #else
       
  1456     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
       
  1457                                      &secondaryDB, &callback, &flags)) {
       
  1458 #endif
       
  1459         return NULL;
       
  1460     }
       
  1461 
       
  1462 #if (DBVER >= 41)
       
  1463     if (!checkTxnObj(txnobj, &txn)) return NULL;
       
  1464 #endif
       
  1465 
       
  1466     CHECK_DB_NOT_CLOSED(self);
       
  1467     if (!DBObject_Check(secondaryDB)) {
       
  1468         makeTypeError("DB", (PyObject*)secondaryDB);
       
  1469         return NULL;
       
  1470     }
       
  1471     CHECK_DB_NOT_CLOSED(secondaryDB);
       
  1472     if (callback == Py_None) {
       
  1473         callback = NULL;
       
  1474     }
       
  1475     else if (!PyCallable_Check(callback)) {
       
  1476         makeTypeError("Callable", callback);
       
  1477         return NULL;
       
  1478     }
       
  1479 
       
  1480     /* Save a reference to the callback in the secondary DB. */
       
  1481     Py_XDECREF(secondaryDB->associateCallback);
       
  1482     Py_XINCREF(callback);
       
  1483     secondaryDB->associateCallback = callback;
       
  1484     secondaryDB->primaryDBType = _DB_get_type(self);
       
  1485 
       
  1486     /* PyEval_InitThreads is called here due to a quirk in python 1.5
       
  1487      * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
       
  1488      * The global interepreter lock is not initialized until the first
       
  1489      * thread is created using thread.start_new_thread() or fork() is
       
  1490      * called.  that would cause the ALLOW_THREADS here to segfault due
       
  1491      * to a null pointer reference if no threads or child processes
       
  1492      * have been created.  This works around that and is a no-op if
       
  1493      * threads have already been initialized.
       
  1494      *  (see pybsddb-users mailing list post on 2002-08-07)
       
  1495      */
       
  1496 #ifdef WITH_THREAD
       
  1497     PyEval_InitThreads();
       
  1498 #endif
       
  1499     MYDB_BEGIN_ALLOW_THREADS;
       
  1500 #if (DBVER >= 41)
       
  1501     err = self->db->associate(self->db,
       
  1502 	                      txn,
       
  1503                               secondaryDB->db,
       
  1504                               _db_associateCallback,
       
  1505                               flags);
       
  1506 #else
       
  1507     err = self->db->associate(self->db,
       
  1508                               secondaryDB->db,
       
  1509                               _db_associateCallback,
       
  1510                               flags);
       
  1511 #endif
       
  1512     MYDB_END_ALLOW_THREADS;
       
  1513 
       
  1514     if (err) {
       
  1515         Py_XDECREF(secondaryDB->associateCallback);
       
  1516         secondaryDB->associateCallback = NULL;
       
  1517         secondaryDB->primaryDBType = 0;
       
  1518     }
       
  1519 
       
  1520     RETURN_IF_ERR();
       
  1521     RETURN_NONE();
       
  1522 }
       
  1523 
       
  1524 
       
  1525 static PyObject*
       
  1526 DB_close_internal(DBObject* self, int flags, int do_not_close)
       
  1527 {
       
  1528     PyObject *dummy;
       
  1529     int err = 0;
       
  1530 
       
  1531     if (self->db != NULL) {
       
  1532         /* Can be NULL if db is not in an environment */
       
  1533         EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
       
  1534 
       
  1535         if (self->txn) {
       
  1536             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
       
  1537             self->txn=NULL;
       
  1538         }
       
  1539 
       
  1540         while(self->children_cursors) {
       
  1541           dummy=DBC_close_internal(self->children_cursors);
       
  1542           Py_XDECREF(dummy);
       
  1543         }
       
  1544 
       
  1545 #if (DBVER >= 43)
       
  1546         while(self->children_sequences) {
       
  1547             dummy=DBSequence_close_internal(self->children_sequences,0,0);
       
  1548             Py_XDECREF(dummy);
       
  1549         }
       
  1550 #endif
       
  1551 
       
  1552         /*
       
  1553         ** "do_not_close" is used to dispose all related objects in the
       
  1554         ** tree, without actually releasing the "root" object.
       
  1555         ** This is done, for example, because function calls like
       
  1556         ** "DB.verify()" implicitly close the underlying handle. So
       
  1557         ** the handle doesn't need to be closed, but related objects
       
  1558         ** must be cleaned up.
       
  1559         */
       
  1560         if (!do_not_close) {
       
  1561             MYDB_BEGIN_ALLOW_THREADS;
       
  1562             err = self->db->close(self->db, flags);
       
  1563             MYDB_END_ALLOW_THREADS;
       
  1564             self->db = NULL;
       
  1565         }
       
  1566         RETURN_IF_ERR();
       
  1567     }
       
  1568     RETURN_NONE();
       
  1569 }
       
  1570 
       
  1571 static PyObject*
       
  1572 DB_close(DBObject* self, PyObject* args)
       
  1573 {
       
  1574     int flags=0;
       
  1575     if (!PyArg_ParseTuple(args,"|i:close", &flags))
       
  1576         return NULL;
       
  1577     return DB_close_internal(self, flags, 0);
       
  1578 }
       
  1579 
       
  1580 
       
  1581 static PyObject*
       
  1582 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
       
  1583 {
       
  1584     int err, flags=0, type;
       
  1585     PyObject* txnobj = NULL;
       
  1586     PyObject* retval = NULL;
       
  1587     DBT key, data;
       
  1588     DB_TXN *txn = NULL;
       
  1589     static char* kwnames[] = { "txn", "flags", NULL };
       
  1590 
       
  1591     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
       
  1592                                      &txnobj, &flags))
       
  1593         return NULL;
       
  1594 
       
  1595     CHECK_DB_NOT_CLOSED(self);
       
  1596     type = _DB_get_type(self);
       
  1597     if (type == -1)
       
  1598         return NULL;
       
  1599     if (type != DB_QUEUE) {
       
  1600         PyErr_SetString(PyExc_TypeError,
       
  1601                         "Consume methods only allowed for Queue DB's");
       
  1602         return NULL;
       
  1603     }
       
  1604     if (!checkTxnObj(txnobj, &txn))
       
  1605         return NULL;
       
  1606 
       
  1607     CLEAR_DBT(key);
       
  1608     CLEAR_DBT(data);
       
  1609     if (CHECK_DBFLAG(self, DB_THREAD)) {
       
  1610         /* Tell Berkeley DB to malloc the return value (thread safe) */
       
  1611         data.flags = DB_DBT_MALLOC;
       
  1612         key.flags = DB_DBT_MALLOC;
       
  1613     }
       
  1614 
       
  1615     MYDB_BEGIN_ALLOW_THREADS;
       
  1616     err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
       
  1617     MYDB_END_ALLOW_THREADS;
       
  1618 
       
  1619     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  1620 	    && self->moduleFlags.getReturnsNone) {
       
  1621         err = 0;
       
  1622         Py_INCREF(Py_None);
       
  1623         retval = Py_None;
       
  1624     }
       
  1625     else if (!err) {
       
  1626         retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  1627         FREE_DBT(key);
       
  1628         FREE_DBT(data);
       
  1629     }
       
  1630 
       
  1631     RETURN_IF_ERR();
       
  1632     return retval;
       
  1633 }
       
  1634 
       
  1635 static PyObject*
       
  1636 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
       
  1637 {
       
  1638     return _DB_consume(self, args, kwargs, DB_CONSUME);
       
  1639 }
       
  1640 
       
  1641 static PyObject*
       
  1642 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
       
  1643                 int consume_flag)
       
  1644 {
       
  1645     return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
       
  1646 }
       
  1647 
       
  1648 
       
  1649 static PyObject*
       
  1650 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1651 {
       
  1652     int err, flags=0;
       
  1653     DBC* dbc;
       
  1654     PyObject* txnobj = NULL;
       
  1655     DB_TXN *txn = NULL;
       
  1656     static char* kwnames[] = { "txn", "flags", NULL };
       
  1657 
       
  1658     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
       
  1659                                      &txnobj, &flags))
       
  1660         return NULL;
       
  1661     CHECK_DB_NOT_CLOSED(self);
       
  1662     if (!checkTxnObj(txnobj, &txn))
       
  1663         return NULL;
       
  1664 
       
  1665     MYDB_BEGIN_ALLOW_THREADS;
       
  1666     err = self->db->cursor(self->db, txn, &dbc, flags);
       
  1667     MYDB_END_ALLOW_THREADS;
       
  1668     RETURN_IF_ERR();
       
  1669     return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
       
  1670 }
       
  1671 
       
  1672 
       
  1673 static PyObject*
       
  1674 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1675 {
       
  1676     PyObject* txnobj = NULL;
       
  1677     int flags = 0;
       
  1678     PyObject* keyobj;
       
  1679     DBT key;
       
  1680     DB_TXN *txn = NULL;
       
  1681     static char* kwnames[] = { "key", "txn", "flags", NULL };
       
  1682 
       
  1683     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
       
  1684                                      &keyobj, &txnobj, &flags))
       
  1685         return NULL;
       
  1686     CHECK_DB_NOT_CLOSED(self);
       
  1687     if (!make_key_dbt(self, keyobj, &key, NULL))
       
  1688         return NULL;
       
  1689     if (!checkTxnObj(txnobj, &txn)) {
       
  1690         FREE_DBT(key);
       
  1691         return NULL;
       
  1692     }
       
  1693 
       
  1694     if (-1 == _DB_delete(self, txn, &key, 0)) {
       
  1695         FREE_DBT(key);
       
  1696         return NULL;
       
  1697     }
       
  1698 
       
  1699     FREE_DBT(key);
       
  1700     RETURN_NONE();
       
  1701 }
       
  1702 
       
  1703 
       
  1704 static PyObject*
       
  1705 DB_fd(DBObject* self)
       
  1706 {
       
  1707     int err, the_fd;
       
  1708 
       
  1709     CHECK_DB_NOT_CLOSED(self);
       
  1710 
       
  1711     MYDB_BEGIN_ALLOW_THREADS;
       
  1712     err = self->db->fd(self->db, &the_fd);
       
  1713     MYDB_END_ALLOW_THREADS;
       
  1714     RETURN_IF_ERR();
       
  1715     return NUMBER_FromLong(the_fd);
       
  1716 }
       
  1717 
       
  1718 
       
  1719 static PyObject*
       
  1720 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1721 {
       
  1722     int err, flags=0;
       
  1723     PyObject* txnobj = NULL;
       
  1724     PyObject* keyobj;
       
  1725     PyObject* dfltobj = NULL;
       
  1726     PyObject* retval = NULL;
       
  1727     int dlen = -1;
       
  1728     int doff = -1;
       
  1729     DBT key, data;
       
  1730     DB_TXN *txn = NULL;
       
  1731     static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
       
  1732                                     "doff", NULL};
       
  1733 
       
  1734     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
       
  1735                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen,
       
  1736                                      &doff))
       
  1737         return NULL;
       
  1738 
       
  1739     CHECK_DB_NOT_CLOSED(self);
       
  1740     if (!make_key_dbt(self, keyobj, &key, &flags))
       
  1741         return NULL;
       
  1742     if (!checkTxnObj(txnobj, &txn)) {
       
  1743         FREE_DBT(key);
       
  1744         return NULL;
       
  1745     }
       
  1746 
       
  1747     CLEAR_DBT(data);
       
  1748     if (CHECK_DBFLAG(self, DB_THREAD)) {
       
  1749         /* Tell Berkeley DB to malloc the return value (thread safe) */
       
  1750         data.flags = DB_DBT_MALLOC;
       
  1751     }
       
  1752     if (!add_partial_dbt(&data, dlen, doff)) {
       
  1753         FREE_DBT(key);
       
  1754         return NULL;
       
  1755     }
       
  1756 
       
  1757     MYDB_BEGIN_ALLOW_THREADS;
       
  1758     err = self->db->get(self->db, txn, &key, &data, flags);
       
  1759     MYDB_END_ALLOW_THREADS;
       
  1760 
       
  1761     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
       
  1762         err = 0;
       
  1763         Py_INCREF(dfltobj);
       
  1764         retval = dfltobj;
       
  1765     }
       
  1766     else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  1767 	     && self->moduleFlags.getReturnsNone) {
       
  1768         err = 0;
       
  1769         Py_INCREF(Py_None);
       
  1770         retval = Py_None;
       
  1771     }
       
  1772     else if (!err) {
       
  1773         if (flags & DB_SET_RECNO) /* return both key and data */
       
  1774             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  1775         else /* return just the data */
       
  1776             retval = Build_PyString(data.data, data.size);
       
  1777         FREE_DBT(data);
       
  1778     }
       
  1779     FREE_DBT(key);
       
  1780 
       
  1781     RETURN_IF_ERR();
       
  1782     return retval;
       
  1783 }
       
  1784 
       
  1785 static PyObject*
       
  1786 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1787 {
       
  1788     int err, flags=0;
       
  1789     PyObject* txnobj = NULL;
       
  1790     PyObject* keyobj;
       
  1791     PyObject* dfltobj = NULL;
       
  1792     PyObject* retval = NULL;
       
  1793     int dlen = -1;
       
  1794     int doff = -1;
       
  1795     DBT key, pkey, data;
       
  1796     DB_TXN *txn = NULL;
       
  1797     static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
       
  1798                                     "doff", NULL};
       
  1799 
       
  1800     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
       
  1801                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen,
       
  1802                                      &doff))
       
  1803         return NULL;
       
  1804 
       
  1805     CHECK_DB_NOT_CLOSED(self);
       
  1806     if (!make_key_dbt(self, keyobj, &key, &flags))
       
  1807         return NULL;
       
  1808     if (!checkTxnObj(txnobj, &txn)) {
       
  1809         FREE_DBT(key);
       
  1810         return NULL;
       
  1811     }
       
  1812 
       
  1813     CLEAR_DBT(data);
       
  1814     if (CHECK_DBFLAG(self, DB_THREAD)) {
       
  1815         /* Tell Berkeley DB to malloc the return value (thread safe) */
       
  1816         data.flags = DB_DBT_MALLOC;
       
  1817     }
       
  1818     if (!add_partial_dbt(&data, dlen, doff)) {
       
  1819         FREE_DBT(key);
       
  1820         return NULL;
       
  1821     }
       
  1822 
       
  1823     CLEAR_DBT(pkey);
       
  1824     pkey.flags = DB_DBT_MALLOC;
       
  1825 
       
  1826     MYDB_BEGIN_ALLOW_THREADS;
       
  1827     err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
       
  1828     MYDB_END_ALLOW_THREADS;
       
  1829 
       
  1830     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
       
  1831         err = 0;
       
  1832         Py_INCREF(dfltobj);
       
  1833         retval = dfltobj;
       
  1834     }
       
  1835     else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  1836 	     && self->moduleFlags.getReturnsNone) {
       
  1837         err = 0;
       
  1838         Py_INCREF(Py_None);
       
  1839         retval = Py_None;
       
  1840     }
       
  1841     else if (!err) {
       
  1842         PyObject *pkeyObj;
       
  1843         PyObject *dataObj;
       
  1844         dataObj = Build_PyString(data.data, data.size);
       
  1845 
       
  1846         if (self->primaryDBType == DB_RECNO ||
       
  1847             self->primaryDBType == DB_QUEUE)
       
  1848             pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
       
  1849         else
       
  1850             pkeyObj = Build_PyString(pkey.data, pkey.size);
       
  1851 
       
  1852         if (flags & DB_SET_RECNO) /* return key , pkey and data */
       
  1853         {
       
  1854             PyObject *keyObj;
       
  1855             int type = _DB_get_type(self);
       
  1856             if (type == DB_RECNO || type == DB_QUEUE)
       
  1857                 keyObj = NUMBER_FromLong(*(int *)key.data);
       
  1858             else
       
  1859                 keyObj = Build_PyString(key.data, key.size);
       
  1860 #if (PY_VERSION_HEX >= 0x02040000)
       
  1861             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
       
  1862 #else
       
  1863             retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
       
  1864 #endif
       
  1865             Py_DECREF(keyObj);
       
  1866         }
       
  1867         else /* return just the pkey and data */
       
  1868         {
       
  1869 #if (PY_VERSION_HEX >= 0x02040000)
       
  1870             retval = PyTuple_Pack(2, pkeyObj, dataObj);
       
  1871 #else
       
  1872             retval = Py_BuildValue("OO", pkeyObj, dataObj);
       
  1873 #endif
       
  1874         }
       
  1875         Py_DECREF(dataObj);
       
  1876         Py_DECREF(pkeyObj);
       
  1877         FREE_DBT(pkey);
       
  1878         FREE_DBT(data);
       
  1879     }
       
  1880     FREE_DBT(key);
       
  1881 
       
  1882     RETURN_IF_ERR();
       
  1883     return retval;
       
  1884 }
       
  1885 
       
  1886 
       
  1887 /* Return size of entry */
       
  1888 static PyObject*
       
  1889 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1890 {
       
  1891     int err, flags=0;
       
  1892     PyObject* txnobj = NULL;
       
  1893     PyObject* keyobj;
       
  1894     PyObject* retval = NULL;
       
  1895     DBT key, data;
       
  1896     DB_TXN *txn = NULL;
       
  1897     static char* kwnames[] = { "key", "txn", NULL };
       
  1898 
       
  1899     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
       
  1900                                      &keyobj, &txnobj))
       
  1901         return NULL;
       
  1902     CHECK_DB_NOT_CLOSED(self);
       
  1903     if (!make_key_dbt(self, keyobj, &key, &flags))
       
  1904         return NULL;
       
  1905     if (!checkTxnObj(txnobj, &txn)) {
       
  1906         FREE_DBT(key);
       
  1907         return NULL;
       
  1908     }
       
  1909     CLEAR_DBT(data);
       
  1910 
       
  1911     /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
       
  1912        thus getting the record size. */
       
  1913     data.flags = DB_DBT_USERMEM;
       
  1914     data.ulen = 0;
       
  1915     MYDB_BEGIN_ALLOW_THREADS;
       
  1916     err = self->db->get(self->db, txn, &key, &data, flags);
       
  1917     MYDB_END_ALLOW_THREADS;
       
  1918     if (err == DB_BUFFER_SMALL) {
       
  1919         retval = NUMBER_FromLong((long)data.size);
       
  1920         err = 0;
       
  1921     }
       
  1922 
       
  1923     FREE_DBT(key);
       
  1924     FREE_DBT(data);
       
  1925     RETURN_IF_ERR();
       
  1926     return retval;
       
  1927 }
       
  1928 
       
  1929 
       
  1930 static PyObject*
       
  1931 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
       
  1932 {
       
  1933     int err, flags=0;
       
  1934     PyObject* txnobj = NULL;
       
  1935     PyObject* keyobj;
       
  1936     PyObject* dataobj;
       
  1937     PyObject* retval = NULL;
       
  1938     DBT key, data;
       
  1939     void *orig_data;
       
  1940     DB_TXN *txn = NULL;
       
  1941     static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
       
  1942 
       
  1943     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
       
  1944                                      &keyobj, &dataobj, &txnobj, &flags))
       
  1945         return NULL;
       
  1946 
       
  1947     CHECK_DB_NOT_CLOSED(self);
       
  1948     if (!make_key_dbt(self, keyobj, &key, NULL))
       
  1949         return NULL;
       
  1950     if ( !make_dbt(dataobj, &data) ||
       
  1951          !checkTxnObj(txnobj, &txn) )
       
  1952     {
       
  1953         FREE_DBT(key);
       
  1954         return NULL;
       
  1955     }
       
  1956 
       
  1957     flags |= DB_GET_BOTH;
       
  1958     orig_data = data.data;
       
  1959 
       
  1960     if (CHECK_DBFLAG(self, DB_THREAD)) {
       
  1961         /* Tell Berkeley DB to malloc the return value (thread safe) */
       
  1962         /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
       
  1963         data.flags = DB_DBT_MALLOC;
       
  1964     }
       
  1965 
       
  1966     MYDB_BEGIN_ALLOW_THREADS;
       
  1967     err = self->db->get(self->db, txn, &key, &data, flags);
       
  1968     MYDB_END_ALLOW_THREADS;
       
  1969 
       
  1970     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  1971 	    && self->moduleFlags.getReturnsNone) {
       
  1972         err = 0;
       
  1973         Py_INCREF(Py_None);
       
  1974         retval = Py_None;
       
  1975     }
       
  1976     else if (!err) {
       
  1977         /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
       
  1978         retval = Build_PyString(data.data, data.size);
       
  1979 
       
  1980         /* Even though the flags require DB_DBT_MALLOC, data is not always
       
  1981            allocated.  4.4: allocated, 4.5: *not* allocated. :-( */
       
  1982         if (data.data != orig_data)
       
  1983             FREE_DBT(data);
       
  1984     }
       
  1985 
       
  1986     FREE_DBT(key);
       
  1987     RETURN_IF_ERR();
       
  1988     return retval;
       
  1989 }
       
  1990 
       
  1991 
       
  1992 static PyObject*
       
  1993 DB_get_byteswapped(DBObject* self)
       
  1994 {
       
  1995     int err = 0;
       
  1996     int retval = -1;
       
  1997 
       
  1998     CHECK_DB_NOT_CLOSED(self);
       
  1999 
       
  2000     MYDB_BEGIN_ALLOW_THREADS;
       
  2001     err = self->db->get_byteswapped(self->db, &retval);
       
  2002     MYDB_END_ALLOW_THREADS;
       
  2003     RETURN_IF_ERR();
       
  2004     return NUMBER_FromLong(retval);
       
  2005 }
       
  2006 
       
  2007 
       
  2008 static PyObject*
       
  2009 DB_get_type(DBObject* self)
       
  2010 {
       
  2011     int type;
       
  2012 
       
  2013     CHECK_DB_NOT_CLOSED(self);
       
  2014 
       
  2015     type = _DB_get_type(self);
       
  2016     if (type == -1)
       
  2017         return NULL;
       
  2018     return NUMBER_FromLong(type);
       
  2019 }
       
  2020 
       
  2021 
       
  2022 static PyObject*
       
  2023 DB_join(DBObject* self, PyObject* args)
       
  2024 {
       
  2025     int err, flags=0;
       
  2026     int length, x;
       
  2027     PyObject* cursorsObj;
       
  2028     DBC** cursors;
       
  2029     DBC*  dbc;
       
  2030 
       
  2031     if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
       
  2032         return NULL;
       
  2033 
       
  2034     CHECK_DB_NOT_CLOSED(self);
       
  2035 
       
  2036     if (!PySequence_Check(cursorsObj)) {
       
  2037         PyErr_SetString(PyExc_TypeError,
       
  2038                         "Sequence of DBCursor objects expected");
       
  2039         return NULL;
       
  2040     }
       
  2041 
       
  2042     length = PyObject_Length(cursorsObj);
       
  2043     cursors = malloc((length+1) * sizeof(DBC*));
       
  2044     if (!cursors) {
       
  2045 	PyErr_NoMemory();
       
  2046 	return NULL;
       
  2047     }
       
  2048 
       
  2049     cursors[length] = NULL;
       
  2050     for (x=0; x<length; x++) {
       
  2051         PyObject* item = PySequence_GetItem(cursorsObj, x);
       
  2052         if (item == NULL) {
       
  2053             free(cursors);
       
  2054             return NULL;
       
  2055         }
       
  2056         if (!DBCursorObject_Check(item)) {
       
  2057             PyErr_SetString(PyExc_TypeError,
       
  2058                             "Sequence of DBCursor objects expected");
       
  2059             free(cursors);
       
  2060             return NULL;
       
  2061         }
       
  2062         cursors[x] = ((DBCursorObject*)item)->dbc;
       
  2063         Py_DECREF(item);
       
  2064     }
       
  2065 
       
  2066     MYDB_BEGIN_ALLOW_THREADS;
       
  2067     err = self->db->join(self->db, cursors, &dbc, flags);
       
  2068     MYDB_END_ALLOW_THREADS;
       
  2069     free(cursors);
       
  2070     RETURN_IF_ERR();
       
  2071 
       
  2072     /* FIXME: this is a buggy interface.  The returned cursor
       
  2073        contains internal references to the passed in cursors
       
  2074        but does not hold python references to them or prevent
       
  2075        them from being closed prematurely.  This can cause
       
  2076        python to crash when things are done in the wrong order. */
       
  2077     return (PyObject*) newDBCursorObject(dbc, NULL, self);
       
  2078 }
       
  2079 
       
  2080 
       
  2081 static PyObject*
       
  2082 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2083 {
       
  2084     int err, flags=0;
       
  2085     PyObject* txnobj = NULL;
       
  2086     PyObject* keyobj;
       
  2087     DBT key;
       
  2088     DB_TXN *txn = NULL;
       
  2089     DB_KEY_RANGE range;
       
  2090     static char* kwnames[] = { "key", "txn", "flags", NULL };
       
  2091 
       
  2092     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
       
  2093                                      &keyobj, &txnobj, &flags))
       
  2094         return NULL;
       
  2095     CHECK_DB_NOT_CLOSED(self);
       
  2096     if (!make_dbt(keyobj, &key))
       
  2097         /* BTree only, don't need to allow for an int key */
       
  2098         return NULL;
       
  2099     if (!checkTxnObj(txnobj, &txn))
       
  2100         return NULL;
       
  2101 
       
  2102     MYDB_BEGIN_ALLOW_THREADS;
       
  2103     err = self->db->key_range(self->db, txn, &key, &range, flags);
       
  2104     MYDB_END_ALLOW_THREADS;
       
  2105 
       
  2106     RETURN_IF_ERR();
       
  2107     return Py_BuildValue("ddd", range.less, range.equal, range.greater);
       
  2108 }
       
  2109 
       
  2110 
       
  2111 static PyObject*
       
  2112 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2113 {
       
  2114     int err, type = DB_UNKNOWN, flags=0, mode=0660;
       
  2115     char* filename = NULL;
       
  2116     char* dbname = NULL;
       
  2117 #if (DBVER >= 41)
       
  2118     PyObject *txnobj = NULL;
       
  2119     DB_TXN *txn = NULL;
       
  2120     /* with dbname */
       
  2121     static char* kwnames[] = {
       
  2122         "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
       
  2123     /* without dbname */
       
  2124     static char* kwnames_basic[] = {
       
  2125         "filename", "dbtype", "flags", "mode", "txn", NULL};
       
  2126 #else
       
  2127     /* with dbname */
       
  2128     static char* kwnames[] = {
       
  2129         "filename", "dbname", "dbtype", "flags", "mode", NULL};
       
  2130     /* without dbname */
       
  2131     static char* kwnames_basic[] = {
       
  2132         "filename", "dbtype", "flags", "mode", NULL};
       
  2133 #endif
       
  2134 
       
  2135 #if (DBVER >= 41)
       
  2136     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
       
  2137 				     &filename, &dbname, &type, &flags, &mode,
       
  2138                                      &txnobj))
       
  2139 #else
       
  2140     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
       
  2141 				     &filename, &dbname, &type, &flags,
       
  2142                                      &mode))
       
  2143 #endif
       
  2144     {
       
  2145 	PyErr_Clear();
       
  2146 	type = DB_UNKNOWN; flags = 0; mode = 0660;
       
  2147 	filename = NULL; dbname = NULL;
       
  2148 #if (DBVER >= 41)
       
  2149 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
       
  2150                                          kwnames_basic,
       
  2151 					 &filename, &type, &flags, &mode,
       
  2152                                          &txnobj))
       
  2153 	    return NULL;
       
  2154 #else
       
  2155 	if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
       
  2156                                          kwnames_basic,
       
  2157 					 &filename, &type, &flags, &mode))
       
  2158 	    return NULL;
       
  2159 #endif
       
  2160     }
       
  2161 
       
  2162 #if (DBVER >= 41)
       
  2163     if (!checkTxnObj(txnobj, &txn)) return NULL;
       
  2164 #endif
       
  2165 
       
  2166     if (NULL == self->db) {
       
  2167         PyObject *t = Py_BuildValue("(is)", 0,
       
  2168                                 "Cannot call open() twice for DB object");
       
  2169         if (t) {
       
  2170             PyErr_SetObject(DBError, t);
       
  2171             Py_DECREF(t);
       
  2172         }
       
  2173         return NULL;
       
  2174     }
       
  2175 
       
  2176 #if (DBVER >= 41)
       
  2177     if (txn) {  /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
       
  2178         INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
       
  2179         self->txn=(DBTxnObject *)txnobj;
       
  2180     } else {
       
  2181         self->txn=NULL;
       
  2182     }
       
  2183 #else
       
  2184     self->txn=NULL;
       
  2185 #endif
       
  2186 
       
  2187     MYDB_BEGIN_ALLOW_THREADS;
       
  2188 #if (DBVER >= 41)
       
  2189     err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
       
  2190 #else
       
  2191     err = self->db->open(self->db, filename, dbname, type, flags, mode);
       
  2192 #endif
       
  2193     MYDB_END_ALLOW_THREADS;
       
  2194     if (makeDBError(err)) {
       
  2195         PyObject *dummy;
       
  2196 
       
  2197         dummy=DB_close_internal(self, 0, 0);
       
  2198         Py_XDECREF(dummy);
       
  2199         return NULL;
       
  2200     }
       
  2201 
       
  2202 #if (DBVER >= 42)
       
  2203     self->db->get_flags(self->db, &self->setflags);
       
  2204 #endif
       
  2205 
       
  2206     self->flags = flags;
       
  2207 
       
  2208     RETURN_NONE();
       
  2209 }
       
  2210 
       
  2211 
       
  2212 static PyObject*
       
  2213 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2214 {
       
  2215     int flags=0;
       
  2216     PyObject* txnobj = NULL;
       
  2217     int dlen = -1;
       
  2218     int doff = -1;
       
  2219     PyObject* keyobj, *dataobj, *retval;
       
  2220     DBT key, data;
       
  2221     DB_TXN *txn = NULL;
       
  2222     static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
       
  2223                                      "doff", NULL };
       
  2224 
       
  2225     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
       
  2226                          &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
       
  2227         return NULL;
       
  2228 
       
  2229     CHECK_DB_NOT_CLOSED(self);
       
  2230     if (!make_key_dbt(self, keyobj, &key, NULL))
       
  2231         return NULL;
       
  2232     if ( !make_dbt(dataobj, &data) ||
       
  2233          !add_partial_dbt(&data, dlen, doff) ||
       
  2234          !checkTxnObj(txnobj, &txn) )
       
  2235     {
       
  2236         FREE_DBT(key);
       
  2237         return NULL;
       
  2238     }
       
  2239 
       
  2240     if (-1 == _DB_put(self, txn, &key, &data, flags)) {
       
  2241         FREE_DBT(key);
       
  2242         return NULL;
       
  2243     }
       
  2244 
       
  2245     if (flags & DB_APPEND)
       
  2246         retval = NUMBER_FromLong(*((db_recno_t*)key.data));
       
  2247     else {
       
  2248         retval = Py_None;
       
  2249         Py_INCREF(retval);
       
  2250     }
       
  2251     FREE_DBT(key);
       
  2252     return retval;
       
  2253 }
       
  2254 
       
  2255 
       
  2256 
       
  2257 static PyObject*
       
  2258 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2259 {
       
  2260     char* filename;
       
  2261     char* database = NULL;
       
  2262     int err, flags=0;
       
  2263     static char* kwnames[] = { "filename", "dbname", "flags", NULL};
       
  2264 
       
  2265     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
       
  2266                                      &filename, &database, &flags))
       
  2267         return NULL;
       
  2268     CHECK_DB_NOT_CLOSED(self);
       
  2269 
       
  2270     EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
       
  2271 
       
  2272     MYDB_BEGIN_ALLOW_THREADS;
       
  2273     err = self->db->remove(self->db, filename, database, flags);
       
  2274     MYDB_END_ALLOW_THREADS;
       
  2275 
       
  2276     self->db = NULL;
       
  2277     RETURN_IF_ERR();
       
  2278     RETURN_NONE();
       
  2279 }
       
  2280 
       
  2281 
       
  2282 
       
  2283 static PyObject*
       
  2284 DB_rename(DBObject* self, PyObject* args)
       
  2285 {
       
  2286     char* filename;
       
  2287     char* database;
       
  2288     char* newname;
       
  2289     int err, flags=0;
       
  2290 
       
  2291     if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
       
  2292                           &flags))
       
  2293         return NULL;
       
  2294     CHECK_DB_NOT_CLOSED(self);
       
  2295 
       
  2296     MYDB_BEGIN_ALLOW_THREADS;
       
  2297     err = self->db->rename(self->db, filename, database, newname, flags);
       
  2298     MYDB_END_ALLOW_THREADS;
       
  2299     RETURN_IF_ERR();
       
  2300     RETURN_NONE();
       
  2301 }
       
  2302 
       
  2303 
       
  2304 static PyObject*
       
  2305 DB_get_private(DBObject* self)
       
  2306 {
       
  2307     /* We can give out the private field even if db is closed */
       
  2308     Py_INCREF(self->private_obj);
       
  2309     return self->private_obj;
       
  2310 }
       
  2311 
       
  2312 static PyObject*
       
  2313 DB_set_private(DBObject* self, PyObject* private_obj)
       
  2314 {
       
  2315     /* We can set the private field even if db is closed */
       
  2316     Py_DECREF(self->private_obj);
       
  2317     Py_INCREF(private_obj);
       
  2318     self->private_obj = private_obj;
       
  2319     RETURN_NONE();
       
  2320 }
       
  2321 
       
  2322 
       
  2323 static PyObject*
       
  2324 DB_set_bt_minkey(DBObject* self, PyObject* args)
       
  2325 {
       
  2326     int err, minkey;
       
  2327 
       
  2328     if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
       
  2329         return NULL;
       
  2330     CHECK_DB_NOT_CLOSED(self);
       
  2331 
       
  2332     MYDB_BEGIN_ALLOW_THREADS;
       
  2333     err = self->db->set_bt_minkey(self->db, minkey);
       
  2334     MYDB_END_ALLOW_THREADS;
       
  2335     RETURN_IF_ERR();
       
  2336     RETURN_NONE();
       
  2337 }
       
  2338 
       
  2339 static int
       
  2340 _default_cmp(const DBT *leftKey,
       
  2341 	     const DBT *rightKey)
       
  2342 {
       
  2343   int res;
       
  2344   int lsize = leftKey->size, rsize = rightKey->size;
       
  2345 
       
  2346   res = memcmp(leftKey->data, rightKey->data,
       
  2347 	       lsize < rsize ? lsize : rsize);
       
  2348 
       
  2349   if (res == 0) {
       
  2350       if (lsize < rsize) {
       
  2351 	  res = -1;
       
  2352       }
       
  2353       else if (lsize > rsize) {
       
  2354 	  res = 1;
       
  2355       }
       
  2356   }
       
  2357   return res;
       
  2358 }
       
  2359 
       
  2360 static int
       
  2361 _db_compareCallback(DB* db,
       
  2362 		    const DBT *leftKey,
       
  2363 		    const DBT *rightKey)
       
  2364 {
       
  2365     int res = 0;
       
  2366     PyObject *args;
       
  2367     PyObject *result = NULL;
       
  2368     DBObject *self = (DBObject *)db->app_private;
       
  2369 
       
  2370     if (self == NULL || self->btCompareCallback == NULL) {
       
  2371 	MYDB_BEGIN_BLOCK_THREADS;
       
  2372 	PyErr_SetString(PyExc_TypeError,
       
  2373 			(self == 0
       
  2374 			 ? "DB_bt_compare db is NULL."
       
  2375 			 : "DB_bt_compare callback is NULL."));
       
  2376 	/* we're in a callback within the DB code, we can't raise */
       
  2377 	PyErr_Print();
       
  2378 	res = _default_cmp(leftKey, rightKey);
       
  2379 	MYDB_END_BLOCK_THREADS;
       
  2380     } else {
       
  2381 	MYDB_BEGIN_BLOCK_THREADS;
       
  2382 
       
  2383 	args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
       
  2384 	if (args != NULL) {
       
  2385 		/* XXX(twouters) I highly doubt this INCREF is correct */
       
  2386 		Py_INCREF(self);
       
  2387 		result = PyEval_CallObject(self->btCompareCallback, args);
       
  2388 	}
       
  2389 	if (args == NULL || result == NULL) {
       
  2390 	    /* we're in a callback within the DB code, we can't raise */
       
  2391 	    PyErr_Print();
       
  2392 	    res = _default_cmp(leftKey, rightKey);
       
  2393 	} else if (NUMBER_Check(result)) {
       
  2394 	    res = NUMBER_AsLong(result);
       
  2395 	} else {
       
  2396 	    PyErr_SetString(PyExc_TypeError,
       
  2397 			    "DB_bt_compare callback MUST return an int.");
       
  2398 	    /* we're in a callback within the DB code, we can't raise */
       
  2399 	    PyErr_Print();
       
  2400 	    res = _default_cmp(leftKey, rightKey);
       
  2401 	}
       
  2402 
       
  2403 	Py_XDECREF(args);
       
  2404 	Py_XDECREF(result);
       
  2405 
       
  2406 	MYDB_END_BLOCK_THREADS;
       
  2407     }
       
  2408     return res;
       
  2409 }
       
  2410 
       
  2411 static PyObject*
       
  2412 DB_set_bt_compare(DBObject* self, PyObject* comparator)
       
  2413 {
       
  2414     int err;
       
  2415     PyObject *tuple, *result;
       
  2416 
       
  2417     CHECK_DB_NOT_CLOSED(self);
       
  2418 
       
  2419     if (!PyCallable_Check(comparator)) {
       
  2420 	makeTypeError("Callable", comparator);
       
  2421 	return NULL;
       
  2422     }
       
  2423 
       
  2424     /*
       
  2425      * Perform a test call of the comparator function with two empty
       
  2426      * string objects here.  verify that it returns an int (0).
       
  2427      * err if not.
       
  2428      */
       
  2429     tuple = Py_BuildValue("(ss)", "", "");
       
  2430     result = PyEval_CallObject(comparator, tuple);
       
  2431     Py_DECREF(tuple);
       
  2432     if (result == NULL)
       
  2433         return NULL;
       
  2434     if (!NUMBER_Check(result)) {
       
  2435 	PyErr_SetString(PyExc_TypeError,
       
  2436 		        "callback MUST return an int");
       
  2437 	return NULL;
       
  2438     } else if (NUMBER_AsLong(result) != 0) {
       
  2439 	PyErr_SetString(PyExc_TypeError,
       
  2440 		        "callback failed to return 0 on two empty strings");
       
  2441 	return NULL;
       
  2442     }
       
  2443     Py_DECREF(result);
       
  2444 
       
  2445     /* We don't accept multiple set_bt_compare operations, in order to
       
  2446      * simplify the code. This would have no real use, as one cannot
       
  2447      * change the function once the db is opened anyway */
       
  2448     if (self->btCompareCallback != NULL) {
       
  2449 	PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
       
  2450 	return NULL;
       
  2451     }
       
  2452 
       
  2453     Py_INCREF(comparator);
       
  2454     self->btCompareCallback = comparator;
       
  2455 
       
  2456     /* This is to workaround a problem with un-initialized threads (see
       
  2457        comment in DB_associate) */
       
  2458 #ifdef WITH_THREAD
       
  2459     PyEval_InitThreads();
       
  2460 #endif
       
  2461 
       
  2462     err = self->db->set_bt_compare(self->db, _db_compareCallback);
       
  2463 
       
  2464     if (err) {
       
  2465 	/* restore the old state in case of error */
       
  2466 	Py_DECREF(comparator);
       
  2467 	self->btCompareCallback = NULL;
       
  2468     }
       
  2469 
       
  2470     RETURN_IF_ERR();
       
  2471     RETURN_NONE();
       
  2472 }
       
  2473 
       
  2474 
       
  2475 static PyObject*
       
  2476 DB_set_cachesize(DBObject* self, PyObject* args)
       
  2477 {
       
  2478     int err;
       
  2479     int gbytes = 0, bytes = 0, ncache = 0;
       
  2480 
       
  2481     if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
       
  2482                           &gbytes,&bytes,&ncache))
       
  2483         return NULL;
       
  2484     CHECK_DB_NOT_CLOSED(self);
       
  2485 
       
  2486     MYDB_BEGIN_ALLOW_THREADS;
       
  2487     err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
       
  2488     MYDB_END_ALLOW_THREADS;
       
  2489     RETURN_IF_ERR();
       
  2490     RETURN_NONE();
       
  2491 }
       
  2492 
       
  2493 
       
  2494 static PyObject*
       
  2495 DB_set_flags(DBObject* self, PyObject* args)
       
  2496 {
       
  2497     int err, flags;
       
  2498 
       
  2499     if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
       
  2500         return NULL;
       
  2501     CHECK_DB_NOT_CLOSED(self);
       
  2502 
       
  2503     MYDB_BEGIN_ALLOW_THREADS;
       
  2504     err = self->db->set_flags(self->db, flags);
       
  2505     MYDB_END_ALLOW_THREADS;
       
  2506     RETURN_IF_ERR();
       
  2507 
       
  2508     self->setflags |= flags;
       
  2509     RETURN_NONE();
       
  2510 }
       
  2511 
       
  2512 
       
  2513 static PyObject*
       
  2514 DB_set_h_ffactor(DBObject* self, PyObject* args)
       
  2515 {
       
  2516     int err, ffactor;
       
  2517 
       
  2518     if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
       
  2519         return NULL;
       
  2520     CHECK_DB_NOT_CLOSED(self);
       
  2521 
       
  2522     MYDB_BEGIN_ALLOW_THREADS;
       
  2523     err = self->db->set_h_ffactor(self->db, ffactor);
       
  2524     MYDB_END_ALLOW_THREADS;
       
  2525     RETURN_IF_ERR();
       
  2526     RETURN_NONE();
       
  2527 }
       
  2528 
       
  2529 
       
  2530 static PyObject*
       
  2531 DB_set_h_nelem(DBObject* self, PyObject* args)
       
  2532 {
       
  2533     int err, nelem;
       
  2534 
       
  2535     if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
       
  2536         return NULL;
       
  2537     CHECK_DB_NOT_CLOSED(self);
       
  2538 
       
  2539     MYDB_BEGIN_ALLOW_THREADS;
       
  2540     err = self->db->set_h_nelem(self->db, nelem);
       
  2541     MYDB_END_ALLOW_THREADS;
       
  2542     RETURN_IF_ERR();
       
  2543     RETURN_NONE();
       
  2544 }
       
  2545 
       
  2546 
       
  2547 static PyObject*
       
  2548 DB_set_lorder(DBObject* self, PyObject* args)
       
  2549 {
       
  2550     int err, lorder;
       
  2551 
       
  2552     if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
       
  2553         return NULL;
       
  2554     CHECK_DB_NOT_CLOSED(self);
       
  2555 
       
  2556     MYDB_BEGIN_ALLOW_THREADS;
       
  2557     err = self->db->set_lorder(self->db, lorder);
       
  2558     MYDB_END_ALLOW_THREADS;
       
  2559     RETURN_IF_ERR();
       
  2560     RETURN_NONE();
       
  2561 }
       
  2562 
       
  2563 
       
  2564 static PyObject*
       
  2565 DB_set_pagesize(DBObject* self, PyObject* args)
       
  2566 {
       
  2567     int err, pagesize;
       
  2568 
       
  2569     if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
       
  2570         return NULL;
       
  2571     CHECK_DB_NOT_CLOSED(self);
       
  2572 
       
  2573     MYDB_BEGIN_ALLOW_THREADS;
       
  2574     err = self->db->set_pagesize(self->db, pagesize);
       
  2575     MYDB_END_ALLOW_THREADS;
       
  2576     RETURN_IF_ERR();
       
  2577     RETURN_NONE();
       
  2578 }
       
  2579 
       
  2580 
       
  2581 static PyObject*
       
  2582 DB_set_re_delim(DBObject* self, PyObject* args)
       
  2583 {
       
  2584     int err;
       
  2585     char delim;
       
  2586 
       
  2587     if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
       
  2588         PyErr_Clear();
       
  2589         if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
       
  2590             return NULL;
       
  2591     }
       
  2592 
       
  2593     CHECK_DB_NOT_CLOSED(self);
       
  2594 
       
  2595     MYDB_BEGIN_ALLOW_THREADS;
       
  2596     err = self->db->set_re_delim(self->db, delim);
       
  2597     MYDB_END_ALLOW_THREADS;
       
  2598     RETURN_IF_ERR();
       
  2599     RETURN_NONE();
       
  2600 }
       
  2601 
       
  2602 static PyObject*
       
  2603 DB_set_re_len(DBObject* self, PyObject* args)
       
  2604 {
       
  2605     int err, len;
       
  2606 
       
  2607     if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
       
  2608         return NULL;
       
  2609     CHECK_DB_NOT_CLOSED(self);
       
  2610 
       
  2611     MYDB_BEGIN_ALLOW_THREADS;
       
  2612     err = self->db->set_re_len(self->db, len);
       
  2613     MYDB_END_ALLOW_THREADS;
       
  2614     RETURN_IF_ERR();
       
  2615     RETURN_NONE();
       
  2616 }
       
  2617 
       
  2618 
       
  2619 static PyObject*
       
  2620 DB_set_re_pad(DBObject* self, PyObject* args)
       
  2621 {
       
  2622     int err;
       
  2623     char pad;
       
  2624 
       
  2625     if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
       
  2626         PyErr_Clear();
       
  2627         if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
       
  2628             return NULL;
       
  2629     }
       
  2630     CHECK_DB_NOT_CLOSED(self);
       
  2631 
       
  2632     MYDB_BEGIN_ALLOW_THREADS;
       
  2633     err = self->db->set_re_pad(self->db, pad);
       
  2634     MYDB_END_ALLOW_THREADS;
       
  2635     RETURN_IF_ERR();
       
  2636     RETURN_NONE();
       
  2637 }
       
  2638 
       
  2639 
       
  2640 static PyObject*
       
  2641 DB_set_re_source(DBObject* self, PyObject* args)
       
  2642 {
       
  2643     int err;
       
  2644     char *re_source;
       
  2645 
       
  2646     if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
       
  2647         return NULL;
       
  2648     CHECK_DB_NOT_CLOSED(self);
       
  2649 
       
  2650     MYDB_BEGIN_ALLOW_THREADS;
       
  2651     err = self->db->set_re_source(self->db, re_source);
       
  2652     MYDB_END_ALLOW_THREADS;
       
  2653     RETURN_IF_ERR();
       
  2654     RETURN_NONE();
       
  2655 }
       
  2656 
       
  2657 
       
  2658 static PyObject*
       
  2659 DB_set_q_extentsize(DBObject* self, PyObject* args)
       
  2660 {
       
  2661     int err;
       
  2662     int extentsize;
       
  2663 
       
  2664     if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
       
  2665         return NULL;
       
  2666     CHECK_DB_NOT_CLOSED(self);
       
  2667 
       
  2668     MYDB_BEGIN_ALLOW_THREADS;
       
  2669     err = self->db->set_q_extentsize(self->db, extentsize);
       
  2670     MYDB_END_ALLOW_THREADS;
       
  2671     RETURN_IF_ERR();
       
  2672     RETURN_NONE();
       
  2673 }
       
  2674 
       
  2675 static PyObject*
       
  2676 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2677 {
       
  2678     int err, flags = 0, type;
       
  2679     void* sp;
       
  2680     PyObject* d;
       
  2681 #if (DBVER >= 43)
       
  2682     PyObject* txnobj = NULL;
       
  2683     DB_TXN *txn = NULL;
       
  2684     static char* kwnames[] = { "flags", "txn", NULL };
       
  2685 #else
       
  2686     static char* kwnames[] = { "flags", NULL };
       
  2687 #endif
       
  2688 
       
  2689 #if (DBVER >= 43)
       
  2690     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
       
  2691                                      &flags, &txnobj))
       
  2692         return NULL;
       
  2693     if (!checkTxnObj(txnobj, &txn))
       
  2694         return NULL;
       
  2695 #else
       
  2696     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
       
  2697         return NULL;
       
  2698 #endif
       
  2699     CHECK_DB_NOT_CLOSED(self);
       
  2700 
       
  2701     MYDB_BEGIN_ALLOW_THREADS;
       
  2702 #if (DBVER >= 43)
       
  2703     err = self->db->stat(self->db, txn, &sp, flags);
       
  2704 #else
       
  2705     err = self->db->stat(self->db, &sp, flags);
       
  2706 #endif
       
  2707     MYDB_END_ALLOW_THREADS;
       
  2708     RETURN_IF_ERR();
       
  2709 
       
  2710     self->haveStat = 1;
       
  2711 
       
  2712     /* Turn the stat structure into a dictionary */
       
  2713     type = _DB_get_type(self);
       
  2714     if ((type == -1) || ((d = PyDict_New()) == NULL)) {
       
  2715         free(sp);
       
  2716         return NULL;
       
  2717     }
       
  2718 
       
  2719 #define MAKE_HASH_ENTRY(name)  _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
       
  2720 #define MAKE_BT_ENTRY(name)    _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
       
  2721 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
       
  2722 
       
  2723     switch (type) {
       
  2724     case DB_HASH:
       
  2725         MAKE_HASH_ENTRY(magic);
       
  2726         MAKE_HASH_ENTRY(version);
       
  2727         MAKE_HASH_ENTRY(nkeys);
       
  2728         MAKE_HASH_ENTRY(ndata);
       
  2729 #if (DBVER >= 46)
       
  2730         MAKE_HASH_ENTRY(pagecnt);
       
  2731 #endif
       
  2732         MAKE_HASH_ENTRY(pagesize);
       
  2733 #if (DBVER < 41)
       
  2734         MAKE_HASH_ENTRY(nelem);
       
  2735 #endif
       
  2736         MAKE_HASH_ENTRY(ffactor);
       
  2737         MAKE_HASH_ENTRY(buckets);
       
  2738         MAKE_HASH_ENTRY(free);
       
  2739         MAKE_HASH_ENTRY(bfree);
       
  2740         MAKE_HASH_ENTRY(bigpages);
       
  2741         MAKE_HASH_ENTRY(big_bfree);
       
  2742         MAKE_HASH_ENTRY(overflows);
       
  2743         MAKE_HASH_ENTRY(ovfl_free);
       
  2744         MAKE_HASH_ENTRY(dup);
       
  2745         MAKE_HASH_ENTRY(dup_free);
       
  2746         break;
       
  2747 
       
  2748     case DB_BTREE:
       
  2749     case DB_RECNO:
       
  2750         MAKE_BT_ENTRY(magic);
       
  2751         MAKE_BT_ENTRY(version);
       
  2752         MAKE_BT_ENTRY(nkeys);
       
  2753         MAKE_BT_ENTRY(ndata);
       
  2754 #if (DBVER >= 46)
       
  2755         MAKE_BT_ENTRY(pagecnt);
       
  2756 #endif
       
  2757         MAKE_BT_ENTRY(pagesize);
       
  2758         MAKE_BT_ENTRY(minkey);
       
  2759         MAKE_BT_ENTRY(re_len);
       
  2760         MAKE_BT_ENTRY(re_pad);
       
  2761         MAKE_BT_ENTRY(levels);
       
  2762         MAKE_BT_ENTRY(int_pg);
       
  2763         MAKE_BT_ENTRY(leaf_pg);
       
  2764         MAKE_BT_ENTRY(dup_pg);
       
  2765         MAKE_BT_ENTRY(over_pg);
       
  2766 #if (DBVER >= 43)
       
  2767         MAKE_BT_ENTRY(empty_pg);
       
  2768 #endif
       
  2769         MAKE_BT_ENTRY(free);
       
  2770         MAKE_BT_ENTRY(int_pgfree);
       
  2771         MAKE_BT_ENTRY(leaf_pgfree);
       
  2772         MAKE_BT_ENTRY(dup_pgfree);
       
  2773         MAKE_BT_ENTRY(over_pgfree);
       
  2774         break;
       
  2775 
       
  2776     case DB_QUEUE:
       
  2777         MAKE_QUEUE_ENTRY(magic);
       
  2778         MAKE_QUEUE_ENTRY(version);
       
  2779         MAKE_QUEUE_ENTRY(nkeys);
       
  2780         MAKE_QUEUE_ENTRY(ndata);
       
  2781         MAKE_QUEUE_ENTRY(pagesize);
       
  2782 #if (DBVER >= 41)
       
  2783         MAKE_QUEUE_ENTRY(extentsize);
       
  2784 #endif
       
  2785         MAKE_QUEUE_ENTRY(pages);
       
  2786         MAKE_QUEUE_ENTRY(re_len);
       
  2787         MAKE_QUEUE_ENTRY(re_pad);
       
  2788         MAKE_QUEUE_ENTRY(pgfree);
       
  2789 #if (DBVER == 31)
       
  2790         MAKE_QUEUE_ENTRY(start);
       
  2791 #endif
       
  2792         MAKE_QUEUE_ENTRY(first_recno);
       
  2793         MAKE_QUEUE_ENTRY(cur_recno);
       
  2794         break;
       
  2795 
       
  2796     default:
       
  2797         PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
       
  2798         Py_DECREF(d);
       
  2799         d = NULL;
       
  2800     }
       
  2801 
       
  2802 #undef MAKE_HASH_ENTRY
       
  2803 #undef MAKE_BT_ENTRY
       
  2804 #undef MAKE_QUEUE_ENTRY
       
  2805 
       
  2806     free(sp);
       
  2807     return d;
       
  2808 }
       
  2809 
       
  2810 static PyObject*
       
  2811 DB_sync(DBObject* self, PyObject* args)
       
  2812 {
       
  2813     int err;
       
  2814     int flags = 0;
       
  2815 
       
  2816     if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
       
  2817         return NULL;
       
  2818     CHECK_DB_NOT_CLOSED(self);
       
  2819 
       
  2820     MYDB_BEGIN_ALLOW_THREADS;
       
  2821     err = self->db->sync(self->db, flags);
       
  2822     MYDB_END_ALLOW_THREADS;
       
  2823     RETURN_IF_ERR();
       
  2824     RETURN_NONE();
       
  2825 }
       
  2826 
       
  2827 
       
  2828 static PyObject*
       
  2829 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2830 {
       
  2831     int err, flags=0;
       
  2832     u_int32_t count=0;
       
  2833     PyObject* txnobj = NULL;
       
  2834     DB_TXN *txn = NULL;
       
  2835     static char* kwnames[] = { "txn", "flags", NULL };
       
  2836 
       
  2837     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
       
  2838                                      &txnobj, &flags))
       
  2839         return NULL;
       
  2840     CHECK_DB_NOT_CLOSED(self);
       
  2841     if (!checkTxnObj(txnobj, &txn))
       
  2842         return NULL;
       
  2843 
       
  2844     MYDB_BEGIN_ALLOW_THREADS;
       
  2845     err = self->db->truncate(self->db, txn, &count, flags);
       
  2846     MYDB_END_ALLOW_THREADS;
       
  2847     RETURN_IF_ERR();
       
  2848     return NUMBER_FromLong(count);
       
  2849 }
       
  2850 
       
  2851 
       
  2852 static PyObject*
       
  2853 DB_upgrade(DBObject* self, PyObject* args)
       
  2854 {
       
  2855     int err, flags=0;
       
  2856     char *filename;
       
  2857 
       
  2858     if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
       
  2859         return NULL;
       
  2860     CHECK_DB_NOT_CLOSED(self);
       
  2861 
       
  2862     MYDB_BEGIN_ALLOW_THREADS;
       
  2863     err = self->db->upgrade(self->db, filename, flags);
       
  2864     MYDB_END_ALLOW_THREADS;
       
  2865     RETURN_IF_ERR();
       
  2866     RETURN_NONE();
       
  2867 }
       
  2868 
       
  2869 
       
  2870 static PyObject*
       
  2871 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2872 {
       
  2873     int err, flags=0;
       
  2874     char* fileName;
       
  2875     char* dbName=NULL;
       
  2876     char* outFileName=NULL;
       
  2877     FILE* outFile=NULL;
       
  2878     static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
       
  2879                                      NULL };
       
  2880 
       
  2881     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
       
  2882                                      &fileName, &dbName, &outFileName, &flags))
       
  2883         return NULL;
       
  2884 
       
  2885     CHECK_DB_NOT_CLOSED(self);
       
  2886     if (outFileName)
       
  2887         outFile = fopen(outFileName, "w");
       
  2888 	/* XXX(nnorwitz): it should probably be an exception if outFile
       
  2889 	   can't be opened. */
       
  2890 
       
  2891     {  /* DB.verify acts as a DB handle destructor (like close) */
       
  2892         PyObject *error;
       
  2893 
       
  2894         error=DB_close_internal(self, 0, 1);
       
  2895         if (error ) {
       
  2896           return error;
       
  2897         }
       
  2898      }
       
  2899 
       
  2900     MYDB_BEGIN_ALLOW_THREADS;
       
  2901     err = self->db->verify(self->db, fileName, dbName, outFile, flags);
       
  2902     MYDB_END_ALLOW_THREADS;
       
  2903 
       
  2904     self->db = NULL;  /* Implicit close; related objects already released */
       
  2905 
       
  2906     if (outFile)
       
  2907         fclose(outFile);
       
  2908 
       
  2909     RETURN_IF_ERR();
       
  2910     RETURN_NONE();
       
  2911 }
       
  2912 
       
  2913 
       
  2914 static PyObject*
       
  2915 DB_set_get_returns_none(DBObject* self, PyObject* args)
       
  2916 {
       
  2917     int flags=0;
       
  2918     int oldValue=0;
       
  2919 
       
  2920     if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
       
  2921         return NULL;
       
  2922     CHECK_DB_NOT_CLOSED(self);
       
  2923 
       
  2924     if (self->moduleFlags.getReturnsNone)
       
  2925         ++oldValue;
       
  2926     if (self->moduleFlags.cursorSetReturnsNone)
       
  2927         ++oldValue;
       
  2928     self->moduleFlags.getReturnsNone = (flags >= 1);
       
  2929     self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
       
  2930     return NUMBER_FromLong(oldValue);
       
  2931 }
       
  2932 
       
  2933 #if (DBVER >= 41)
       
  2934 static PyObject*
       
  2935 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
       
  2936 {
       
  2937     int err;
       
  2938     u_int32_t flags=0;
       
  2939     char *passwd = NULL;
       
  2940     static char* kwnames[] = { "passwd", "flags", NULL };
       
  2941 
       
  2942     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
       
  2943 		&passwd, &flags)) {
       
  2944 	return NULL;
       
  2945     }
       
  2946 
       
  2947     MYDB_BEGIN_ALLOW_THREADS;
       
  2948     err = self->db->set_encrypt(self->db, passwd, flags);
       
  2949     MYDB_END_ALLOW_THREADS;
       
  2950 
       
  2951     RETURN_IF_ERR();
       
  2952     RETURN_NONE();
       
  2953 }
       
  2954 #endif /* DBVER >= 41 */
       
  2955 
       
  2956 
       
  2957 /*-------------------------------------------------------------- */
       
  2958 /* Mapping and Dictionary-like access routines */
       
  2959 
       
  2960 Py_ssize_t DB_length(PyObject* _self)
       
  2961 {
       
  2962     int err;
       
  2963     Py_ssize_t size = 0;
       
  2964     int flags = 0;
       
  2965     void* sp;
       
  2966     DBObject* self = (DBObject*)_self;
       
  2967 
       
  2968     if (self->db == NULL) {
       
  2969         PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
       
  2970         if (t) {
       
  2971             PyErr_SetObject(DBError, t);
       
  2972             Py_DECREF(t);
       
  2973         }
       
  2974         return -1;
       
  2975     }
       
  2976 
       
  2977     if (self->haveStat) {  /* Has the stat function been called recently?  If
       
  2978                               so, we can use the cached value. */
       
  2979         flags = DB_FAST_STAT;
       
  2980     }
       
  2981 
       
  2982     MYDB_BEGIN_ALLOW_THREADS;
       
  2983 redo_stat_for_length:
       
  2984 #if (DBVER >= 43)
       
  2985     err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
       
  2986 #else
       
  2987     err = self->db->stat(self->db, &sp, flags);
       
  2988 #endif
       
  2989 
       
  2990     /* All the stat structures have matching fields upto the ndata field,
       
  2991        so we can use any of them for the type cast */
       
  2992     size = ((DB_BTREE_STAT*)sp)->bt_ndata;
       
  2993 
       
  2994     /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
       
  2995      * redo a full stat to make sure.
       
  2996      *   Fixes SF python bug 1493322, pybsddb bug 1184012
       
  2997      */
       
  2998     if (size == 0 && (flags & DB_FAST_STAT)) {
       
  2999         flags = 0;
       
  3000         if (!err)
       
  3001             free(sp);
       
  3002         goto redo_stat_for_length;
       
  3003     }
       
  3004 
       
  3005     MYDB_END_ALLOW_THREADS;
       
  3006 
       
  3007     if (err)
       
  3008         return -1;
       
  3009 
       
  3010     self->haveStat = 1;
       
  3011 
       
  3012     free(sp);
       
  3013     return size;
       
  3014 }
       
  3015 
       
  3016 
       
  3017 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
       
  3018 {
       
  3019     int err;
       
  3020     PyObject* retval;
       
  3021     DBT key;
       
  3022     DBT data;
       
  3023 
       
  3024     CHECK_DB_NOT_CLOSED(self);
       
  3025     if (!make_key_dbt(self, keyobj, &key, NULL))
       
  3026         return NULL;
       
  3027 
       
  3028     CLEAR_DBT(data);
       
  3029     if (CHECK_DBFLAG(self, DB_THREAD)) {
       
  3030         /* Tell Berkeley DB to malloc the return value (thread safe) */
       
  3031         data.flags = DB_DBT_MALLOC;
       
  3032     }
       
  3033     MYDB_BEGIN_ALLOW_THREADS;
       
  3034     err = self->db->get(self->db, NULL, &key, &data, 0);
       
  3035     MYDB_END_ALLOW_THREADS;
       
  3036     if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
       
  3037         PyErr_SetObject(PyExc_KeyError, keyobj);
       
  3038         retval = NULL;
       
  3039     }
       
  3040     else if (makeDBError(err)) {
       
  3041         retval = NULL;
       
  3042     }
       
  3043     else {
       
  3044         retval = Build_PyString(data.data, data.size);
       
  3045         FREE_DBT(data);
       
  3046     }
       
  3047 
       
  3048     FREE_DBT(key);
       
  3049     return retval;
       
  3050 }
       
  3051 
       
  3052 
       
  3053 static int
       
  3054 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
       
  3055 {
       
  3056     DBT key, data;
       
  3057     int retval;
       
  3058     int flags = 0;
       
  3059 
       
  3060     if (self->db == NULL) {
       
  3061         PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
       
  3062         if (t) {
       
  3063             PyErr_SetObject(DBError, t);
       
  3064             Py_DECREF(t);
       
  3065         }
       
  3066         return -1;
       
  3067     }
       
  3068 
       
  3069     if (!make_key_dbt(self, keyobj, &key, NULL))
       
  3070         return -1;
       
  3071 
       
  3072     if (dataobj != NULL) {
       
  3073         if (!make_dbt(dataobj, &data))
       
  3074             retval =  -1;
       
  3075         else {
       
  3076             if (self->setflags & (DB_DUP|DB_DUPSORT))
       
  3077                 /* dictionaries shouldn't have duplicate keys */
       
  3078                 flags = DB_NOOVERWRITE;
       
  3079             retval = _DB_put(self, NULL, &key, &data, flags);
       
  3080 
       
  3081             if ((retval == -1) &&  (self->setflags & (DB_DUP|DB_DUPSORT))) {
       
  3082                 /* try deleting any old record that matches and then PUT it
       
  3083                  * again... */
       
  3084                 _DB_delete(self, NULL, &key, 0);
       
  3085                 PyErr_Clear();
       
  3086                 retval = _DB_put(self, NULL, &key, &data, flags);
       
  3087             }
       
  3088         }
       
  3089     }
       
  3090     else {
       
  3091         /* dataobj == NULL, so delete the key */
       
  3092         retval = _DB_delete(self, NULL, &key, 0);
       
  3093     }
       
  3094     FREE_DBT(key);
       
  3095     return retval;
       
  3096 }
       
  3097 
       
  3098 
       
  3099 static PyObject*
       
  3100 DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
       
  3101 {
       
  3102     int err;
       
  3103     PyObject* keyobj;
       
  3104     DBT key, data;
       
  3105     PyObject* txnobj = NULL;
       
  3106     DB_TXN *txn = NULL;
       
  3107     static char* kwnames[] = {"key","txn", NULL};
       
  3108 
       
  3109     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
       
  3110                 &keyobj, &txnobj))
       
  3111         return NULL;
       
  3112 
       
  3113     CHECK_DB_NOT_CLOSED(self);
       
  3114     if (!make_key_dbt(self, keyobj, &key, NULL))
       
  3115         return NULL;
       
  3116     if (!checkTxnObj(txnobj, &txn)) {
       
  3117         FREE_DBT(key);
       
  3118         return NULL;
       
  3119     }
       
  3120 
       
  3121     /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
       
  3122        it has a record but can't allocate a buffer for the data.  This saves
       
  3123        having to deal with data we won't be using.
       
  3124      */
       
  3125     CLEAR_DBT(data);
       
  3126     data.flags = DB_DBT_USERMEM;
       
  3127 
       
  3128     MYDB_BEGIN_ALLOW_THREADS;
       
  3129     err = self->db->get(self->db, txn, &key, &data, 0);
       
  3130     MYDB_END_ALLOW_THREADS;
       
  3131     FREE_DBT(key);
       
  3132 
       
  3133     if (err == DB_BUFFER_SMALL || err == 0) {
       
  3134         return NUMBER_FromLong(1);
       
  3135     } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
       
  3136         return NUMBER_FromLong(0);
       
  3137     }
       
  3138 
       
  3139     makeDBError(err);
       
  3140     return NULL;
       
  3141 }
       
  3142 
       
  3143 
       
  3144 #define _KEYS_LIST      1
       
  3145 #define _VALUES_LIST    2
       
  3146 #define _ITEMS_LIST     3
       
  3147 
       
  3148 static PyObject*
       
  3149 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
       
  3150 {
       
  3151     int err, dbtype;
       
  3152     DBT key;
       
  3153     DBT data;
       
  3154     DBC *cursor;
       
  3155     PyObject* list;
       
  3156     PyObject* item = NULL;
       
  3157 
       
  3158     CHECK_DB_NOT_CLOSED(self);
       
  3159     CLEAR_DBT(key);
       
  3160     CLEAR_DBT(data);
       
  3161 
       
  3162     dbtype = _DB_get_type(self);
       
  3163     if (dbtype == -1)
       
  3164         return NULL;
       
  3165 
       
  3166     list = PyList_New(0);
       
  3167     if (list == NULL)
       
  3168         return NULL;
       
  3169 
       
  3170     /* get a cursor */
       
  3171     MYDB_BEGIN_ALLOW_THREADS;
       
  3172     err = self->db->cursor(self->db, txn, &cursor, 0);
       
  3173     MYDB_END_ALLOW_THREADS;
       
  3174     if (makeDBError(err)) {
       
  3175         Py_DECREF(list);
       
  3176         return NULL;
       
  3177     }
       
  3178 
       
  3179     while (1) { /* use the cursor to traverse the DB, collecting items */
       
  3180         MYDB_BEGIN_ALLOW_THREADS;
       
  3181         err = _DBC_get(cursor, &key, &data, DB_NEXT);
       
  3182         MYDB_END_ALLOW_THREADS;
       
  3183 
       
  3184         if (err) {
       
  3185             /* for any error, break out of the loop */
       
  3186             break;
       
  3187         }
       
  3188 
       
  3189         switch (type) {
       
  3190         case _KEYS_LIST:
       
  3191             switch(dbtype) {
       
  3192             case DB_BTREE:
       
  3193             case DB_HASH:
       
  3194             default:
       
  3195                 item = Build_PyString(key.data, key.size);
       
  3196                 break;
       
  3197             case DB_RECNO:
       
  3198             case DB_QUEUE:
       
  3199                 item = NUMBER_FromLong(*((db_recno_t*)key.data));
       
  3200                 break;
       
  3201             }
       
  3202             break;
       
  3203 
       
  3204         case _VALUES_LIST:
       
  3205             item = Build_PyString(data.data, data.size);
       
  3206             break;
       
  3207 
       
  3208         case _ITEMS_LIST:
       
  3209             switch(dbtype) {
       
  3210             case DB_BTREE:
       
  3211             case DB_HASH:
       
  3212             default:
       
  3213                 item = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  3214                 break;
       
  3215             case DB_RECNO:
       
  3216             case DB_QUEUE:
       
  3217                 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
       
  3218                 break;
       
  3219             }
       
  3220             break;
       
  3221         default:
       
  3222             PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
       
  3223             item = NULL;
       
  3224             break;
       
  3225         }
       
  3226         if (item == NULL) {
       
  3227             Py_DECREF(list);
       
  3228             list = NULL;
       
  3229             goto done;
       
  3230         }
       
  3231         if (PyList_Append(list, item)) {
       
  3232             Py_DECREF(list);
       
  3233             Py_DECREF(item);
       
  3234             list = NULL;
       
  3235             goto done;
       
  3236         }
       
  3237         Py_DECREF(item);
       
  3238     }
       
  3239 
       
  3240     /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
       
  3241     if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
       
  3242         Py_DECREF(list);
       
  3243         list = NULL;
       
  3244     }
       
  3245 
       
  3246  done:
       
  3247     MYDB_BEGIN_ALLOW_THREADS;
       
  3248     _DBC_close(cursor);
       
  3249     MYDB_END_ALLOW_THREADS;
       
  3250     return list;
       
  3251 }
       
  3252 
       
  3253 
       
  3254 static PyObject*
       
  3255 DB_keys(DBObject* self, PyObject* args)
       
  3256 {
       
  3257     PyObject* txnobj = NULL;
       
  3258     DB_TXN *txn = NULL;
       
  3259 
       
  3260     if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
       
  3261         return NULL;
       
  3262     if (!checkTxnObj(txnobj, &txn))
       
  3263         return NULL;
       
  3264     return _DB_make_list(self, txn, _KEYS_LIST);
       
  3265 }
       
  3266 
       
  3267 
       
  3268 static PyObject*
       
  3269 DB_items(DBObject* self, PyObject* args)
       
  3270 {
       
  3271     PyObject* txnobj = NULL;
       
  3272     DB_TXN *txn = NULL;
       
  3273 
       
  3274     if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
       
  3275         return NULL;
       
  3276     if (!checkTxnObj(txnobj, &txn))
       
  3277         return NULL;
       
  3278     return _DB_make_list(self, txn, _ITEMS_LIST);
       
  3279 }
       
  3280 
       
  3281 
       
  3282 static PyObject*
       
  3283 DB_values(DBObject* self, PyObject* args)
       
  3284 {
       
  3285     PyObject* txnobj = NULL;
       
  3286     DB_TXN *txn = NULL;
       
  3287 
       
  3288     if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
       
  3289         return NULL;
       
  3290     if (!checkTxnObj(txnobj, &txn))
       
  3291         return NULL;
       
  3292     return _DB_make_list(self, txn, _VALUES_LIST);
       
  3293 }
       
  3294 
       
  3295 /* --------------------------------------------------------------------- */
       
  3296 /* DBCursor methods */
       
  3297 
       
  3298 
       
  3299 static PyObject*
       
  3300 DBC_close_internal(DBCursorObject* self)
       
  3301 {
       
  3302     int err = 0;
       
  3303 
       
  3304     if (self->dbc != NULL) {
       
  3305         EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
       
  3306         if (self->txn) {
       
  3307             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
       
  3308             self->txn=NULL;
       
  3309         }
       
  3310 
       
  3311         MYDB_BEGIN_ALLOW_THREADS;
       
  3312         err = _DBC_close(self->dbc);
       
  3313         MYDB_END_ALLOW_THREADS;
       
  3314         self->dbc = NULL;
       
  3315     }
       
  3316     RETURN_IF_ERR();
       
  3317     RETURN_NONE();
       
  3318 }
       
  3319 
       
  3320 static PyObject*
       
  3321 DBC_close(DBCursorObject* self)
       
  3322 {
       
  3323     return DBC_close_internal(self);
       
  3324 }
       
  3325 
       
  3326 
       
  3327 static PyObject*
       
  3328 DBC_count(DBCursorObject* self, PyObject* args)
       
  3329 {
       
  3330     int err = 0;
       
  3331     db_recno_t count;
       
  3332     int flags = 0;
       
  3333 
       
  3334     if (!PyArg_ParseTuple(args, "|i:count", &flags))
       
  3335         return NULL;
       
  3336 
       
  3337     CHECK_CURSOR_NOT_CLOSED(self);
       
  3338 
       
  3339     MYDB_BEGIN_ALLOW_THREADS;
       
  3340     err = _DBC_count(self->dbc, &count, flags);
       
  3341     MYDB_END_ALLOW_THREADS;
       
  3342     RETURN_IF_ERR();
       
  3343 
       
  3344     return NUMBER_FromLong(count);
       
  3345 }
       
  3346 
       
  3347 
       
  3348 static PyObject*
       
  3349 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3350 {
       
  3351     return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
       
  3352 }
       
  3353 
       
  3354 
       
  3355 static PyObject*
       
  3356 DBC_delete(DBCursorObject* self, PyObject* args)
       
  3357 {
       
  3358     int err, flags=0;
       
  3359 
       
  3360     if (!PyArg_ParseTuple(args, "|i:delete", &flags))
       
  3361         return NULL;
       
  3362 
       
  3363     CHECK_CURSOR_NOT_CLOSED(self);
       
  3364 
       
  3365     MYDB_BEGIN_ALLOW_THREADS;
       
  3366     err = _DBC_del(self->dbc, flags);
       
  3367     MYDB_END_ALLOW_THREADS;
       
  3368     RETURN_IF_ERR();
       
  3369 
       
  3370     self->mydb->haveStat = 0;
       
  3371     RETURN_NONE();
       
  3372 }
       
  3373 
       
  3374 
       
  3375 static PyObject*
       
  3376 DBC_dup(DBCursorObject* self, PyObject* args)
       
  3377 {
       
  3378     int err, flags =0;
       
  3379     DBC* dbc = NULL;
       
  3380 
       
  3381     if (!PyArg_ParseTuple(args, "|i:dup", &flags))
       
  3382         return NULL;
       
  3383 
       
  3384     CHECK_CURSOR_NOT_CLOSED(self);
       
  3385 
       
  3386     MYDB_BEGIN_ALLOW_THREADS;
       
  3387     err = _DBC_dup(self->dbc, &dbc, flags);
       
  3388     MYDB_END_ALLOW_THREADS;
       
  3389     RETURN_IF_ERR();
       
  3390 
       
  3391     return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
       
  3392 }
       
  3393 
       
  3394 static PyObject*
       
  3395 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
       
  3396 {
       
  3397     return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
       
  3398 }
       
  3399 
       
  3400 
       
  3401 static PyObject*
       
  3402 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3403 {
       
  3404     int err, flags=0;
       
  3405     PyObject* keyobj = NULL;
       
  3406     PyObject* dataobj = NULL;
       
  3407     PyObject* retval = NULL;
       
  3408     int dlen = -1;
       
  3409     int doff = -1;
       
  3410     DBT key, data;
       
  3411     static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
       
  3412                                      NULL };
       
  3413 
       
  3414     CLEAR_DBT(key);
       
  3415     CLEAR_DBT(data);
       
  3416     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
       
  3417 				     &flags, &dlen, &doff))
       
  3418     {
       
  3419         PyErr_Clear();
       
  3420         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
       
  3421                                          &kwnames[1],
       
  3422 					 &keyobj, &flags, &dlen, &doff))
       
  3423         {
       
  3424             PyErr_Clear();
       
  3425             if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
       
  3426                                              kwnames, &keyobj, &dataobj,
       
  3427                                              &flags, &dlen, &doff))
       
  3428             {
       
  3429                 return NULL;
       
  3430 	    }
       
  3431 	}
       
  3432     }
       
  3433 
       
  3434     CHECK_CURSOR_NOT_CLOSED(self);
       
  3435 
       
  3436     if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  3437         return NULL;
       
  3438     if ( (dataobj && !make_dbt(dataobj, &data)) ||
       
  3439          (!add_partial_dbt(&data, dlen, doff)) )
       
  3440     {
       
  3441         FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
       
  3442         return NULL;
       
  3443     }
       
  3444 
       
  3445     MYDB_BEGIN_ALLOW_THREADS;
       
  3446     err = _DBC_get(self->dbc, &key, &data, flags);
       
  3447     MYDB_END_ALLOW_THREADS;
       
  3448 
       
  3449     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  3450 	    && self->mydb->moduleFlags.getReturnsNone) {
       
  3451         Py_INCREF(Py_None);
       
  3452         retval = Py_None;
       
  3453     }
       
  3454     else if (makeDBError(err)) {
       
  3455         retval = NULL;
       
  3456     }
       
  3457     else {
       
  3458         switch (_DB_get_type(self->mydb)) {
       
  3459         case -1:
       
  3460             retval = NULL;
       
  3461             break;
       
  3462         case DB_BTREE:
       
  3463         case DB_HASH:
       
  3464         default:
       
  3465             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  3466             break;
       
  3467         case DB_RECNO:
       
  3468         case DB_QUEUE:
       
  3469             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
       
  3470             break;
       
  3471         }
       
  3472     }
       
  3473     FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3474     return retval;
       
  3475 }
       
  3476 
       
  3477 static PyObject*
       
  3478 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3479 {
       
  3480     int err, flags=0;
       
  3481     PyObject* keyobj = NULL;
       
  3482     PyObject* dataobj = NULL;
       
  3483     PyObject* retval = NULL;
       
  3484     int dlen = -1;
       
  3485     int doff = -1;
       
  3486     DBT key, pkey, data;
       
  3487     static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
       
  3488     static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
       
  3489 
       
  3490     CLEAR_DBT(key);
       
  3491     CLEAR_DBT(data);
       
  3492     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
       
  3493 				     &flags, &dlen, &doff))
       
  3494     {
       
  3495         PyErr_Clear();
       
  3496         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
       
  3497                                          kwnames_keyOnly, 
       
  3498 					 &keyobj, &flags, &dlen, &doff))
       
  3499         {
       
  3500             PyErr_Clear();
       
  3501             if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
       
  3502                                              kwnames, &keyobj, &dataobj,
       
  3503                                              &flags, &dlen, &doff))
       
  3504             {
       
  3505                 return NULL;
       
  3506 	    }
       
  3507 	}
       
  3508     }
       
  3509 
       
  3510     CHECK_CURSOR_NOT_CLOSED(self);
       
  3511 
       
  3512     if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  3513         return NULL;
       
  3514     if ( (dataobj && !make_dbt(dataobj, &data)) ||
       
  3515          (!add_partial_dbt(&data, dlen, doff)) ) {
       
  3516         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3517         return NULL;
       
  3518     }
       
  3519 
       
  3520     CLEAR_DBT(pkey);
       
  3521     pkey.flags = DB_DBT_MALLOC;
       
  3522 
       
  3523     MYDB_BEGIN_ALLOW_THREADS;
       
  3524     err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
       
  3525     MYDB_END_ALLOW_THREADS;
       
  3526 
       
  3527     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  3528 	    && self->mydb->moduleFlags.getReturnsNone) {
       
  3529         Py_INCREF(Py_None);
       
  3530         retval = Py_None;
       
  3531     }
       
  3532     else if (makeDBError(err)) {
       
  3533         retval = NULL;
       
  3534     }
       
  3535     else {
       
  3536         PyObject *pkeyObj;
       
  3537         PyObject *dataObj;
       
  3538         dataObj = Build_PyString(data.data, data.size);
       
  3539 
       
  3540         if (self->mydb->primaryDBType == DB_RECNO ||
       
  3541             self->mydb->primaryDBType == DB_QUEUE)
       
  3542             pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
       
  3543         else
       
  3544             pkeyObj = Build_PyString(pkey.data, pkey.size);
       
  3545 
       
  3546         if (key.data && key.size) /* return key, pkey and data */
       
  3547         {
       
  3548             PyObject *keyObj;
       
  3549             int type = _DB_get_type(self->mydb);
       
  3550             if (type == DB_RECNO || type == DB_QUEUE)
       
  3551                 keyObj = NUMBER_FromLong(*(int *)key.data);
       
  3552             else
       
  3553                 keyObj = Build_PyString(key.data, key.size);
       
  3554 #if (PY_VERSION_HEX >= 0x02040000)
       
  3555             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
       
  3556 #else
       
  3557             retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
       
  3558 #endif
       
  3559             Py_DECREF(keyObj);
       
  3560             FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3561         }
       
  3562         else /* return just the pkey and data */
       
  3563         {
       
  3564 #if (PY_VERSION_HEX >= 0x02040000)
       
  3565             retval = PyTuple_Pack(2, pkeyObj, dataObj);
       
  3566 #else
       
  3567             retval = Py_BuildValue("OO", pkeyObj, dataObj);
       
  3568 #endif
       
  3569         }
       
  3570         Py_DECREF(dataObj);
       
  3571         Py_DECREF(pkeyObj);
       
  3572         FREE_DBT(pkey);
       
  3573     }
       
  3574     /* the only time REALLOC should be set is if we used an integer
       
  3575      * key that make_key_dbt malloc'd for us.  always free these. */
       
  3576     if (key.flags & DB_DBT_REALLOC) {  /* 'make_key_dbt' could do a 'malloc' */
       
  3577         FREE_DBT(key);
       
  3578     }
       
  3579     return retval;
       
  3580 }
       
  3581 
       
  3582 
       
  3583 static PyObject*
       
  3584 DBC_get_recno(DBCursorObject* self)
       
  3585 {
       
  3586     int err;
       
  3587     db_recno_t recno;
       
  3588     DBT key;
       
  3589     DBT data;
       
  3590 
       
  3591     CHECK_CURSOR_NOT_CLOSED(self);
       
  3592 
       
  3593     CLEAR_DBT(key);
       
  3594     CLEAR_DBT(data);
       
  3595 
       
  3596     MYDB_BEGIN_ALLOW_THREADS;
       
  3597     err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
       
  3598     MYDB_END_ALLOW_THREADS;
       
  3599     RETURN_IF_ERR();
       
  3600 
       
  3601     recno = *((db_recno_t*)data.data);
       
  3602     return NUMBER_FromLong(recno);
       
  3603 }
       
  3604 
       
  3605 
       
  3606 static PyObject*
       
  3607 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3608 {
       
  3609     return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
       
  3610 }
       
  3611 
       
  3612 
       
  3613 static PyObject*
       
  3614 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3615 {
       
  3616     return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
       
  3617 }
       
  3618 
       
  3619 
       
  3620 static PyObject*
       
  3621 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3622 {
       
  3623     return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
       
  3624 }
       
  3625 
       
  3626 
       
  3627 static PyObject*
       
  3628 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
       
  3629 {
       
  3630     int err, flags = 0;
       
  3631     PyObject* keyobj, *dataobj;
       
  3632     DBT key, data;
       
  3633     static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
       
  3634                                      NULL };
       
  3635     int dlen = -1;
       
  3636     int doff = -1;
       
  3637 
       
  3638     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
       
  3639 				     &keyobj, &dataobj, &flags, &dlen, &doff))
       
  3640         return NULL;
       
  3641 
       
  3642     CHECK_CURSOR_NOT_CLOSED(self);
       
  3643 
       
  3644     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  3645         return NULL;
       
  3646     if (!make_dbt(dataobj, &data) ||
       
  3647         !add_partial_dbt(&data, dlen, doff) )
       
  3648     {
       
  3649         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3650         return NULL;
       
  3651     }
       
  3652 
       
  3653     MYDB_BEGIN_ALLOW_THREADS;
       
  3654     err = _DBC_put(self->dbc, &key, &data, flags);
       
  3655     MYDB_END_ALLOW_THREADS;
       
  3656     FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3657     RETURN_IF_ERR();
       
  3658     self->mydb->haveStat = 0;
       
  3659     RETURN_NONE();
       
  3660 }
       
  3661 
       
  3662 
       
  3663 static PyObject*
       
  3664 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3665 {
       
  3666     int err, flags = 0;
       
  3667     DBT key, data;
       
  3668     PyObject* retval, *keyobj;
       
  3669     static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
       
  3670     int dlen = -1;
       
  3671     int doff = -1;
       
  3672 
       
  3673     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
       
  3674 				     &keyobj, &flags, &dlen, &doff))
       
  3675         return NULL;
       
  3676 
       
  3677     CHECK_CURSOR_NOT_CLOSED(self);
       
  3678 
       
  3679     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  3680         return NULL;
       
  3681 
       
  3682     CLEAR_DBT(data);
       
  3683     if (!add_partial_dbt(&data, dlen, doff)) {
       
  3684         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3685         return NULL;
       
  3686     }
       
  3687 
       
  3688     MYDB_BEGIN_ALLOW_THREADS;
       
  3689     err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
       
  3690     MYDB_END_ALLOW_THREADS;
       
  3691     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  3692 	    && self->mydb->moduleFlags.cursorSetReturnsNone) {
       
  3693         Py_INCREF(Py_None);
       
  3694         retval = Py_None;
       
  3695     }
       
  3696     else if (makeDBError(err)) {
       
  3697         retval = NULL;
       
  3698     }
       
  3699     else {
       
  3700         switch (_DB_get_type(self->mydb)) {
       
  3701         case -1:
       
  3702             retval = NULL;
       
  3703             break;
       
  3704         case DB_BTREE:
       
  3705         case DB_HASH:
       
  3706         default:
       
  3707             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  3708             break;
       
  3709         case DB_RECNO:
       
  3710         case DB_QUEUE:
       
  3711             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
       
  3712             break;
       
  3713         }
       
  3714         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3715     }
       
  3716     /* the only time REALLOC should be set is if we used an integer
       
  3717      * key that make_key_dbt malloc'd for us.  always free these. */
       
  3718     if (key.flags & DB_DBT_REALLOC) {
       
  3719         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3720     }
       
  3721 
       
  3722     return retval;
       
  3723 }
       
  3724 
       
  3725 
       
  3726 static PyObject*
       
  3727 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
       
  3728 {
       
  3729     int err, flags = 0;
       
  3730     DBT key, data;
       
  3731     PyObject* retval, *keyobj;
       
  3732     static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
       
  3733     int dlen = -1;
       
  3734     int doff = -1;
       
  3735 
       
  3736     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
       
  3737 				     &keyobj, &flags, &dlen, &doff))
       
  3738         return NULL;
       
  3739 
       
  3740     CHECK_CURSOR_NOT_CLOSED(self);
       
  3741 
       
  3742     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  3743         return NULL;
       
  3744 
       
  3745     CLEAR_DBT(data);
       
  3746     if (!add_partial_dbt(&data, dlen, doff)) {
       
  3747         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3748         return NULL;
       
  3749     }
       
  3750     MYDB_BEGIN_ALLOW_THREADS;
       
  3751     err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
       
  3752     MYDB_END_ALLOW_THREADS;
       
  3753     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  3754 	    && self->mydb->moduleFlags.cursorSetReturnsNone) {
       
  3755         Py_INCREF(Py_None);
       
  3756         retval = Py_None;
       
  3757     }
       
  3758     else if (makeDBError(err)) {
       
  3759         retval = NULL;
       
  3760     }
       
  3761     else {
       
  3762         switch (_DB_get_type(self->mydb)) {
       
  3763         case -1:
       
  3764             retval = NULL;
       
  3765             break;
       
  3766         case DB_BTREE:
       
  3767         case DB_HASH:
       
  3768         default:
       
  3769             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  3770             break;
       
  3771         case DB_RECNO:
       
  3772         case DB_QUEUE:
       
  3773             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
       
  3774             break;
       
  3775         }
       
  3776         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3777     }
       
  3778     /* the only time REALLOC should be set is if we used an integer
       
  3779      * key that make_key_dbt malloc'd for us.  always free these. */
       
  3780     if (key.flags & DB_DBT_REALLOC) {
       
  3781         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3782     }
       
  3783 
       
  3784     return retval;
       
  3785 }
       
  3786 
       
  3787 static PyObject*
       
  3788 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
       
  3789                   int flags, unsigned int returnsNone)
       
  3790 {
       
  3791     int err;
       
  3792     DBT key, data;
       
  3793     PyObject* retval;
       
  3794 
       
  3795     /* the caller did this:  CHECK_CURSOR_NOT_CLOSED(self); */
       
  3796     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  3797         return NULL;
       
  3798     if (!make_dbt(dataobj, &data)) {
       
  3799         FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3800         return NULL;
       
  3801     }
       
  3802 
       
  3803     MYDB_BEGIN_ALLOW_THREADS;
       
  3804     err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
       
  3805     MYDB_END_ALLOW_THREADS;
       
  3806     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
       
  3807         Py_INCREF(Py_None);
       
  3808         retval = Py_None;
       
  3809     }
       
  3810     else if (makeDBError(err)) {
       
  3811         retval = NULL;
       
  3812     }
       
  3813     else {
       
  3814         switch (_DB_get_type(self->mydb)) {
       
  3815         case -1:
       
  3816             retval = NULL;
       
  3817             break;
       
  3818         case DB_BTREE:
       
  3819         case DB_HASH:
       
  3820         default:
       
  3821             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  3822             break;
       
  3823         case DB_RECNO:
       
  3824         case DB_QUEUE:
       
  3825             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
       
  3826             break;
       
  3827         }
       
  3828     }
       
  3829 
       
  3830     FREE_DBT(key);  /* 'make_key_dbt' could do a 'malloc' */
       
  3831     return retval;
       
  3832 }
       
  3833 
       
  3834 static PyObject*
       
  3835 DBC_get_both(DBCursorObject* self, PyObject* args)
       
  3836 {
       
  3837     int flags=0;
       
  3838     PyObject *keyobj, *dataobj;
       
  3839 
       
  3840     if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
       
  3841         return NULL;
       
  3842 
       
  3843     /* if the cursor is closed, self->mydb may be invalid */
       
  3844     CHECK_CURSOR_NOT_CLOSED(self);
       
  3845 
       
  3846     return _DBC_get_set_both(self, keyobj, dataobj, flags,
       
  3847                 self->mydb->moduleFlags.getReturnsNone);
       
  3848 }
       
  3849 
       
  3850 /* Return size of entry */
       
  3851 static PyObject*
       
  3852 DBC_get_current_size(DBCursorObject* self)
       
  3853 {
       
  3854     int err, flags=DB_CURRENT;
       
  3855     PyObject* retval = NULL;
       
  3856     DBT key, data;
       
  3857 
       
  3858     CHECK_CURSOR_NOT_CLOSED(self);
       
  3859     CLEAR_DBT(key);
       
  3860     CLEAR_DBT(data);
       
  3861 
       
  3862     /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
       
  3863        getting the record size. */
       
  3864     data.flags = DB_DBT_USERMEM;
       
  3865     data.ulen = 0;
       
  3866     MYDB_BEGIN_ALLOW_THREADS;
       
  3867     err = _DBC_get(self->dbc, &key, &data, flags);
       
  3868     MYDB_END_ALLOW_THREADS;
       
  3869     if (err == DB_BUFFER_SMALL || !err) {
       
  3870         /* DB_BUFFER_SMALL means positive size, !err means zero length value */
       
  3871         retval = NUMBER_FromLong((long)data.size);
       
  3872         err = 0;
       
  3873     }
       
  3874 
       
  3875     RETURN_IF_ERR();
       
  3876     return retval;
       
  3877 }
       
  3878 
       
  3879 static PyObject*
       
  3880 DBC_set_both(DBCursorObject* self, PyObject* args)
       
  3881 {
       
  3882     int flags=0;
       
  3883     PyObject *keyobj, *dataobj;
       
  3884 
       
  3885     if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
       
  3886         return NULL;
       
  3887 
       
  3888     /* if the cursor is closed, self->mydb may be invalid */
       
  3889     CHECK_CURSOR_NOT_CLOSED(self);
       
  3890 
       
  3891     return _DBC_get_set_both(self, keyobj, dataobj, flags,
       
  3892                 self->mydb->moduleFlags.cursorSetReturnsNone);
       
  3893 }
       
  3894 
       
  3895 
       
  3896 static PyObject*
       
  3897 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3898 {
       
  3899     int err, irecno, flags=0;
       
  3900     db_recno_t recno;
       
  3901     DBT key, data;
       
  3902     PyObject* retval;
       
  3903     int dlen = -1;
       
  3904     int doff = -1;
       
  3905     static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
       
  3906 
       
  3907     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
       
  3908 				     &irecno, &flags, &dlen, &doff))
       
  3909       return NULL;
       
  3910 
       
  3911     CHECK_CURSOR_NOT_CLOSED(self);
       
  3912 
       
  3913     CLEAR_DBT(key);
       
  3914     recno = (db_recno_t) irecno;
       
  3915     /* use allocated space so DB will be able to realloc room for the real
       
  3916      * key */
       
  3917     key.data = malloc(sizeof(db_recno_t));
       
  3918     if (key.data == NULL) {
       
  3919         PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
       
  3920         return NULL;
       
  3921     }
       
  3922     key.size = sizeof(db_recno_t);
       
  3923     key.ulen = key.size;
       
  3924     memcpy(key.data, &recno, sizeof(db_recno_t));
       
  3925     key.flags = DB_DBT_REALLOC;
       
  3926 
       
  3927     CLEAR_DBT(data);
       
  3928     if (!add_partial_dbt(&data, dlen, doff)) {
       
  3929         FREE_DBT(key);
       
  3930         return NULL;
       
  3931     }
       
  3932 
       
  3933     MYDB_BEGIN_ALLOW_THREADS;
       
  3934     err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
       
  3935     MYDB_END_ALLOW_THREADS;
       
  3936     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  3937 	    && self->mydb->moduleFlags.cursorSetReturnsNone) {
       
  3938         Py_INCREF(Py_None);
       
  3939         retval = Py_None;
       
  3940     }
       
  3941     else if (makeDBError(err)) {
       
  3942         retval = NULL;
       
  3943     }
       
  3944     else {  /* Can only be used for BTrees, so no need to return int key */
       
  3945         retval = BuildValue_SS(key.data, key.size, data.data, data.size);
       
  3946     }
       
  3947     FREE_DBT(key);
       
  3948 
       
  3949     return retval;
       
  3950 }
       
  3951 
       
  3952 
       
  3953 static PyObject*
       
  3954 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3955 {
       
  3956     return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
       
  3957 }
       
  3958 
       
  3959 
       
  3960 static PyObject*
       
  3961 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3962 {
       
  3963     return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
       
  3964 }
       
  3965 
       
  3966 
       
  3967 static PyObject*
       
  3968 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3969 {
       
  3970     return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
       
  3971 }
       
  3972 
       
  3973 
       
  3974 static PyObject*
       
  3975 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
       
  3976 {
       
  3977     return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
       
  3978 }
       
  3979 
       
  3980 
       
  3981 static PyObject*
       
  3982 DBC_join_item(DBCursorObject* self, PyObject* args)
       
  3983 {
       
  3984     int err, flags=0;
       
  3985     DBT key, data;
       
  3986     PyObject* retval;
       
  3987 
       
  3988     if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
       
  3989         return NULL;
       
  3990 
       
  3991     CHECK_CURSOR_NOT_CLOSED(self);
       
  3992 
       
  3993     CLEAR_DBT(key);
       
  3994     CLEAR_DBT(data);
       
  3995 
       
  3996     MYDB_BEGIN_ALLOW_THREADS;
       
  3997     err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
       
  3998     MYDB_END_ALLOW_THREADS;
       
  3999     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
       
  4000 	    && self->mydb->moduleFlags.getReturnsNone) {
       
  4001         Py_INCREF(Py_None);
       
  4002         retval = Py_None;
       
  4003     }
       
  4004     else if (makeDBError(err)) {
       
  4005         retval = NULL;
       
  4006     }
       
  4007     else {
       
  4008         retval = BuildValue_S(key.data, key.size);
       
  4009     }
       
  4010 
       
  4011     return retval;
       
  4012 }
       
  4013 
       
  4014 
       
  4015 
       
  4016 /* --------------------------------------------------------------------- */
       
  4017 /* DBEnv methods */
       
  4018 
       
  4019 
       
  4020 static PyObject*
       
  4021 DBEnv_close_internal(DBEnvObject* self, int flags)
       
  4022 {
       
  4023     PyObject *dummy;
       
  4024     int err;
       
  4025 
       
  4026     if (!self->closed) {      /* Don't close more than once */
       
  4027         while(self->children_txns) {
       
  4028           dummy=DBTxn_abort_discard_internal(self->children_txns,0);
       
  4029           Py_XDECREF(dummy);
       
  4030         }
       
  4031         while(self->children_dbs) {
       
  4032           dummy=DB_close_internal(self->children_dbs, 0, 0);
       
  4033           Py_XDECREF(dummy);
       
  4034         }
       
  4035     }
       
  4036 
       
  4037     self->closed = 1;
       
  4038     if (self->db_env) {
       
  4039         MYDB_BEGIN_ALLOW_THREADS;
       
  4040         err = self->db_env->close(self->db_env, flags);
       
  4041         MYDB_END_ALLOW_THREADS;
       
  4042         /* after calling DBEnv->close, regardless of error, this DBEnv
       
  4043          * may not be accessed again (Berkeley DB docs). */
       
  4044         self->db_env = NULL;
       
  4045         RETURN_IF_ERR();
       
  4046     }
       
  4047     RETURN_NONE();
       
  4048 }
       
  4049 
       
  4050 static PyObject*
       
  4051 DBEnv_close(DBEnvObject* self, PyObject* args)
       
  4052 {
       
  4053     int flags = 0;
       
  4054 
       
  4055     if (!PyArg_ParseTuple(args, "|i:close", &flags))
       
  4056         return NULL;
       
  4057     return DBEnv_close_internal(self, flags);
       
  4058 }
       
  4059 
       
  4060 
       
  4061 static PyObject*
       
  4062 DBEnv_open(DBEnvObject* self, PyObject* args)
       
  4063 {
       
  4064     int err, flags=0, mode=0660;
       
  4065     char *db_home;
       
  4066 
       
  4067     if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
       
  4068         return NULL;
       
  4069 
       
  4070     CHECK_ENV_NOT_CLOSED(self);
       
  4071 
       
  4072     MYDB_BEGIN_ALLOW_THREADS;
       
  4073     err = self->db_env->open(self->db_env, db_home, flags, mode);
       
  4074     MYDB_END_ALLOW_THREADS;
       
  4075     RETURN_IF_ERR();
       
  4076     self->closed = 0;
       
  4077     self->flags = flags;
       
  4078     RETURN_NONE();
       
  4079 }
       
  4080 
       
  4081 
       
  4082 static PyObject*
       
  4083 DBEnv_remove(DBEnvObject* self, PyObject* args)
       
  4084 {
       
  4085     int err, flags=0;
       
  4086     char *db_home;
       
  4087 
       
  4088     if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
       
  4089         return NULL;
       
  4090     CHECK_ENV_NOT_CLOSED(self);
       
  4091     MYDB_BEGIN_ALLOW_THREADS;
       
  4092     err = self->db_env->remove(self->db_env, db_home, flags);
       
  4093     MYDB_END_ALLOW_THREADS;
       
  4094     RETURN_IF_ERR();
       
  4095     RETURN_NONE();
       
  4096 }
       
  4097 
       
  4098 #if (DBVER >= 41)
       
  4099 static PyObject*
       
  4100 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  4101 {
       
  4102     int err;
       
  4103     u_int32_t flags=0;
       
  4104     char *file = NULL;
       
  4105     char *database = NULL;
       
  4106     PyObject *txnobj = NULL;
       
  4107     DB_TXN *txn = NULL;
       
  4108     static char* kwnames[] = { "file", "database", "txn", "flags",
       
  4109                                      NULL };
       
  4110 
       
  4111     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
       
  4112 		&file, &database, &txnobj, &flags)) {
       
  4113 	return NULL;
       
  4114     }
       
  4115     if (!checkTxnObj(txnobj, &txn)) {
       
  4116         return NULL;
       
  4117     }
       
  4118     CHECK_ENV_NOT_CLOSED(self);
       
  4119     MYDB_BEGIN_ALLOW_THREADS;
       
  4120     err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
       
  4121     MYDB_END_ALLOW_THREADS;
       
  4122     RETURN_IF_ERR();
       
  4123     RETURN_NONE();
       
  4124 }
       
  4125 
       
  4126 static PyObject*
       
  4127 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  4128 {
       
  4129     int err;
       
  4130     u_int32_t flags=0;
       
  4131     char *file = NULL;
       
  4132     char *database = NULL;
       
  4133     char *newname = NULL;
       
  4134     PyObject *txnobj = NULL;
       
  4135     DB_TXN *txn = NULL;
       
  4136     static char* kwnames[] = { "file", "database", "newname", "txn",
       
  4137                                      "flags", NULL };
       
  4138 
       
  4139     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
       
  4140 		&file, &database, &newname, &txnobj, &flags)) {
       
  4141 	return NULL;
       
  4142     }
       
  4143     if (!checkTxnObj(txnobj, &txn)) {
       
  4144         return NULL;
       
  4145     }
       
  4146     CHECK_ENV_NOT_CLOSED(self);
       
  4147     MYDB_BEGIN_ALLOW_THREADS;
       
  4148     err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
       
  4149                                  flags);
       
  4150     MYDB_END_ALLOW_THREADS;
       
  4151     RETURN_IF_ERR();
       
  4152     RETURN_NONE();
       
  4153 }
       
  4154 
       
  4155 static PyObject*
       
  4156 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  4157 {
       
  4158     int err;
       
  4159     u_int32_t flags=0;
       
  4160     char *passwd = NULL;
       
  4161     static char* kwnames[] = { "passwd", "flags", NULL };
       
  4162 
       
  4163     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
       
  4164 		&passwd, &flags)) {
       
  4165 	return NULL;
       
  4166     }
       
  4167 
       
  4168     MYDB_BEGIN_ALLOW_THREADS;
       
  4169     err = self->db_env->set_encrypt(self->db_env, passwd, flags);
       
  4170     MYDB_END_ALLOW_THREADS;
       
  4171 
       
  4172     RETURN_IF_ERR();
       
  4173     RETURN_NONE();
       
  4174 }
       
  4175 #endif /* DBVER >= 41 */
       
  4176 
       
  4177 static PyObject*
       
  4178 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  4179 {
       
  4180     int err;
       
  4181     u_int32_t flags=0;
       
  4182     u_int32_t timeout = 0;
       
  4183     static char* kwnames[] = { "timeout", "flags", NULL };
       
  4184 
       
  4185     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
       
  4186 		&timeout, &flags)) {
       
  4187 	return NULL;
       
  4188     }
       
  4189 
       
  4190     MYDB_BEGIN_ALLOW_THREADS;
       
  4191     err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
       
  4192     MYDB_END_ALLOW_THREADS;
       
  4193 
       
  4194     RETURN_IF_ERR();
       
  4195     RETURN_NONE();
       
  4196 }
       
  4197 
       
  4198 static PyObject*
       
  4199 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
       
  4200 {
       
  4201     int err;
       
  4202     long shm_key = 0;
       
  4203 
       
  4204     if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
       
  4205         return NULL;
       
  4206     CHECK_ENV_NOT_CLOSED(self);
       
  4207 
       
  4208     err = self->db_env->set_shm_key(self->db_env, shm_key);
       
  4209     RETURN_IF_ERR();
       
  4210     RETURN_NONE();
       
  4211 }
       
  4212 
       
  4213 static PyObject*
       
  4214 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
       
  4215 {
       
  4216     int err, gbytes=0, bytes=0, ncache=0;
       
  4217 
       
  4218     if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
       
  4219                           &gbytes, &bytes, &ncache))
       
  4220         return NULL;
       
  4221     CHECK_ENV_NOT_CLOSED(self);
       
  4222 
       
  4223     MYDB_BEGIN_ALLOW_THREADS;
       
  4224     err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
       
  4225     MYDB_END_ALLOW_THREADS;
       
  4226     RETURN_IF_ERR();
       
  4227     RETURN_NONE();
       
  4228 }
       
  4229 
       
  4230 
       
  4231 static PyObject*
       
  4232 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
       
  4233 {
       
  4234     int err, flags=0, onoff=0;
       
  4235 
       
  4236     if (!PyArg_ParseTuple(args, "ii:set_flags",
       
  4237                           &flags, &onoff))
       
  4238         return NULL;
       
  4239     CHECK_ENV_NOT_CLOSED(self);
       
  4240 
       
  4241     MYDB_BEGIN_ALLOW_THREADS;
       
  4242     err = self->db_env->set_flags(self->db_env, flags, onoff);
       
  4243     MYDB_END_ALLOW_THREADS;
       
  4244     RETURN_IF_ERR();
       
  4245     RETURN_NONE();
       
  4246 }
       
  4247 
       
  4248 
       
  4249 #if (DBVER >= 47)
       
  4250 static PyObject*
       
  4251 DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
       
  4252 {
       
  4253     int err, flags, onoff;
       
  4254 
       
  4255     if (!PyArg_ParseTuple(args, "ii:log_set_config",
       
  4256                           &flags, &onoff))
       
  4257         return NULL;
       
  4258     CHECK_ENV_NOT_CLOSED(self);
       
  4259 
       
  4260     MYDB_BEGIN_ALLOW_THREADS;
       
  4261     err = self->db_env->log_set_config(self->db_env, flags, onoff);
       
  4262     MYDB_END_ALLOW_THREADS;
       
  4263     RETURN_IF_ERR();
       
  4264     RETURN_NONE();
       
  4265 }
       
  4266 #endif /* DBVER >= 47 */
       
  4267 
       
  4268 
       
  4269 static PyObject*
       
  4270 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
       
  4271 {
       
  4272     int err;
       
  4273     char *dir;
       
  4274 
       
  4275     if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
       
  4276         return NULL;
       
  4277     CHECK_ENV_NOT_CLOSED(self);
       
  4278 
       
  4279     MYDB_BEGIN_ALLOW_THREADS;
       
  4280     err = self->db_env->set_data_dir(self->db_env, dir);
       
  4281     MYDB_END_ALLOW_THREADS;
       
  4282     RETURN_IF_ERR();
       
  4283     RETURN_NONE();
       
  4284 }
       
  4285 
       
  4286 
       
  4287 static PyObject*
       
  4288 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
       
  4289 {
       
  4290     int err, lg_bsize;
       
  4291 
       
  4292     if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
       
  4293         return NULL;
       
  4294     CHECK_ENV_NOT_CLOSED(self);
       
  4295 
       
  4296     MYDB_BEGIN_ALLOW_THREADS;
       
  4297     err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
       
  4298     MYDB_END_ALLOW_THREADS;
       
  4299     RETURN_IF_ERR();
       
  4300     RETURN_NONE();
       
  4301 }
       
  4302 
       
  4303 
       
  4304 static PyObject*
       
  4305 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
       
  4306 {
       
  4307     int err;
       
  4308     char *dir;
       
  4309 
       
  4310     if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
       
  4311         return NULL;
       
  4312     CHECK_ENV_NOT_CLOSED(self);
       
  4313 
       
  4314     MYDB_BEGIN_ALLOW_THREADS;
       
  4315     err = self->db_env->set_lg_dir(self->db_env, dir);
       
  4316     MYDB_END_ALLOW_THREADS;
       
  4317     RETURN_IF_ERR();
       
  4318     RETURN_NONE();
       
  4319 }
       
  4320 
       
  4321 static PyObject*
       
  4322 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
       
  4323 {
       
  4324     int err, lg_max;
       
  4325 
       
  4326     if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
       
  4327         return NULL;
       
  4328     CHECK_ENV_NOT_CLOSED(self);
       
  4329 
       
  4330     MYDB_BEGIN_ALLOW_THREADS;
       
  4331     err = self->db_env->set_lg_max(self->db_env, lg_max);
       
  4332     MYDB_END_ALLOW_THREADS;
       
  4333     RETURN_IF_ERR();
       
  4334     RETURN_NONE();
       
  4335 }
       
  4336 
       
  4337 #if (DBVER >= 42)
       
  4338 static PyObject*
       
  4339 DBEnv_get_lg_max(DBEnvObject* self)
       
  4340 {
       
  4341     int err;
       
  4342     u_int32_t lg_max;
       
  4343 
       
  4344     CHECK_ENV_NOT_CLOSED(self);
       
  4345 
       
  4346     MYDB_BEGIN_ALLOW_THREADS;
       
  4347     err = self->db_env->get_lg_max(self->db_env, &lg_max);
       
  4348     MYDB_END_ALLOW_THREADS;
       
  4349     RETURN_IF_ERR();
       
  4350     return NUMBER_FromLong(lg_max);
       
  4351 }
       
  4352 #endif
       
  4353 
       
  4354 
       
  4355 static PyObject*
       
  4356 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
       
  4357 {
       
  4358     int err, lg_max;
       
  4359 
       
  4360     if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
       
  4361         return NULL;
       
  4362     CHECK_ENV_NOT_CLOSED(self);
       
  4363 
       
  4364     MYDB_BEGIN_ALLOW_THREADS;
       
  4365     err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
       
  4366     MYDB_END_ALLOW_THREADS;
       
  4367     RETURN_IF_ERR();
       
  4368     RETURN_NONE();
       
  4369 }
       
  4370 
       
  4371 
       
  4372 static PyObject*
       
  4373 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
       
  4374 {
       
  4375     int err, lk_detect;
       
  4376 
       
  4377     if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
       
  4378         return NULL;
       
  4379     CHECK_ENV_NOT_CLOSED(self);
       
  4380 
       
  4381     MYDB_BEGIN_ALLOW_THREADS;
       
  4382     err = self->db_env->set_lk_detect(self->db_env, lk_detect);
       
  4383     MYDB_END_ALLOW_THREADS;
       
  4384     RETURN_IF_ERR();
       
  4385     RETURN_NONE();
       
  4386 }
       
  4387 
       
  4388 
       
  4389 #if (DBVER < 45)
       
  4390 static PyObject*
       
  4391 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
       
  4392 {
       
  4393     int err, max;
       
  4394 
       
  4395     if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
       
  4396         return NULL;
       
  4397     CHECK_ENV_NOT_CLOSED(self);
       
  4398 
       
  4399     MYDB_BEGIN_ALLOW_THREADS;
       
  4400     err = self->db_env->set_lk_max(self->db_env, max);
       
  4401     MYDB_END_ALLOW_THREADS;
       
  4402     RETURN_IF_ERR();
       
  4403     RETURN_NONE();
       
  4404 }
       
  4405 #endif
       
  4406 
       
  4407 
       
  4408 
       
  4409 static PyObject*
       
  4410 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
       
  4411 {
       
  4412     int err, max;
       
  4413 
       
  4414     if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
       
  4415         return NULL;
       
  4416     CHECK_ENV_NOT_CLOSED(self);
       
  4417 
       
  4418     MYDB_BEGIN_ALLOW_THREADS;
       
  4419     err = self->db_env->set_lk_max_locks(self->db_env, max);
       
  4420     MYDB_END_ALLOW_THREADS;
       
  4421     RETURN_IF_ERR();
       
  4422     RETURN_NONE();
       
  4423 }
       
  4424 
       
  4425 
       
  4426 static PyObject*
       
  4427 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
       
  4428 {
       
  4429     int err, max;
       
  4430 
       
  4431     if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
       
  4432         return NULL;
       
  4433     CHECK_ENV_NOT_CLOSED(self);
       
  4434 
       
  4435     MYDB_BEGIN_ALLOW_THREADS;
       
  4436     err = self->db_env->set_lk_max_lockers(self->db_env, max);
       
  4437     MYDB_END_ALLOW_THREADS;
       
  4438     RETURN_IF_ERR();
       
  4439     RETURN_NONE();
       
  4440 }
       
  4441 
       
  4442 
       
  4443 static PyObject*
       
  4444 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
       
  4445 {
       
  4446     int err, max;
       
  4447 
       
  4448     if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
       
  4449         return NULL;
       
  4450     CHECK_ENV_NOT_CLOSED(self);
       
  4451 
       
  4452     MYDB_BEGIN_ALLOW_THREADS;
       
  4453     err = self->db_env->set_lk_max_objects(self->db_env, max);
       
  4454     MYDB_END_ALLOW_THREADS;
       
  4455     RETURN_IF_ERR();
       
  4456     RETURN_NONE();
       
  4457 }
       
  4458 
       
  4459 
       
  4460 static PyObject*
       
  4461 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
       
  4462 {
       
  4463     int err, mp_mmapsize;
       
  4464 
       
  4465     if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
       
  4466         return NULL;
       
  4467     CHECK_ENV_NOT_CLOSED(self);
       
  4468 
       
  4469     MYDB_BEGIN_ALLOW_THREADS;
       
  4470     err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
       
  4471     MYDB_END_ALLOW_THREADS;
       
  4472     RETURN_IF_ERR();
       
  4473     RETURN_NONE();
       
  4474 }
       
  4475 
       
  4476 
       
  4477 static PyObject*
       
  4478 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
       
  4479 {
       
  4480     int err;
       
  4481     char *dir;
       
  4482 
       
  4483     if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
       
  4484         return NULL;
       
  4485     CHECK_ENV_NOT_CLOSED(self);
       
  4486 
       
  4487     MYDB_BEGIN_ALLOW_THREADS;
       
  4488     err = self->db_env->set_tmp_dir(self->db_env, dir);
       
  4489     MYDB_END_ALLOW_THREADS;
       
  4490     RETURN_IF_ERR();
       
  4491     RETURN_NONE();
       
  4492 }
       
  4493 
       
  4494 
       
  4495 static PyObject*
       
  4496 DBEnv_txn_recover(DBEnvObject* self)
       
  4497 {
       
  4498     int flags = DB_FIRST;
       
  4499     int err, i;
       
  4500     PyObject *list, *tuple, *gid;
       
  4501     DBTxnObject *txn;
       
  4502 #define PREPLIST_LEN 16
       
  4503     DB_PREPLIST preplist[PREPLIST_LEN];
       
  4504     long retp;
       
  4505 
       
  4506     CHECK_ENV_NOT_CLOSED(self);
       
  4507 
       
  4508     list=PyList_New(0);
       
  4509     if (!list)
       
  4510         return NULL;
       
  4511     while (!0) {
       
  4512         MYDB_BEGIN_ALLOW_THREADS
       
  4513         err=self->db_env->txn_recover(self->db_env,
       
  4514                         preplist, PREPLIST_LEN, &retp, flags);
       
  4515 #undef PREPLIST_LEN
       
  4516         MYDB_END_ALLOW_THREADS
       
  4517         if (err) {
       
  4518             Py_DECREF(list);
       
  4519             RETURN_IF_ERR();
       
  4520         }
       
  4521         if (!retp) break;
       
  4522         flags=DB_NEXT;  /* Prepare for next loop pass */
       
  4523         for (i=0; i<retp; i++) {
       
  4524             gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
       
  4525                                 DB_XIDDATASIZE);
       
  4526             if (!gid) {
       
  4527                 Py_DECREF(list);
       
  4528                 return NULL;
       
  4529             }
       
  4530             txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
       
  4531             if (!txn) {
       
  4532                 Py_DECREF(list);
       
  4533                 Py_DECREF(gid);
       
  4534                 return NULL;
       
  4535             }
       
  4536             txn->flag_prepare=1;  /* Recover state */
       
  4537             tuple=PyTuple_New(2);
       
  4538             if (!tuple) {
       
  4539                 Py_DECREF(list);
       
  4540                 Py_DECREF(gid);
       
  4541                 Py_DECREF(txn);
       
  4542                 return NULL;
       
  4543             }
       
  4544             if (PyTuple_SetItem(tuple, 0, gid)) {
       
  4545                 Py_DECREF(list);
       
  4546                 Py_DECREF(gid);
       
  4547                 Py_DECREF(txn);
       
  4548                 Py_DECREF(tuple);
       
  4549                 return NULL;
       
  4550             }
       
  4551             if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
       
  4552                 Py_DECREF(list);
       
  4553                 Py_DECREF(txn);
       
  4554                 Py_DECREF(tuple); /* This delete the "gid" also */
       
  4555                 return NULL;
       
  4556             }
       
  4557             if (PyList_Append(list, tuple)) {
       
  4558                 Py_DECREF(list);
       
  4559                 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
       
  4560                 return NULL;
       
  4561             }
       
  4562             Py_DECREF(tuple);
       
  4563         }
       
  4564     }
       
  4565     return list;
       
  4566 }
       
  4567 
       
  4568 static PyObject*
       
  4569 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  4570 {
       
  4571     int flags = 0;
       
  4572     PyObject* txnobj = NULL;
       
  4573     DB_TXN *txn = NULL;
       
  4574     static char* kwnames[] = { "parent", "flags", NULL };
       
  4575 
       
  4576     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
       
  4577                                      &txnobj, &flags))
       
  4578         return NULL;
       
  4579 
       
  4580     if (!checkTxnObj(txnobj, &txn))
       
  4581         return NULL;
       
  4582     CHECK_ENV_NOT_CLOSED(self);
       
  4583 
       
  4584     return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
       
  4585 }
       
  4586 
       
  4587 
       
  4588 static PyObject*
       
  4589 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
       
  4590 {
       
  4591     int err, kbyte=0, min=0, flags=0;
       
  4592 
       
  4593     if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
       
  4594         return NULL;
       
  4595     CHECK_ENV_NOT_CLOSED(self);
       
  4596 
       
  4597     MYDB_BEGIN_ALLOW_THREADS;
       
  4598     err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
       
  4599     MYDB_END_ALLOW_THREADS;
       
  4600     RETURN_IF_ERR();
       
  4601     RETURN_NONE();
       
  4602 }
       
  4603 
       
  4604 
       
  4605 static PyObject*
       
  4606 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
       
  4607 {
       
  4608     int err, max;
       
  4609 
       
  4610     if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
       
  4611         return NULL;
       
  4612     CHECK_ENV_NOT_CLOSED(self);
       
  4613 
       
  4614     err = self->db_env->set_tx_max(self->db_env, max);
       
  4615     RETURN_IF_ERR();
       
  4616     RETURN_NONE();
       
  4617 }
       
  4618 
       
  4619 
       
  4620 static PyObject*
       
  4621 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
       
  4622 {
       
  4623     int err;
       
  4624     long stamp;
       
  4625     time_t timestamp;
       
  4626 
       
  4627     if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
       
  4628         return NULL;
       
  4629     CHECK_ENV_NOT_CLOSED(self);
       
  4630     timestamp = (time_t)stamp;
       
  4631     err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
       
  4632     RETURN_IF_ERR();
       
  4633     RETURN_NONE();
       
  4634 }
       
  4635 
       
  4636 
       
  4637 static PyObject*
       
  4638 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
       
  4639 {
       
  4640     int err, atype, flags=0;
       
  4641     int aborted = 0;
       
  4642 
       
  4643     if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
       
  4644         return NULL;
       
  4645     CHECK_ENV_NOT_CLOSED(self);
       
  4646 
       
  4647     MYDB_BEGIN_ALLOW_THREADS;
       
  4648     err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
       
  4649     MYDB_END_ALLOW_THREADS;
       
  4650     RETURN_IF_ERR();
       
  4651     return NUMBER_FromLong(aborted);
       
  4652 }
       
  4653 
       
  4654 
       
  4655 static PyObject*
       
  4656 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
       
  4657 {
       
  4658     int flags=0;
       
  4659     int locker, lock_mode;
       
  4660     DBT obj;
       
  4661     PyObject* objobj;
       
  4662 
       
  4663     if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
       
  4664         return NULL;
       
  4665 
       
  4666 
       
  4667     if (!make_dbt(objobj, &obj))
       
  4668         return NULL;
       
  4669 
       
  4670     return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
       
  4671 }
       
  4672 
       
  4673 
       
  4674 static PyObject*
       
  4675 DBEnv_lock_id(DBEnvObject* self)
       
  4676 {
       
  4677     int err;
       
  4678     u_int32_t theID;
       
  4679 
       
  4680     CHECK_ENV_NOT_CLOSED(self);
       
  4681     MYDB_BEGIN_ALLOW_THREADS;
       
  4682     err = self->db_env->lock_id(self->db_env, &theID);
       
  4683     MYDB_END_ALLOW_THREADS;
       
  4684     RETURN_IF_ERR();
       
  4685 
       
  4686     return NUMBER_FromLong((long)theID);
       
  4687 }
       
  4688 
       
  4689 static PyObject*
       
  4690 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
       
  4691 {
       
  4692     int err;
       
  4693     u_int32_t theID;
       
  4694 
       
  4695     if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
       
  4696         return NULL;
       
  4697 
       
  4698     CHECK_ENV_NOT_CLOSED(self);
       
  4699     MYDB_BEGIN_ALLOW_THREADS;
       
  4700     err = self->db_env->lock_id_free(self->db_env, theID);
       
  4701     MYDB_END_ALLOW_THREADS;
       
  4702     RETURN_IF_ERR();
       
  4703     RETURN_NONE();
       
  4704 }
       
  4705 
       
  4706 static PyObject*
       
  4707 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
       
  4708 {
       
  4709     int err;
       
  4710     DBLockObject* dblockobj;
       
  4711 
       
  4712     if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
       
  4713         return NULL;
       
  4714 
       
  4715     CHECK_ENV_NOT_CLOSED(self);
       
  4716     MYDB_BEGIN_ALLOW_THREADS;
       
  4717     err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
       
  4718     MYDB_END_ALLOW_THREADS;
       
  4719     RETURN_IF_ERR();
       
  4720     RETURN_NONE();
       
  4721 }
       
  4722 
       
  4723 #if (DBVER >= 44)
       
  4724 static PyObject*
       
  4725 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  4726 {
       
  4727     int err;
       
  4728     char *file;
       
  4729     u_int32_t flags = 0;
       
  4730     static char* kwnames[] = { "file", "flags", NULL};
       
  4731 
       
  4732     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
       
  4733                                      &file, &flags))
       
  4734         return NULL;
       
  4735     CHECK_ENV_NOT_CLOSED(self);
       
  4736 
       
  4737     MYDB_BEGIN_ALLOW_THREADS;
       
  4738     err = self->db_env->lsn_reset(self->db_env, file, flags);
       
  4739     MYDB_END_ALLOW_THREADS;
       
  4740     RETURN_IF_ERR();
       
  4741     RETURN_NONE();
       
  4742 }
       
  4743 #endif /* DBVER >= 4.4 */
       
  4744 
       
  4745 static PyObject*
       
  4746 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
       
  4747 {
       
  4748     int err;
       
  4749     DB_LOG_STAT* statp = NULL;
       
  4750     PyObject* d = NULL;
       
  4751     u_int32_t flags = 0;
       
  4752 
       
  4753     if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
       
  4754         return NULL;
       
  4755     CHECK_ENV_NOT_CLOSED(self);
       
  4756 
       
  4757     MYDB_BEGIN_ALLOW_THREADS;
       
  4758     err = self->db_env->log_stat(self->db_env, &statp, flags);
       
  4759     MYDB_END_ALLOW_THREADS;
       
  4760     RETURN_IF_ERR();
       
  4761 
       
  4762     /* Turn the stat structure into a dictionary */
       
  4763     d = PyDict_New();
       
  4764     if (d == NULL) {
       
  4765         if (statp)
       
  4766             free(statp);
       
  4767         return NULL;
       
  4768     }
       
  4769 
       
  4770 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, statp->st_##name)
       
  4771 
       
  4772     MAKE_ENTRY(magic);
       
  4773     MAKE_ENTRY(version);
       
  4774     MAKE_ENTRY(mode);
       
  4775     MAKE_ENTRY(lg_bsize);
       
  4776 #if (DBVER >= 44)
       
  4777     MAKE_ENTRY(lg_size);
       
  4778     MAKE_ENTRY(record);
       
  4779 #endif
       
  4780 #if (DBVER < 41)
       
  4781     MAKE_ENTRY(lg_max);
       
  4782 #endif
       
  4783     MAKE_ENTRY(w_mbytes);
       
  4784     MAKE_ENTRY(w_bytes);
       
  4785     MAKE_ENTRY(wc_mbytes);
       
  4786     MAKE_ENTRY(wc_bytes);
       
  4787     MAKE_ENTRY(wcount);
       
  4788     MAKE_ENTRY(wcount_fill);
       
  4789 #if (DBVER >= 44)
       
  4790     MAKE_ENTRY(rcount);
       
  4791 #endif
       
  4792     MAKE_ENTRY(scount);
       
  4793     MAKE_ENTRY(cur_file);
       
  4794     MAKE_ENTRY(cur_offset);
       
  4795     MAKE_ENTRY(disk_file);
       
  4796     MAKE_ENTRY(disk_offset);
       
  4797     MAKE_ENTRY(maxcommitperflush);
       
  4798     MAKE_ENTRY(mincommitperflush);
       
  4799     MAKE_ENTRY(regsize);
       
  4800     MAKE_ENTRY(region_wait);
       
  4801     MAKE_ENTRY(region_nowait);
       
  4802 
       
  4803 #undef MAKE_ENTRY
       
  4804     free(statp);
       
  4805     return d;
       
  4806 } /* DBEnv_log_stat */
       
  4807 
       
  4808 
       
  4809 static PyObject*
       
  4810 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
       
  4811 {
       
  4812     int err;
       
  4813     DB_LOCK_STAT* sp;
       
  4814     PyObject* d = NULL;
       
  4815     u_int32_t flags = 0;
       
  4816 
       
  4817     if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
       
  4818         return NULL;
       
  4819     CHECK_ENV_NOT_CLOSED(self);
       
  4820 
       
  4821     MYDB_BEGIN_ALLOW_THREADS;
       
  4822     err = self->db_env->lock_stat(self->db_env, &sp, flags);
       
  4823     MYDB_END_ALLOW_THREADS;
       
  4824     RETURN_IF_ERR();
       
  4825 
       
  4826     /* Turn the stat structure into a dictionary */
       
  4827     d = PyDict_New();
       
  4828     if (d == NULL) {
       
  4829         free(sp);
       
  4830         return NULL;
       
  4831     }
       
  4832 
       
  4833 #define MAKE_ENTRY(name)  _addIntToDict(d, #name, sp->st_##name)
       
  4834 
       
  4835 #if (DBVER < 41)
       
  4836     MAKE_ENTRY(lastid);
       
  4837 #endif
       
  4838 #if (DBVER >=41)
       
  4839     MAKE_ENTRY(id);
       
  4840     MAKE_ENTRY(cur_maxid);
       
  4841 #endif
       
  4842     MAKE_ENTRY(nmodes);
       
  4843     MAKE_ENTRY(maxlocks);
       
  4844     MAKE_ENTRY(maxlockers);
       
  4845     MAKE_ENTRY(maxobjects);
       
  4846     MAKE_ENTRY(nlocks);
       
  4847     MAKE_ENTRY(maxnlocks);
       
  4848     MAKE_ENTRY(nlockers);
       
  4849     MAKE_ENTRY(maxnlockers);
       
  4850     MAKE_ENTRY(nobjects);
       
  4851     MAKE_ENTRY(maxnobjects);
       
  4852     MAKE_ENTRY(nrequests);
       
  4853     MAKE_ENTRY(nreleases);
       
  4854 #if (DBVER >= 44)
       
  4855     MAKE_ENTRY(nupgrade);
       
  4856     MAKE_ENTRY(ndowngrade);
       
  4857 #endif
       
  4858 #if (DBVER < 44)
       
  4859     MAKE_ENTRY(nnowaits);       /* these were renamed in 4.4 */
       
  4860     MAKE_ENTRY(nconflicts);
       
  4861 #else
       
  4862     MAKE_ENTRY(lock_nowait);
       
  4863     MAKE_ENTRY(lock_wait);
       
  4864 #endif
       
  4865     MAKE_ENTRY(ndeadlocks);
       
  4866 #if (DBVER >= 41)
       
  4867     MAKE_ENTRY(locktimeout);
       
  4868     MAKE_ENTRY(txntimeout);
       
  4869 #endif
       
  4870     MAKE_ENTRY(nlocktimeouts);
       
  4871     MAKE_ENTRY(ntxntimeouts);
       
  4872 #if (DBVER >= 46)
       
  4873     MAKE_ENTRY(objs_wait);
       
  4874     MAKE_ENTRY(objs_nowait);
       
  4875     MAKE_ENTRY(lockers_wait);
       
  4876     MAKE_ENTRY(lockers_nowait);
       
  4877 #if (DBVER >= 47)
       
  4878     MAKE_ENTRY(lock_wait);
       
  4879     MAKE_ENTRY(lock_nowait);
       
  4880 #else
       
  4881     MAKE_ENTRY(locks_wait);
       
  4882     MAKE_ENTRY(locks_nowait);
       
  4883 #endif
       
  4884     MAKE_ENTRY(hash_len);
       
  4885 #endif
       
  4886     MAKE_ENTRY(regsize);
       
  4887     MAKE_ENTRY(region_wait);
       
  4888     MAKE_ENTRY(region_nowait);
       
  4889 
       
  4890 #undef MAKE_ENTRY
       
  4891     free(sp);
       
  4892     return d;
       
  4893 }
       
  4894 
       
  4895 static PyObject*
       
  4896 DBEnv_log_flush(DBEnvObject* self)
       
  4897 {
       
  4898     int err;
       
  4899 
       
  4900     CHECK_ENV_NOT_CLOSED(self);
       
  4901 
       
  4902     MYDB_BEGIN_ALLOW_THREADS
       
  4903     err = self->db_env->log_flush(self->db_env, NULL);
       
  4904     MYDB_END_ALLOW_THREADS
       
  4905 
       
  4906     RETURN_IF_ERR();
       
  4907     RETURN_NONE();
       
  4908 }
       
  4909 
       
  4910 static PyObject*
       
  4911 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
       
  4912 {
       
  4913     int flags=0;
       
  4914     int err;
       
  4915     char **log_list = NULL;
       
  4916     PyObject* list;
       
  4917     PyObject* item = NULL;
       
  4918 
       
  4919     if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
       
  4920         return NULL;
       
  4921 
       
  4922     CHECK_ENV_NOT_CLOSED(self);
       
  4923     MYDB_BEGIN_ALLOW_THREADS;
       
  4924     err = self->db_env->log_archive(self->db_env, &log_list, flags);
       
  4925     MYDB_END_ALLOW_THREADS;
       
  4926     RETURN_IF_ERR();
       
  4927 
       
  4928     list = PyList_New(0);
       
  4929     if (list == NULL) {
       
  4930         if (log_list)
       
  4931             free(log_list);
       
  4932         return NULL;
       
  4933     }
       
  4934 
       
  4935     if (log_list) {
       
  4936         char **log_list_start;
       
  4937         for (log_list_start = log_list; *log_list != NULL; ++log_list) {
       
  4938             item = PyBytes_FromString (*log_list);
       
  4939             if (item == NULL) {
       
  4940                 Py_DECREF(list);
       
  4941                 list = NULL;
       
  4942                 break;
       
  4943             }
       
  4944             if (PyList_Append(list, item)) {
       
  4945                 Py_DECREF(list);
       
  4946                 list = NULL;
       
  4947                 Py_DECREF(item);
       
  4948                 break;
       
  4949             }
       
  4950             Py_DECREF(item);
       
  4951         }
       
  4952         free(log_list_start);
       
  4953     }
       
  4954     return list;
       
  4955 }
       
  4956 
       
  4957 
       
  4958 static PyObject*
       
  4959 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
       
  4960 {
       
  4961     int err;
       
  4962     DB_TXN_STAT* sp;
       
  4963     PyObject* d = NULL;
       
  4964     u_int32_t flags=0;
       
  4965 
       
  4966     if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
       
  4967         return NULL;
       
  4968     CHECK_ENV_NOT_CLOSED(self);
       
  4969 
       
  4970     MYDB_BEGIN_ALLOW_THREADS;
       
  4971     err = self->db_env->txn_stat(self->db_env, &sp, flags);
       
  4972     MYDB_END_ALLOW_THREADS;
       
  4973     RETURN_IF_ERR();
       
  4974 
       
  4975     /* Turn the stat structure into a dictionary */
       
  4976     d = PyDict_New();
       
  4977     if (d == NULL) {
       
  4978         free(sp);
       
  4979         return NULL;
       
  4980     }
       
  4981 
       
  4982 #define MAKE_ENTRY(name)        _addIntToDict(d, #name, sp->st_##name)
       
  4983 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
       
  4984 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
       
  4985 
       
  4986     MAKE_DB_LSN_ENTRY(last_ckp);
       
  4987     MAKE_TIME_T_ENTRY(time_ckp);
       
  4988     MAKE_ENTRY(last_txnid);
       
  4989     MAKE_ENTRY(maxtxns);
       
  4990     MAKE_ENTRY(nactive);
       
  4991     MAKE_ENTRY(maxnactive);
       
  4992 #if (DBVER >= 45)
       
  4993     MAKE_ENTRY(nsnapshot);
       
  4994     MAKE_ENTRY(maxnsnapshot);
       
  4995 #endif
       
  4996     MAKE_ENTRY(nbegins);
       
  4997     MAKE_ENTRY(naborts);
       
  4998     MAKE_ENTRY(ncommits);
       
  4999     MAKE_ENTRY(nrestores);
       
  5000     MAKE_ENTRY(regsize);
       
  5001     MAKE_ENTRY(region_wait);
       
  5002     MAKE_ENTRY(region_nowait);
       
  5003 
       
  5004 #undef MAKE_DB_LSN_ENTRY
       
  5005 #undef MAKE_ENTRY
       
  5006 #undef MAKE_TIME_T_ENTRY
       
  5007     free(sp);
       
  5008     return d;
       
  5009 }
       
  5010 
       
  5011 
       
  5012 static PyObject*
       
  5013 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
       
  5014 {
       
  5015     int flags=0;
       
  5016     int oldValue=0;
       
  5017 
       
  5018     if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
       
  5019         return NULL;
       
  5020     CHECK_ENV_NOT_CLOSED(self);
       
  5021 
       
  5022     if (self->moduleFlags.getReturnsNone)
       
  5023         ++oldValue;
       
  5024     if (self->moduleFlags.cursorSetReturnsNone)
       
  5025         ++oldValue;
       
  5026     self->moduleFlags.getReturnsNone = (flags >= 1);
       
  5027     self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
       
  5028     return NUMBER_FromLong(oldValue);
       
  5029 }
       
  5030 
       
  5031 static PyObject*
       
  5032 DBEnv_get_private(DBEnvObject* self)
       
  5033 {
       
  5034     /* We can give out the private field even if dbenv is closed */
       
  5035     Py_INCREF(self->private_obj);
       
  5036     return self->private_obj;
       
  5037 }
       
  5038 
       
  5039 static PyObject*
       
  5040 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
       
  5041 {
       
  5042     /* We can set the private field even if dbenv is closed */
       
  5043     Py_DECREF(self->private_obj);
       
  5044     Py_INCREF(private_obj);
       
  5045     self->private_obj = private_obj;
       
  5046     RETURN_NONE();
       
  5047 }
       
  5048 
       
  5049 
       
  5050 static PyObject*
       
  5051 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  5052 {
       
  5053     int err;
       
  5054     char *host;
       
  5055     long cl_timeout=0, sv_timeout=0;
       
  5056 
       
  5057     static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
       
  5058 
       
  5059     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
       
  5060                                      &host, &cl_timeout, &sv_timeout))
       
  5061         return NULL;
       
  5062     CHECK_ENV_NOT_CLOSED(self);
       
  5063 
       
  5064     MYDB_BEGIN_ALLOW_THREADS;
       
  5065     err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
       
  5066             sv_timeout, 0);
       
  5067     MYDB_END_ALLOW_THREADS;
       
  5068     RETURN_IF_ERR();
       
  5069     RETURN_NONE();
       
  5070 }
       
  5071 
       
  5072 static PyObject*
       
  5073 DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
       
  5074 {
       
  5075     int err;
       
  5076     int which, onoff;
       
  5077 
       
  5078     if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
       
  5079         return NULL;
       
  5080     }
       
  5081     CHECK_ENV_NOT_CLOSED(self);
       
  5082     MYDB_BEGIN_ALLOW_THREADS;
       
  5083     err = self->db_env->set_verbose(self->db_env, which, onoff);
       
  5084     MYDB_END_ALLOW_THREADS;
       
  5085     RETURN_IF_ERR();
       
  5086     RETURN_NONE();
       
  5087 }
       
  5088 
       
  5089 #if (DBVER >= 42)
       
  5090 static PyObject*
       
  5091 DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
       
  5092 {
       
  5093     int err;
       
  5094     int which;
       
  5095     int verbose;
       
  5096 
       
  5097     if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
       
  5098         return NULL;
       
  5099     }
       
  5100     CHECK_ENV_NOT_CLOSED(self);
       
  5101     MYDB_BEGIN_ALLOW_THREADS;
       
  5102     err = self->db_env->get_verbose(self->db_env, which, &verbose);
       
  5103     MYDB_END_ALLOW_THREADS;
       
  5104     RETURN_IF_ERR();
       
  5105     return PyBool_FromLong(verbose);
       
  5106 }
       
  5107 #endif
       
  5108 
       
  5109 #if (DBVER >= 45)
       
  5110 static void
       
  5111 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
       
  5112 {
       
  5113     DBEnvObject *dbenv;
       
  5114     PyObject* callback;
       
  5115     PyObject* args;
       
  5116     PyObject* result = NULL;
       
  5117 
       
  5118     MYDB_BEGIN_BLOCK_THREADS;
       
  5119     dbenv = (DBEnvObject *)db_env->app_private;
       
  5120     callback = dbenv->event_notifyCallback;
       
  5121     if (callback) {
       
  5122         if (event == DB_EVENT_REP_NEWMASTER) {
       
  5123             args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
       
  5124         } else {
       
  5125             args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
       
  5126         }
       
  5127         if (args) {
       
  5128             result = PyEval_CallObject(callback, args);
       
  5129         }
       
  5130         if ((!args) || (!result)) {
       
  5131             PyErr_Print();
       
  5132         }
       
  5133         Py_XDECREF(args);
       
  5134         Py_XDECREF(result);
       
  5135     }
       
  5136     MYDB_END_BLOCK_THREADS;
       
  5137 }
       
  5138 #endif
       
  5139 
       
  5140 #if (DBVER >= 45)
       
  5141 static PyObject*
       
  5142 DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
       
  5143 {
       
  5144     int err;
       
  5145 
       
  5146     CHECK_ENV_NOT_CLOSED(self);
       
  5147 
       
  5148     if (!PyCallable_Check(notifyFunc)) {
       
  5149 	    makeTypeError("Callable", notifyFunc);
       
  5150 	    return NULL;
       
  5151     }
       
  5152 
       
  5153     Py_XDECREF(self->event_notifyCallback);
       
  5154     Py_INCREF(notifyFunc);
       
  5155     self->event_notifyCallback = notifyFunc;
       
  5156 
       
  5157     /* This is to workaround a problem with un-initialized threads (see
       
  5158        comment in DB_associate) */
       
  5159 #ifdef WITH_THREAD
       
  5160     PyEval_InitThreads();
       
  5161 #endif
       
  5162 
       
  5163     MYDB_BEGIN_ALLOW_THREADS;
       
  5164     err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
       
  5165     MYDB_END_ALLOW_THREADS;
       
  5166 
       
  5167     if (err) {
       
  5168 	    Py_DECREF(notifyFunc);
       
  5169 	    self->event_notifyCallback = NULL;
       
  5170     }
       
  5171 
       
  5172     RETURN_IF_ERR();
       
  5173     RETURN_NONE();
       
  5174 }
       
  5175 #endif
       
  5176 
       
  5177 
       
  5178 /* --------------------------------------------------------------------- */
       
  5179 /* REPLICATION METHODS: Base Replication */
       
  5180 
       
  5181 
       
  5182 static PyObject*
       
  5183 DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
       
  5184 {
       
  5185     int err;
       
  5186     PyObject *control_py, *rec_py;
       
  5187     DBT control, rec;
       
  5188     int envid;
       
  5189 #if (DBVER >= 42)
       
  5190     DB_LSN lsn;
       
  5191 #endif
       
  5192 
       
  5193     if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
       
  5194                 &rec_py, &envid))
       
  5195         return NULL;
       
  5196     CHECK_ENV_NOT_CLOSED(self);
       
  5197 
       
  5198     if (!make_dbt(control_py, &control))
       
  5199         return NULL;
       
  5200     if (!make_dbt(rec_py, &rec))
       
  5201         return NULL;
       
  5202 
       
  5203     MYDB_BEGIN_ALLOW_THREADS;
       
  5204 #if (DBVER >= 46)
       
  5205     err = self->db_env->rep_process_message(self->db_env, &control, &rec,
       
  5206             envid, &lsn);
       
  5207 #else
       
  5208 #if (DBVER >= 42)
       
  5209     err = self->db_env->rep_process_message(self->db_env, &control, &rec,
       
  5210             &envid, &lsn);
       
  5211 #else
       
  5212     err = self->db_env->rep_process_message(self->db_env, &control, &rec,
       
  5213             &envid);
       
  5214 #endif
       
  5215 #endif
       
  5216     MYDB_END_ALLOW_THREADS;
       
  5217     switch (err) {
       
  5218         case DB_REP_NEWMASTER :
       
  5219           return Py_BuildValue("(iO)", envid, Py_None);
       
  5220           break;
       
  5221 
       
  5222         case DB_REP_DUPMASTER :
       
  5223         case DB_REP_HOLDELECTION :
       
  5224 #if (DBVER >= 44)
       
  5225         case DB_REP_IGNORE :
       
  5226         case DB_REP_JOIN_FAILURE :
       
  5227 #endif
       
  5228             return Py_BuildValue("(iO)", err, Py_None);
       
  5229             break;
       
  5230         case DB_REP_NEWSITE :
       
  5231             {
       
  5232                 PyObject *tmp, *r;
       
  5233 
       
  5234                 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
       
  5235                     return NULL;
       
  5236                 }
       
  5237 
       
  5238                 r = Py_BuildValue("(iO)", err, tmp);
       
  5239                 Py_DECREF(tmp);
       
  5240                 return r;
       
  5241                 break;
       
  5242             }
       
  5243 #if (DBVER >= 42)
       
  5244         case DB_REP_NOTPERM :
       
  5245         case DB_REP_ISPERM :
       
  5246             return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
       
  5247             break;
       
  5248 #endif
       
  5249     }
       
  5250     RETURN_IF_ERR();
       
  5251     return Py_BuildValue("(OO)", Py_None, Py_None);
       
  5252 }
       
  5253 
       
  5254 static int
       
  5255 _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
       
  5256         const DB_LSN *lsn, int envid, u_int32_t flags)
       
  5257 {
       
  5258     DBEnvObject *dbenv;
       
  5259     PyObject* rep_transport;
       
  5260     PyObject* args;
       
  5261     PyObject *a, *b;
       
  5262     PyObject* result = NULL;
       
  5263     int ret=0;
       
  5264 
       
  5265     MYDB_BEGIN_BLOCK_THREADS;
       
  5266     dbenv = (DBEnvObject *)db_env->app_private;
       
  5267     rep_transport = dbenv->rep_transport;
       
  5268 
       
  5269     /*
       
  5270     ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
       
  5271     */
       
  5272     a = PyBytes_FromStringAndSize(control->data, control->size);
       
  5273     b = PyBytes_FromStringAndSize(rec->data, rec->size);
       
  5274 
       
  5275     args = Py_BuildValue(
       
  5276 #if (PY_VERSION_HEX >= 0x02040000)
       
  5277             "(OOO(ll)iI)",
       
  5278 #else
       
  5279             "(OOO(ll)ii)",
       
  5280 #endif
       
  5281             dbenv,
       
  5282             a, b,
       
  5283             lsn->file, lsn->offset, envid, flags);
       
  5284     if (args) {
       
  5285         result = PyEval_CallObject(rep_transport, args);
       
  5286     }
       
  5287 
       
  5288     if ((!args) || (!result)) {
       
  5289         PyErr_Print();
       
  5290         ret = -1;
       
  5291     }
       
  5292     Py_XDECREF(a);
       
  5293     Py_XDECREF(b);
       
  5294     Py_XDECREF(args);
       
  5295     Py_XDECREF(result);
       
  5296     MYDB_END_BLOCK_THREADS;
       
  5297     return ret;
       
  5298 }
       
  5299 
       
  5300 #if (DBVER <= 41)
       
  5301 static int
       
  5302 _DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
       
  5303         int envid, u_int32_t flags)
       
  5304 {
       
  5305     DB_LSN lsn;
       
  5306 
       
  5307     lsn.file = -1;  /* Dummy values */
       
  5308     lsn.offset = -1;
       
  5309     return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
       
  5310             flags);
       
  5311 }
       
  5312 #endif
       
  5313 
       
  5314 static PyObject*
       
  5315 DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
       
  5316 {
       
  5317     int err;
       
  5318     int envid;
       
  5319     PyObject *rep_transport;
       
  5320 
       
  5321     if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
       
  5322         return NULL;
       
  5323     CHECK_ENV_NOT_CLOSED(self);
       
  5324     if (!PyCallable_Check(rep_transport)) {
       
  5325         makeTypeError("Callable", rep_transport);
       
  5326         return NULL;
       
  5327     }
       
  5328 
       
  5329     MYDB_BEGIN_ALLOW_THREADS;
       
  5330 #if (DBVER >=45)
       
  5331     err = self->db_env->rep_set_transport(self->db_env, envid,
       
  5332             &_DBEnv_rep_transportCallback);
       
  5333 #else
       
  5334 #if (DBVER >= 42)
       
  5335     err = self->db_env->set_rep_transport(self->db_env, envid,
       
  5336             &_DBEnv_rep_transportCallback);
       
  5337 #else
       
  5338     err = self->db_env->set_rep_transport(self->db_env, envid,
       
  5339             &_DBEnv_rep_transportCallbackOLD);
       
  5340 #endif
       
  5341 #endif
       
  5342     MYDB_END_ALLOW_THREADS;
       
  5343     RETURN_IF_ERR();
       
  5344 
       
  5345     Py_DECREF(self->rep_transport);
       
  5346     Py_INCREF(rep_transport);
       
  5347     self->rep_transport = rep_transport;
       
  5348     RETURN_NONE();
       
  5349 }
       
  5350 
       
  5351 #if (DBVER >= 47)
       
  5352 static PyObject*
       
  5353 DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
       
  5354 {
       
  5355     int err;
       
  5356     unsigned int minimum, maximum;
       
  5357 
       
  5358     if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
       
  5359         return NULL;
       
  5360     CHECK_ENV_NOT_CLOSED(self);
       
  5361 
       
  5362     MYDB_BEGIN_ALLOW_THREADS;
       
  5363     err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
       
  5364     MYDB_END_ALLOW_THREADS;
       
  5365     RETURN_IF_ERR();
       
  5366     RETURN_NONE();
       
  5367 }
       
  5368 
       
  5369 static PyObject*
       
  5370 DBEnv_rep_get_request(DBEnvObject* self)
       
  5371 {
       
  5372     int err;
       
  5373     u_int32_t minimum, maximum;
       
  5374 
       
  5375     CHECK_ENV_NOT_CLOSED(self);
       
  5376     MYDB_BEGIN_ALLOW_THREADS;
       
  5377     err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
       
  5378     MYDB_END_ALLOW_THREADS;
       
  5379     RETURN_IF_ERR();
       
  5380 #if (PY_VERSION_HEX >= 0x02040000)
       
  5381     return Py_BuildValue("II", minimum, maximum);
       
  5382 #else
       
  5383     return Py_BuildValue("ii", minimum, maximum);
       
  5384 #endif
       
  5385 }
       
  5386 #endif
       
  5387 
       
  5388 #if (DBVER >= 45)
       
  5389 static PyObject*
       
  5390 DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
       
  5391 {
       
  5392     int err;
       
  5393     int limit;
       
  5394 
       
  5395     if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
       
  5396         return NULL;
       
  5397     CHECK_ENV_NOT_CLOSED(self);
       
  5398 
       
  5399     MYDB_BEGIN_ALLOW_THREADS;
       
  5400     err = self->db_env->rep_set_limit(self->db_env, 0, limit);
       
  5401     MYDB_END_ALLOW_THREADS;
       
  5402     RETURN_IF_ERR();
       
  5403     RETURN_NONE();
       
  5404 }
       
  5405 
       
  5406 static PyObject*
       
  5407 DBEnv_rep_get_limit(DBEnvObject* self)
       
  5408 {
       
  5409     int err;
       
  5410     u_int32_t gbytes, bytes;
       
  5411 
       
  5412     CHECK_ENV_NOT_CLOSED(self);
       
  5413     MYDB_BEGIN_ALLOW_THREADS;
       
  5414     err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
       
  5415     MYDB_END_ALLOW_THREADS;
       
  5416     RETURN_IF_ERR();
       
  5417     return NUMBER_FromLong(bytes);
       
  5418 }
       
  5419 #endif
       
  5420 
       
  5421 #if (DBVER >= 44)
       
  5422 static PyObject*
       
  5423 DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
       
  5424 {
       
  5425     int err;
       
  5426     int which;
       
  5427     int onoff;
       
  5428 
       
  5429     if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
       
  5430         return NULL;
       
  5431     CHECK_ENV_NOT_CLOSED(self);
       
  5432 
       
  5433     MYDB_BEGIN_ALLOW_THREADS;
       
  5434     err = self->db_env->rep_set_config(self->db_env, which, onoff);
       
  5435     MYDB_END_ALLOW_THREADS;
       
  5436     RETURN_IF_ERR();
       
  5437     RETURN_NONE();
       
  5438 }
       
  5439 
       
  5440 static PyObject*
       
  5441 DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
       
  5442 {
       
  5443     int err;
       
  5444     int which;
       
  5445     int onoff;
       
  5446 
       
  5447     if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
       
  5448         return NULL;
       
  5449     }
       
  5450     CHECK_ENV_NOT_CLOSED(self);
       
  5451     MYDB_BEGIN_ALLOW_THREADS;
       
  5452     err = self->db_env->rep_get_config(self->db_env, which, &onoff);
       
  5453     MYDB_END_ALLOW_THREADS;
       
  5454     RETURN_IF_ERR();
       
  5455     return PyBool_FromLong(onoff);
       
  5456 }
       
  5457 #endif
       
  5458 
       
  5459 #if (DBVER >= 46)
       
  5460 static PyObject*
       
  5461 DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
       
  5462 {
       
  5463     int err;
       
  5464     u_int32_t nsites, nvotes;
       
  5465 
       
  5466     if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
       
  5467         return NULL;
       
  5468     }
       
  5469     CHECK_ENV_NOT_CLOSED(self);
       
  5470     MYDB_BEGIN_ALLOW_THREADS;
       
  5471     err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
       
  5472     MYDB_END_ALLOW_THREADS;
       
  5473     RETURN_IF_ERR();
       
  5474     RETURN_NONE();
       
  5475 }
       
  5476 #endif
       
  5477 
       
  5478 static PyObject*
       
  5479 DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
       
  5480 {
       
  5481     int err;
       
  5482     PyObject *cdata_py = Py_None;
       
  5483     DBT cdata;
       
  5484     int flags;
       
  5485     static char* kwnames[] = {"flags","cdata", NULL};
       
  5486 
       
  5487     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
       
  5488                 "i|O:rep_start", kwnames, &flags, &cdata_py))
       
  5489     {
       
  5490 	    return NULL;
       
  5491     }
       
  5492     CHECK_ENV_NOT_CLOSED(self);
       
  5493 
       
  5494     if (!make_dbt(cdata_py, &cdata))
       
  5495         return NULL;
       
  5496 
       
  5497     MYDB_BEGIN_ALLOW_THREADS;
       
  5498     err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
       
  5499             flags);
       
  5500     MYDB_END_ALLOW_THREADS;
       
  5501     RETURN_IF_ERR();
       
  5502     RETURN_NONE();
       
  5503 }
       
  5504 
       
  5505 #if (DBVER >= 44)
       
  5506 static PyObject*
       
  5507 DBEnv_rep_sync(DBEnvObject* self)
       
  5508 {
       
  5509     int err;
       
  5510 
       
  5511     CHECK_ENV_NOT_CLOSED(self);
       
  5512     MYDB_BEGIN_ALLOW_THREADS;
       
  5513     err = self->db_env->rep_sync(self->db_env, 0);
       
  5514     MYDB_END_ALLOW_THREADS;
       
  5515     RETURN_IF_ERR();
       
  5516     RETURN_NONE();
       
  5517 }
       
  5518 #endif
       
  5519 
       
  5520 
       
  5521 #if (DBVER >= 45)
       
  5522 static PyObject*
       
  5523 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
       
  5524 {
       
  5525     int err;
       
  5526     int nsites;
       
  5527 
       
  5528     if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
       
  5529         return NULL;
       
  5530     }
       
  5531     CHECK_ENV_NOT_CLOSED(self);
       
  5532     MYDB_BEGIN_ALLOW_THREADS;
       
  5533     err = self->db_env->rep_set_nsites(self->db_env, nsites);
       
  5534     MYDB_END_ALLOW_THREADS;
       
  5535     RETURN_IF_ERR();
       
  5536     RETURN_NONE();
       
  5537 }
       
  5538 
       
  5539 static PyObject*
       
  5540 DBEnv_rep_get_nsites(DBEnvObject* self)
       
  5541 {
       
  5542     int err;
       
  5543 #if (DBVER >= 47)
       
  5544     u_int32_t nsites;
       
  5545 #else
       
  5546     int nsites;
       
  5547 #endif
       
  5548 
       
  5549     CHECK_ENV_NOT_CLOSED(self);
       
  5550     MYDB_BEGIN_ALLOW_THREADS;
       
  5551     err = self->db_env->rep_get_nsites(self->db_env, &nsites);
       
  5552     MYDB_END_ALLOW_THREADS;
       
  5553     RETURN_IF_ERR();
       
  5554     return NUMBER_FromLong(nsites);
       
  5555 }
       
  5556 
       
  5557 static PyObject*
       
  5558 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
       
  5559 {
       
  5560     int err;
       
  5561     int priority;
       
  5562 
       
  5563     if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
       
  5564         return NULL;
       
  5565     }
       
  5566     CHECK_ENV_NOT_CLOSED(self);
       
  5567     MYDB_BEGIN_ALLOW_THREADS;
       
  5568     err = self->db_env->rep_set_priority(self->db_env, priority);
       
  5569     MYDB_END_ALLOW_THREADS;
       
  5570     RETURN_IF_ERR();
       
  5571     RETURN_NONE();
       
  5572 }
       
  5573 
       
  5574 static PyObject*
       
  5575 DBEnv_rep_get_priority(DBEnvObject* self)
       
  5576 {
       
  5577     int err;
       
  5578 #if (DBVER >= 47)
       
  5579     u_int32_t priority;
       
  5580 #else
       
  5581     int priority;
       
  5582 #endif
       
  5583 
       
  5584     CHECK_ENV_NOT_CLOSED(self);
       
  5585     MYDB_BEGIN_ALLOW_THREADS;
       
  5586     err = self->db_env->rep_get_priority(self->db_env, &priority);
       
  5587     MYDB_END_ALLOW_THREADS;
       
  5588     RETURN_IF_ERR();
       
  5589     return NUMBER_FromLong(priority);
       
  5590 }
       
  5591 
       
  5592 static PyObject*
       
  5593 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
       
  5594 {
       
  5595     int err;
       
  5596     int which, timeout;
       
  5597 
       
  5598     if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
       
  5599         return NULL;
       
  5600     }
       
  5601     CHECK_ENV_NOT_CLOSED(self);
       
  5602     MYDB_BEGIN_ALLOW_THREADS;
       
  5603     err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
       
  5604     MYDB_END_ALLOW_THREADS;
       
  5605     RETURN_IF_ERR();
       
  5606     RETURN_NONE();
       
  5607 }
       
  5608 
       
  5609 static PyObject*
       
  5610 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
       
  5611 {
       
  5612     int err;
       
  5613     int which;
       
  5614     u_int32_t timeout;
       
  5615 
       
  5616     if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
       
  5617         return NULL;
       
  5618     }
       
  5619     CHECK_ENV_NOT_CLOSED(self);
       
  5620     MYDB_BEGIN_ALLOW_THREADS;
       
  5621     err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
       
  5622     MYDB_END_ALLOW_THREADS;
       
  5623     RETURN_IF_ERR();
       
  5624     return NUMBER_FromLong(timeout);
       
  5625 }
       
  5626 #endif
       
  5627 
       
  5628 /* --------------------------------------------------------------------- */
       
  5629 /* REPLICATION METHODS: Replication Manager */
       
  5630 
       
  5631 #if (DBVER >= 45)
       
  5632 static PyObject*
       
  5633 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
       
  5634         kwargs)
       
  5635 {
       
  5636     int err;
       
  5637     int nthreads, flags;
       
  5638     static char* kwnames[] = {"nthreads","flags", NULL};
       
  5639 
       
  5640     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
       
  5641                 "ii:repmgr_start", kwnames, &nthreads, &flags))
       
  5642     {
       
  5643 	    return NULL;
       
  5644     }
       
  5645     CHECK_ENV_NOT_CLOSED(self);
       
  5646     MYDB_BEGIN_ALLOW_THREADS;
       
  5647     err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
       
  5648     MYDB_END_ALLOW_THREADS;
       
  5649     RETURN_IF_ERR();
       
  5650     RETURN_NONE();
       
  5651 }
       
  5652 
       
  5653 static PyObject*
       
  5654 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
       
  5655         kwargs)
       
  5656 {
       
  5657     int err;
       
  5658     char *host;
       
  5659     int port;
       
  5660     int flags = 0;
       
  5661     static char* kwnames[] = {"host", "port", "flags", NULL};
       
  5662 
       
  5663     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
       
  5664                 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
       
  5665     {
       
  5666 	    return NULL;
       
  5667     }
       
  5668     CHECK_ENV_NOT_CLOSED(self);
       
  5669     MYDB_BEGIN_ALLOW_THREADS;
       
  5670     err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
       
  5671     MYDB_END_ALLOW_THREADS;
       
  5672     RETURN_IF_ERR();
       
  5673     RETURN_NONE();
       
  5674 }
       
  5675 
       
  5676 static PyObject*
       
  5677 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
       
  5678         kwargs)
       
  5679 {
       
  5680     int err;
       
  5681     char *host;
       
  5682     int port;
       
  5683     int flags = 0;
       
  5684     int eidp;
       
  5685     static char* kwnames[] = {"host", "port", "flags", NULL};
       
  5686 
       
  5687     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
       
  5688                 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
       
  5689     {
       
  5690 	    return NULL;
       
  5691     }
       
  5692     CHECK_ENV_NOT_CLOSED(self);
       
  5693     MYDB_BEGIN_ALLOW_THREADS;
       
  5694     err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
       
  5695     MYDB_END_ALLOW_THREADS;
       
  5696     RETURN_IF_ERR();
       
  5697     return NUMBER_FromLong(eidp);
       
  5698 }
       
  5699 
       
  5700 static PyObject*
       
  5701 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
       
  5702 {
       
  5703     int err;
       
  5704     int ack_policy;
       
  5705 
       
  5706     if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
       
  5707     {
       
  5708 	    return NULL;
       
  5709     }
       
  5710     CHECK_ENV_NOT_CLOSED(self);
       
  5711     MYDB_BEGIN_ALLOW_THREADS;
       
  5712     err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
       
  5713     MYDB_END_ALLOW_THREADS;
       
  5714     RETURN_IF_ERR();
       
  5715     RETURN_NONE();
       
  5716 }
       
  5717 
       
  5718 static PyObject*
       
  5719 DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
       
  5720 {
       
  5721     int err;
       
  5722     int ack_policy;
       
  5723 
       
  5724     CHECK_ENV_NOT_CLOSED(self);
       
  5725     MYDB_BEGIN_ALLOW_THREADS;
       
  5726     err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
       
  5727     MYDB_END_ALLOW_THREADS;
       
  5728     RETURN_IF_ERR();
       
  5729     return NUMBER_FromLong(ack_policy);
       
  5730 }
       
  5731 
       
  5732 static PyObject*
       
  5733 DBEnv_repmgr_site_list(DBEnvObject* self)
       
  5734 {
       
  5735     int err;
       
  5736     unsigned int countp;
       
  5737     DB_REPMGR_SITE *listp;
       
  5738     PyObject *stats, *key, *tuple;
       
  5739 
       
  5740     CHECK_ENV_NOT_CLOSED(self);
       
  5741     MYDB_BEGIN_ALLOW_THREADS;
       
  5742     err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
       
  5743     MYDB_END_ALLOW_THREADS;
       
  5744     RETURN_IF_ERR();
       
  5745 
       
  5746     stats=PyDict_New();
       
  5747     if (stats == NULL) {
       
  5748         free(listp);
       
  5749         return NULL;
       
  5750     }
       
  5751 
       
  5752     for(;countp--;) {
       
  5753         key=NUMBER_FromLong(listp[countp].eid);
       
  5754         if(!key) {
       
  5755             Py_DECREF(stats);
       
  5756             free(listp);
       
  5757             return NULL;
       
  5758         }
       
  5759 #if (PY_VERSION_HEX >= 0x02040000)
       
  5760         tuple=Py_BuildValue("(sII)", listp[countp].host,
       
  5761                 listp[countp].port, listp[countp].status);
       
  5762 #else
       
  5763         tuple=Py_BuildValue("(sii)", listp[countp].host,
       
  5764                 listp[countp].port, listp[countp].status);
       
  5765 #endif
       
  5766         if(!tuple) {
       
  5767             Py_DECREF(key);
       
  5768             Py_DECREF(stats);
       
  5769             free(listp);
       
  5770             return NULL;
       
  5771         }
       
  5772         if(PyDict_SetItem(stats, key, tuple)) {
       
  5773             Py_DECREF(key);
       
  5774             Py_DECREF(tuple);
       
  5775             Py_DECREF(stats);
       
  5776             free(listp);
       
  5777             return NULL;
       
  5778         }
       
  5779     }
       
  5780     free(listp);
       
  5781     return stats;
       
  5782 }
       
  5783 #endif
       
  5784 
       
  5785 #if (DBVER >= 46)
       
  5786 static PyObject*
       
  5787 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
       
  5788 {
       
  5789     int err;
       
  5790     int flags=0;
       
  5791     static char* kwnames[] = { "flags", NULL };
       
  5792 
       
  5793     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
       
  5794                 kwnames, &flags))
       
  5795     {
       
  5796         return NULL;
       
  5797     }
       
  5798     CHECK_ENV_NOT_CLOSED(self);
       
  5799     MYDB_BEGIN_ALLOW_THREADS;
       
  5800     err = self->db_env->repmgr_stat_print(self->db_env, flags);
       
  5801     MYDB_END_ALLOW_THREADS;
       
  5802     RETURN_IF_ERR();
       
  5803     RETURN_NONE();
       
  5804 }
       
  5805 
       
  5806 static PyObject*
       
  5807 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
       
  5808 {
       
  5809     int err;
       
  5810     int flags=0;
       
  5811     DB_REPMGR_STAT *statp;
       
  5812     PyObject *stats;
       
  5813     static char* kwnames[] = { "flags", NULL };
       
  5814 
       
  5815     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
       
  5816                 kwnames, &flags))
       
  5817     {
       
  5818         return NULL;
       
  5819     }
       
  5820     CHECK_ENV_NOT_CLOSED(self);
       
  5821     MYDB_BEGIN_ALLOW_THREADS;
       
  5822     err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
       
  5823     MYDB_END_ALLOW_THREADS;
       
  5824     RETURN_IF_ERR();
       
  5825 
       
  5826     stats=PyDict_New();
       
  5827     if (stats == NULL) {
       
  5828         free(statp);
       
  5829         return NULL;
       
  5830     }
       
  5831 
       
  5832 #define MAKE_ENTRY(name)  _addIntToDict(stats, #name, statp->st_##name)
       
  5833 
       
  5834     MAKE_ENTRY(perm_failed);
       
  5835     MAKE_ENTRY(msgs_queued);
       
  5836     MAKE_ENTRY(msgs_dropped);
       
  5837     MAKE_ENTRY(connection_drop);
       
  5838     MAKE_ENTRY(connect_fail);
       
  5839 
       
  5840 #undef MAKE_ENTRY
       
  5841 
       
  5842     free(statp);
       
  5843     return stats;
       
  5844 }
       
  5845 #endif
       
  5846 
       
  5847 
       
  5848 /* --------------------------------------------------------------------- */
       
  5849 /* DBTxn methods */
       
  5850 
       
  5851 
       
  5852 static void _close_transaction_cursors(DBTxnObject* txn)
       
  5853 {
       
  5854     PyObject *dummy;
       
  5855 
       
  5856     while(txn->children_cursors) {
       
  5857         PyErr_Warn(PyExc_RuntimeWarning,
       
  5858             "Must close cursors before resolving a transaction.");
       
  5859         dummy=DBC_close_internal(txn->children_cursors);
       
  5860         Py_XDECREF(dummy);
       
  5861     }
       
  5862 }
       
  5863 
       
  5864 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
       
  5865 {
       
  5866     DBObject *db;
       
  5867 #if (DBVER >= 43)
       
  5868     DBSequenceObject *dbs;
       
  5869 #endif
       
  5870 
       
  5871     while (txn->children_dbs) {
       
  5872         db=txn->children_dbs;
       
  5873         EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
       
  5874         if (txn->parent_txn) {
       
  5875             INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
       
  5876             db->txn=txn->parent_txn;
       
  5877         } else {
       
  5878             /* The db is already linked to its environment,
       
  5879             ** so nothing to do.
       
  5880             */
       
  5881             db->txn=NULL; 
       
  5882         }
       
  5883     }
       
  5884 
       
  5885 #if (DBVER >= 43)
       
  5886     while (txn->children_sequences) {
       
  5887         dbs=txn->children_sequences;
       
  5888         EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
       
  5889         if (txn->parent_txn) {
       
  5890             INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
       
  5891             dbs->txn=txn->parent_txn;
       
  5892         } else {
       
  5893             /* The sequence is already linked to its
       
  5894             ** parent db. Nothing to do.
       
  5895             */
       
  5896             dbs->txn=NULL;
       
  5897         }
       
  5898     }
       
  5899 #endif
       
  5900 }
       
  5901 
       
  5902 
       
  5903 static PyObject*
       
  5904 DBTxn_commit(DBTxnObject* self, PyObject* args)
       
  5905 {
       
  5906     int flags=0, err;
       
  5907     DB_TXN *txn;
       
  5908 
       
  5909     if (!PyArg_ParseTuple(args, "|i:commit", &flags))
       
  5910         return NULL;
       
  5911 
       
  5912     _close_transaction_cursors(self);
       
  5913 
       
  5914     if (!self->txn) {
       
  5915         PyObject *t =  Py_BuildValue("(is)", 0, "DBTxn must not be used "
       
  5916                                      "after txn_commit, txn_abort "
       
  5917                                      "or txn_discard");
       
  5918         if (t) {
       
  5919             PyErr_SetObject(DBError, t);
       
  5920             Py_DECREF(t);
       
  5921         }
       
  5922         return NULL;
       
  5923     }
       
  5924     self->flag_prepare=0;
       
  5925     txn = self->txn;
       
  5926     self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
       
  5927 
       
  5928     EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
       
  5929 
       
  5930     MYDB_BEGIN_ALLOW_THREADS;
       
  5931     err = txn->commit(txn, flags);
       
  5932     MYDB_END_ALLOW_THREADS;
       
  5933 
       
  5934     _promote_transaction_dbs_and_sequences(self);
       
  5935 
       
  5936     RETURN_IF_ERR();
       
  5937     RETURN_NONE();
       
  5938 }
       
  5939 
       
  5940 static PyObject*
       
  5941 DBTxn_prepare(DBTxnObject* self, PyObject* args)
       
  5942 {
       
  5943     int err;
       
  5944     char* gid=NULL;
       
  5945     int   gid_size=0;
       
  5946 
       
  5947     if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
       
  5948         return NULL;
       
  5949 
       
  5950     if (gid_size != DB_XIDDATASIZE) {
       
  5951         PyErr_SetString(PyExc_TypeError,
       
  5952                         "gid must be DB_XIDDATASIZE bytes long");
       
  5953         return NULL;
       
  5954     }
       
  5955 
       
  5956     if (!self->txn) {
       
  5957         PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
       
  5958                                     "after txn_commit, txn_abort "
       
  5959                                     "or txn_discard");
       
  5960         if (t) {
       
  5961             PyErr_SetObject(DBError, t);
       
  5962             Py_DECREF(t);
       
  5963         }
       
  5964         return NULL;
       
  5965     }
       
  5966     self->flag_prepare=1;  /* Prepare state */
       
  5967     MYDB_BEGIN_ALLOW_THREADS;
       
  5968     err = self->txn->prepare(self->txn, (u_int8_t*)gid);
       
  5969     MYDB_END_ALLOW_THREADS;
       
  5970     RETURN_IF_ERR();
       
  5971     RETURN_NONE();
       
  5972 }
       
  5973 
       
  5974 
       
  5975 static PyObject*
       
  5976 DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
       
  5977 {
       
  5978     PyObject *dummy;
       
  5979     int err=0;
       
  5980     DB_TXN *txn;
       
  5981 
       
  5982     if (!self->txn) {
       
  5983         PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
       
  5984                                     "after txn_commit, txn_abort "
       
  5985                                     "or txn_discard");
       
  5986         if (t) {
       
  5987             PyErr_SetObject(DBError, t);
       
  5988             Py_DECREF(t);
       
  5989         }
       
  5990         return NULL;
       
  5991     }
       
  5992     txn = self->txn;
       
  5993     self->txn = NULL;   /* this DB_TXN is no longer valid after this call */
       
  5994 
       
  5995     _close_transaction_cursors(self);
       
  5996 #if (DBVER >= 43)
       
  5997     while (self->children_sequences) {
       
  5998         dummy=DBSequence_close_internal(self->children_sequences,0,0);
       
  5999         Py_XDECREF(dummy);
       
  6000     }
       
  6001 #endif
       
  6002     while (self->children_dbs) {
       
  6003         dummy=DB_close_internal(self->children_dbs, 0, 0);
       
  6004         Py_XDECREF(dummy);
       
  6005     }
       
  6006 
       
  6007     EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
       
  6008 
       
  6009     MYDB_BEGIN_ALLOW_THREADS;
       
  6010     if (discard) {
       
  6011         assert(!self->flag_prepare);
       
  6012         err = txn->discard(txn,0);
       
  6013     } else {
       
  6014         /*
       
  6015         ** If the transaction is in the "prepare" or "recover" state,
       
  6016         ** we better do not implicitly abort it.
       
  6017         */
       
  6018         if (!self->flag_prepare) {
       
  6019             err = txn->abort(txn);
       
  6020         }
       
  6021     }
       
  6022     MYDB_END_ALLOW_THREADS;
       
  6023     RETURN_IF_ERR();
       
  6024     RETURN_NONE();
       
  6025 }
       
  6026 
       
  6027 static PyObject*
       
  6028 DBTxn_abort(DBTxnObject* self)
       
  6029 {
       
  6030     self->flag_prepare=0;
       
  6031     _close_transaction_cursors(self);
       
  6032 
       
  6033     return DBTxn_abort_discard_internal(self,0);
       
  6034 }
       
  6035 
       
  6036 static PyObject*
       
  6037 DBTxn_discard(DBTxnObject* self)
       
  6038 {
       
  6039     self->flag_prepare=0;
       
  6040     _close_transaction_cursors(self);
       
  6041 
       
  6042     return DBTxn_abort_discard_internal(self,1);
       
  6043 }
       
  6044 
       
  6045 
       
  6046 static PyObject*
       
  6047 DBTxn_id(DBTxnObject* self)
       
  6048 {
       
  6049     int id;
       
  6050 
       
  6051     if (!self->txn) {
       
  6052         PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
       
  6053                                     "after txn_commit, txn_abort "
       
  6054                                     "or txn_discard");
       
  6055         if (t) {
       
  6056             PyErr_SetObject(DBError, t);
       
  6057             Py_DECREF(t);
       
  6058         }
       
  6059         return NULL;
       
  6060     }
       
  6061     MYDB_BEGIN_ALLOW_THREADS;
       
  6062     id = self->txn->id(self->txn);
       
  6063     MYDB_END_ALLOW_THREADS;
       
  6064     return NUMBER_FromLong(id);
       
  6065 }
       
  6066 
       
  6067 #if (DBVER >= 43)
       
  6068 /* --------------------------------------------------------------------- */
       
  6069 /* DBSequence methods */
       
  6070 
       
  6071 
       
  6072 static PyObject*
       
  6073 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
       
  6074 {
       
  6075     int err=0;
       
  6076 
       
  6077     if (self->sequence!=NULL) {
       
  6078         EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
       
  6079         if (self->txn) {
       
  6080             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
       
  6081             self->txn=NULL;
       
  6082         }
       
  6083 
       
  6084         /*
       
  6085         ** "do_not_close" is used to dispose all related objects in the
       
  6086         ** tree, without actually releasing the "root" object.
       
  6087         ** This is done, for example, because function calls like
       
  6088         ** "DBSequence.remove()" implicitly close the underlying handle. So
       
  6089         ** the handle doesn't need to be closed, but related objects
       
  6090         ** must be cleaned up.
       
  6091         */
       
  6092         if (!do_not_close) {
       
  6093             MYDB_BEGIN_ALLOW_THREADS
       
  6094             err = self->sequence->close(self->sequence, flags);
       
  6095             MYDB_END_ALLOW_THREADS
       
  6096         }
       
  6097         self->sequence = NULL;
       
  6098 
       
  6099         RETURN_IF_ERR();
       
  6100     }
       
  6101 
       
  6102     RETURN_NONE();
       
  6103 }
       
  6104 
       
  6105 static PyObject*
       
  6106 DBSequence_close(DBSequenceObject* self, PyObject* args)
       
  6107 {
       
  6108     int flags=0;
       
  6109     if (!PyArg_ParseTuple(args,"|i:close", &flags))
       
  6110         return NULL;
       
  6111 
       
  6112     return DBSequence_close_internal(self,flags,0);
       
  6113 }
       
  6114 
       
  6115 static PyObject*
       
  6116 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
       
  6117 {
       
  6118     int err, flags = 0;
       
  6119     int delta = 1;
       
  6120     db_seq_t value;
       
  6121     PyObject *txnobj = NULL;
       
  6122     DB_TXN *txn = NULL;
       
  6123     static char* kwnames[] = {"delta", "txn", "flags", NULL };
       
  6124     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
       
  6125         return NULL;
       
  6126     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6127 
       
  6128     if (!checkTxnObj(txnobj, &txn))
       
  6129         return NULL;
       
  6130 
       
  6131     MYDB_BEGIN_ALLOW_THREADS
       
  6132     err = self->sequence->get(self->sequence, txn, delta, &value, flags);
       
  6133     MYDB_END_ALLOW_THREADS
       
  6134 
       
  6135     RETURN_IF_ERR();
       
  6136     return PyLong_FromLongLong(value);
       
  6137 }
       
  6138 
       
  6139 static PyObject*
       
  6140 DBSequence_get_dbp(DBSequenceObject* self)
       
  6141 {
       
  6142     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6143     Py_INCREF(self->mydb);
       
  6144     return (PyObject* )self->mydb;
       
  6145 }
       
  6146 
       
  6147 static PyObject*
       
  6148 DBSequence_get_key(DBSequenceObject* self)
       
  6149 {
       
  6150     int err;
       
  6151     DBT key;
       
  6152     PyObject *retval = NULL;
       
  6153 
       
  6154     key.flags = DB_DBT_MALLOC;
       
  6155     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6156     MYDB_BEGIN_ALLOW_THREADS
       
  6157     err = self->sequence->get_key(self->sequence, &key);
       
  6158     MYDB_END_ALLOW_THREADS
       
  6159 
       
  6160     if (!err)
       
  6161         retval = Build_PyString(key.data, key.size);
       
  6162 
       
  6163     FREE_DBT(key);
       
  6164     RETURN_IF_ERR();
       
  6165 
       
  6166     return retval;
       
  6167 }
       
  6168 
       
  6169 static PyObject*
       
  6170 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
       
  6171 {
       
  6172     int err;
       
  6173     PY_LONG_LONG value;
       
  6174     db_seq_t value2;
       
  6175     if (!PyArg_ParseTuple(args,"L:init_value", &value))
       
  6176         return NULL;
       
  6177     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6178 
       
  6179     value2=value; /* If truncation, compiler should show a warning */
       
  6180     MYDB_BEGIN_ALLOW_THREADS
       
  6181     err = self->sequence->initial_value(self->sequence, value2);
       
  6182     MYDB_END_ALLOW_THREADS
       
  6183 
       
  6184     RETURN_IF_ERR();
       
  6185 
       
  6186     RETURN_NONE();
       
  6187 }
       
  6188 
       
  6189 static PyObject*
       
  6190 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
       
  6191 {
       
  6192     int err, flags = 0;
       
  6193     PyObject* keyobj;
       
  6194     PyObject *txnobj = NULL;
       
  6195     DB_TXN *txn = NULL;
       
  6196     DBT key;
       
  6197 
       
  6198     static char* kwnames[] = {"key", "txn", "flags", NULL };
       
  6199     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
       
  6200         return NULL;
       
  6201 
       
  6202     if (!checkTxnObj(txnobj, &txn))
       
  6203         return NULL;
       
  6204 
       
  6205     if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
       
  6206         return NULL;
       
  6207 
       
  6208     MYDB_BEGIN_ALLOW_THREADS
       
  6209     err = self->sequence->open(self->sequence, txn, &key, flags);
       
  6210     MYDB_END_ALLOW_THREADS
       
  6211 
       
  6212     FREE_DBT(key);
       
  6213     RETURN_IF_ERR();
       
  6214 
       
  6215     if (txn) {
       
  6216         INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
       
  6217         self->txn=(DBTxnObject *)txnobj;
       
  6218     }
       
  6219 
       
  6220     RETURN_NONE();
       
  6221 }
       
  6222 
       
  6223 static PyObject*
       
  6224 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
       
  6225 {
       
  6226     PyObject *dummy;
       
  6227     int err, flags = 0;
       
  6228     PyObject *txnobj = NULL;
       
  6229     DB_TXN *txn = NULL;
       
  6230 
       
  6231     static char* kwnames[] = {"txn", "flags", NULL };
       
  6232     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
       
  6233         return NULL;
       
  6234 
       
  6235     if (!checkTxnObj(txnobj, &txn))
       
  6236         return NULL;
       
  6237 
       
  6238     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6239 
       
  6240     MYDB_BEGIN_ALLOW_THREADS
       
  6241     err = self->sequence->remove(self->sequence, txn, flags);
       
  6242     MYDB_END_ALLOW_THREADS
       
  6243 
       
  6244     dummy=DBSequence_close_internal(self,flags,1);
       
  6245     Py_XDECREF(dummy);
       
  6246 
       
  6247     RETURN_IF_ERR();
       
  6248     RETURN_NONE();
       
  6249 }
       
  6250 
       
  6251 static PyObject*
       
  6252 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
       
  6253 {
       
  6254     int err, size;
       
  6255     if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
       
  6256         return NULL;
       
  6257     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6258 
       
  6259     MYDB_BEGIN_ALLOW_THREADS
       
  6260     err = self->sequence->set_cachesize(self->sequence, size);
       
  6261     MYDB_END_ALLOW_THREADS
       
  6262 
       
  6263     RETURN_IF_ERR();
       
  6264     RETURN_NONE();
       
  6265 }
       
  6266 
       
  6267 static PyObject*
       
  6268 DBSequence_get_cachesize(DBSequenceObject* self)
       
  6269 {
       
  6270     int err, size;
       
  6271 
       
  6272     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6273 
       
  6274     MYDB_BEGIN_ALLOW_THREADS
       
  6275     err = self->sequence->get_cachesize(self->sequence, &size);
       
  6276     MYDB_END_ALLOW_THREADS
       
  6277 
       
  6278     RETURN_IF_ERR();
       
  6279     return NUMBER_FromLong(size);
       
  6280 }
       
  6281 
       
  6282 static PyObject*
       
  6283 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
       
  6284 {
       
  6285     int err, flags = 0;
       
  6286     if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
       
  6287         return NULL;
       
  6288     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6289 
       
  6290     MYDB_BEGIN_ALLOW_THREADS
       
  6291     err = self->sequence->set_flags(self->sequence, flags);
       
  6292     MYDB_END_ALLOW_THREADS
       
  6293 
       
  6294     RETURN_IF_ERR();
       
  6295     RETURN_NONE();
       
  6296 }
       
  6297 
       
  6298 static PyObject*
       
  6299 DBSequence_get_flags(DBSequenceObject* self)
       
  6300 {
       
  6301     unsigned int flags;
       
  6302     int err;
       
  6303 
       
  6304     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6305 
       
  6306     MYDB_BEGIN_ALLOW_THREADS
       
  6307     err = self->sequence->get_flags(self->sequence, &flags);
       
  6308     MYDB_END_ALLOW_THREADS
       
  6309 
       
  6310     RETURN_IF_ERR();
       
  6311     return NUMBER_FromLong((int)flags);
       
  6312 }
       
  6313 
       
  6314 static PyObject*
       
  6315 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
       
  6316 {
       
  6317     int err;
       
  6318     PY_LONG_LONG min, max;
       
  6319     db_seq_t min2, max2;
       
  6320     if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
       
  6321         return NULL;
       
  6322     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6323 
       
  6324     min2=min;  /* If truncation, compiler should show a warning */
       
  6325     max2=max;
       
  6326     MYDB_BEGIN_ALLOW_THREADS
       
  6327     err = self->sequence->set_range(self->sequence, min2, max2);
       
  6328     MYDB_END_ALLOW_THREADS
       
  6329 
       
  6330     RETURN_IF_ERR();
       
  6331     RETURN_NONE();
       
  6332 }
       
  6333 
       
  6334 static PyObject*
       
  6335 DBSequence_get_range(DBSequenceObject* self)
       
  6336 {
       
  6337     int err;
       
  6338     PY_LONG_LONG min, max;
       
  6339     db_seq_t min2, max2;
       
  6340 
       
  6341     CHECK_SEQUENCE_NOT_CLOSED(self)
       
  6342 
       
  6343     MYDB_BEGIN_ALLOW_THREADS
       
  6344     err = self->sequence->get_range(self->sequence, &min2, &max2);
       
  6345     MYDB_END_ALLOW_THREADS
       
  6346 
       
  6347     RETURN_IF_ERR();
       
  6348     min=min2;  /* If truncation, compiler should show a warning */
       
  6349     max=max2;
       
  6350     return Py_BuildValue("(LL)", min, max);
       
  6351 }
       
  6352 
       
  6353 static PyObject*
       
  6354 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
       
  6355 {
       
  6356     int err, flags = 0;
       
  6357     DB_SEQUENCE_STAT* sp = NULL;
       
  6358     PyObject* dict_stat;
       
  6359     static char* kwnames[] = {"flags", NULL };
       
  6360     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
       
  6361         return NULL;
       
  6362     CHECK_SEQUENCE_NOT_CLOSED(self);
       
  6363 
       
  6364     MYDB_BEGIN_ALLOW_THREADS;
       
  6365     err = self->sequence->stat(self->sequence, &sp, flags);
       
  6366     MYDB_END_ALLOW_THREADS;
       
  6367     RETURN_IF_ERR();
       
  6368 
       
  6369     if ((dict_stat = PyDict_New()) == NULL) {
       
  6370         free(sp);
       
  6371         return NULL;
       
  6372     }
       
  6373 
       
  6374 
       
  6375 #define MAKE_INT_ENTRY(name)  _addIntToDict(dict_stat, #name, sp->st_##name)
       
  6376 #define MAKE_LONG_LONG_ENTRY(name)  _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
       
  6377 
       
  6378     MAKE_INT_ENTRY(wait);
       
  6379     MAKE_INT_ENTRY(nowait);
       
  6380     MAKE_LONG_LONG_ENTRY(current);
       
  6381     MAKE_LONG_LONG_ENTRY(value);
       
  6382     MAKE_LONG_LONG_ENTRY(last_value);
       
  6383     MAKE_LONG_LONG_ENTRY(min);
       
  6384     MAKE_LONG_LONG_ENTRY(max);
       
  6385     MAKE_INT_ENTRY(cache_size);
       
  6386     MAKE_INT_ENTRY(flags);
       
  6387 
       
  6388 #undef MAKE_INT_ENTRY
       
  6389 #undef MAKE_LONG_LONG_ENTRY
       
  6390 
       
  6391     free(sp);
       
  6392     return dict_stat;
       
  6393 }
       
  6394 #endif
       
  6395 
       
  6396 
       
  6397 /* --------------------------------------------------------------------- */
       
  6398 /* Method definition tables and type objects */
       
  6399 
       
  6400 static PyMethodDef DB_methods[] = {
       
  6401     {"append",          (PyCFunction)DB_append,         METH_VARARGS|METH_KEYWORDS},
       
  6402     {"associate",       (PyCFunction)DB_associate,      METH_VARARGS|METH_KEYWORDS},
       
  6403     {"close",           (PyCFunction)DB_close,          METH_VARARGS},
       
  6404     {"consume",         (PyCFunction)DB_consume,        METH_VARARGS|METH_KEYWORDS},
       
  6405     {"consume_wait",    (PyCFunction)DB_consume_wait,   METH_VARARGS|METH_KEYWORDS},
       
  6406     {"cursor",          (PyCFunction)DB_cursor,         METH_VARARGS|METH_KEYWORDS},
       
  6407     {"delete",          (PyCFunction)DB_delete,         METH_VARARGS|METH_KEYWORDS},
       
  6408     {"fd",              (PyCFunction)DB_fd,             METH_NOARGS},
       
  6409     {"get",             (PyCFunction)DB_get,            METH_VARARGS|METH_KEYWORDS},
       
  6410     {"pget",            (PyCFunction)DB_pget,           METH_VARARGS|METH_KEYWORDS},
       
  6411     {"get_both",        (PyCFunction)DB_get_both,       METH_VARARGS|METH_KEYWORDS},
       
  6412     {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
       
  6413     {"get_size",        (PyCFunction)DB_get_size,       METH_VARARGS|METH_KEYWORDS},
       
  6414     {"get_type",        (PyCFunction)DB_get_type,       METH_NOARGS},
       
  6415     {"join",            (PyCFunction)DB_join,           METH_VARARGS},
       
  6416     {"key_range",       (PyCFunction)DB_key_range,      METH_VARARGS|METH_KEYWORDS},
       
  6417     {"has_key",         (PyCFunction)DB_has_key,        METH_VARARGS|METH_KEYWORDS},
       
  6418     {"items",           (PyCFunction)DB_items,          METH_VARARGS},
       
  6419     {"keys",            (PyCFunction)DB_keys,           METH_VARARGS},
       
  6420     {"open",            (PyCFunction)DB_open,           METH_VARARGS|METH_KEYWORDS},
       
  6421     {"put",             (PyCFunction)DB_put,            METH_VARARGS|METH_KEYWORDS},
       
  6422     {"remove",          (PyCFunction)DB_remove,         METH_VARARGS|METH_KEYWORDS},
       
  6423     {"rename",          (PyCFunction)DB_rename,         METH_VARARGS},
       
  6424     {"set_bt_minkey",   (PyCFunction)DB_set_bt_minkey,  METH_VARARGS},
       
  6425     {"set_bt_compare",  (PyCFunction)DB_set_bt_compare, METH_O},
       
  6426     {"set_cachesize",   (PyCFunction)DB_set_cachesize,  METH_VARARGS},
       
  6427 #if (DBVER >= 41)
       
  6428     {"set_encrypt",     (PyCFunction)DB_set_encrypt,    METH_VARARGS|METH_KEYWORDS},
       
  6429 #endif
       
  6430     {"set_flags",       (PyCFunction)DB_set_flags,      METH_VARARGS},
       
  6431     {"set_h_ffactor",   (PyCFunction)DB_set_h_ffactor,  METH_VARARGS},
       
  6432     {"set_h_nelem",     (PyCFunction)DB_set_h_nelem,    METH_VARARGS},
       
  6433     {"set_lorder",      (PyCFunction)DB_set_lorder,     METH_VARARGS},
       
  6434     {"set_pagesize",    (PyCFunction)DB_set_pagesize,   METH_VARARGS},
       
  6435     {"set_re_delim",    (PyCFunction)DB_set_re_delim,   METH_VARARGS},
       
  6436     {"set_re_len",      (PyCFunction)DB_set_re_len,     METH_VARARGS},
       
  6437     {"set_re_pad",      (PyCFunction)DB_set_re_pad,     METH_VARARGS},
       
  6438     {"set_re_source",   (PyCFunction)DB_set_re_source,  METH_VARARGS},
       
  6439     {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
       
  6440     {"set_private",     (PyCFunction)DB_set_private,    METH_O},
       
  6441     {"get_private",     (PyCFunction)DB_get_private,    METH_NOARGS},
       
  6442     {"stat",            (PyCFunction)DB_stat,           METH_VARARGS|METH_KEYWORDS},
       
  6443     {"sync",            (PyCFunction)DB_sync,           METH_VARARGS},
       
  6444     {"truncate",        (PyCFunction)DB_truncate,       METH_VARARGS|METH_KEYWORDS},
       
  6445     {"type",            (PyCFunction)DB_get_type,       METH_NOARGS},
       
  6446     {"upgrade",         (PyCFunction)DB_upgrade,        METH_VARARGS},
       
  6447     {"values",          (PyCFunction)DB_values,         METH_VARARGS},
       
  6448     {"verify",          (PyCFunction)DB_verify,         METH_VARARGS|METH_KEYWORDS},
       
  6449     {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none,      METH_VARARGS},
       
  6450     {NULL,      NULL}       /* sentinel */
       
  6451 };
       
  6452 
       
  6453 
       
  6454 static PyMappingMethods DB_mapping = {
       
  6455         DB_length,                   /*mp_length*/
       
  6456         (binaryfunc)DB_subscript,    /*mp_subscript*/
       
  6457         (objobjargproc)DB_ass_sub,   /*mp_ass_subscript*/
       
  6458 };
       
  6459 
       
  6460 
       
  6461 static PyMethodDef DBCursor_methods[] = {
       
  6462     {"close",           (PyCFunction)DBC_close,         METH_NOARGS},
       
  6463     {"count",           (PyCFunction)DBC_count,         METH_VARARGS},
       
  6464     {"current",         (PyCFunction)DBC_current,       METH_VARARGS|METH_KEYWORDS},
       
  6465     {"delete",          (PyCFunction)DBC_delete,        METH_VARARGS},
       
  6466     {"dup",             (PyCFunction)DBC_dup,           METH_VARARGS},
       
  6467     {"first",           (PyCFunction)DBC_first,         METH_VARARGS|METH_KEYWORDS},
       
  6468     {"get",             (PyCFunction)DBC_get,           METH_VARARGS|METH_KEYWORDS},
       
  6469     {"pget",            (PyCFunction)DBC_pget,          METH_VARARGS|METH_KEYWORDS},
       
  6470     {"get_recno",       (PyCFunction)DBC_get_recno,     METH_NOARGS},
       
  6471     {"last",            (PyCFunction)DBC_last,          METH_VARARGS|METH_KEYWORDS},
       
  6472     {"next",            (PyCFunction)DBC_next,          METH_VARARGS|METH_KEYWORDS},
       
  6473     {"prev",            (PyCFunction)DBC_prev,          METH_VARARGS|METH_KEYWORDS},
       
  6474     {"put",             (PyCFunction)DBC_put,           METH_VARARGS|METH_KEYWORDS},
       
  6475     {"set",             (PyCFunction)DBC_set,           METH_VARARGS|METH_KEYWORDS},
       
  6476     {"set_range",       (PyCFunction)DBC_set_range,     METH_VARARGS|METH_KEYWORDS},
       
  6477     {"get_both",        (PyCFunction)DBC_get_both,      METH_VARARGS},
       
  6478     {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
       
  6479     {"set_both",        (PyCFunction)DBC_set_both,      METH_VARARGS},
       
  6480     {"set_recno",       (PyCFunction)DBC_set_recno,     METH_VARARGS|METH_KEYWORDS},
       
  6481     {"consume",         (PyCFunction)DBC_consume,       METH_VARARGS|METH_KEYWORDS},
       
  6482     {"next_dup",        (PyCFunction)DBC_next_dup,      METH_VARARGS|METH_KEYWORDS},
       
  6483     {"next_nodup",      (PyCFunction)DBC_next_nodup,    METH_VARARGS|METH_KEYWORDS},
       
  6484     {"prev_nodup",      (PyCFunction)DBC_prev_nodup,    METH_VARARGS|METH_KEYWORDS},
       
  6485     {"join_item",       (PyCFunction)DBC_join_item,     METH_VARARGS},
       
  6486     {NULL,      NULL}       /* sentinel */
       
  6487 };
       
  6488 
       
  6489 
       
  6490 static PyMethodDef DBEnv_methods[] = {
       
  6491     {"close",           (PyCFunction)DBEnv_close,            METH_VARARGS},
       
  6492     {"open",            (PyCFunction)DBEnv_open,             METH_VARARGS},
       
  6493     {"remove",          (PyCFunction)DBEnv_remove,           METH_VARARGS},
       
  6494 #if (DBVER >= 41)
       
  6495     {"dbremove",        (PyCFunction)DBEnv_dbremove,         METH_VARARGS|METH_KEYWORDS},
       
  6496     {"dbrename",        (PyCFunction)DBEnv_dbrename,         METH_VARARGS|METH_KEYWORDS},
       
  6497     {"set_encrypt",     (PyCFunction)DBEnv_set_encrypt,      METH_VARARGS|METH_KEYWORDS},
       
  6498 #endif
       
  6499     {"set_timeout",     (PyCFunction)DBEnv_set_timeout,      METH_VARARGS|METH_KEYWORDS},
       
  6500     {"set_shm_key",     (PyCFunction)DBEnv_set_shm_key,      METH_VARARGS},
       
  6501     {"set_cachesize",   (PyCFunction)DBEnv_set_cachesize,    METH_VARARGS},
       
  6502     {"set_data_dir",    (PyCFunction)DBEnv_set_data_dir,     METH_VARARGS},
       
  6503     {"set_flags",       (PyCFunction)DBEnv_set_flags,        METH_VARARGS},
       
  6504 #if (DBVER >= 47)
       
  6505     {"log_set_config",  (PyCFunction)DBEnv_log_set_config,   METH_VARARGS},
       
  6506 #endif
       
  6507     {"set_lg_bsize",    (PyCFunction)DBEnv_set_lg_bsize,     METH_VARARGS},
       
  6508     {"set_lg_dir",      (PyCFunction)DBEnv_set_lg_dir,       METH_VARARGS},
       
  6509     {"set_lg_max",      (PyCFunction)DBEnv_set_lg_max,       METH_VARARGS},
       
  6510 #if (DBVER >= 42)
       
  6511     {"get_lg_max",      (PyCFunction)DBEnv_get_lg_max,       METH_NOARGS},
       
  6512 #endif
       
  6513     {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
       
  6514     {"set_lk_detect",   (PyCFunction)DBEnv_set_lk_detect,    METH_VARARGS},
       
  6515 #if (DBVER < 45)
       
  6516     {"set_lk_max",      (PyCFunction)DBEnv_set_lk_max,       METH_VARARGS},
       
  6517 #endif
       
  6518     {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
       
  6519     {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
       
  6520     {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
       
  6521     {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize,  METH_VARARGS},
       
  6522     {"set_tmp_dir",     (PyCFunction)DBEnv_set_tmp_dir,      METH_VARARGS},
       
  6523     {"txn_begin",       (PyCFunction)DBEnv_txn_begin,        METH_VARARGS|METH_KEYWORDS},
       
  6524     {"txn_checkpoint",  (PyCFunction)DBEnv_txn_checkpoint,   METH_VARARGS},
       
  6525     {"txn_stat",        (PyCFunction)DBEnv_txn_stat,         METH_VARARGS},
       
  6526     {"set_tx_max",      (PyCFunction)DBEnv_set_tx_max,       METH_VARARGS},
       
  6527     {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
       
  6528     {"lock_detect",     (PyCFunction)DBEnv_lock_detect,      METH_VARARGS},
       
  6529     {"lock_get",        (PyCFunction)DBEnv_lock_get,         METH_VARARGS},
       
  6530     {"lock_id",         (PyCFunction)DBEnv_lock_id,          METH_NOARGS},
       
  6531     {"lock_id_free",    (PyCFunction)DBEnv_lock_id_free,     METH_VARARGS},
       
  6532     {"lock_put",        (PyCFunction)DBEnv_lock_put,         METH_VARARGS},
       
  6533     {"lock_stat",       (PyCFunction)DBEnv_lock_stat,        METH_VARARGS},
       
  6534     {"log_archive",     (PyCFunction)DBEnv_log_archive,      METH_VARARGS},
       
  6535     {"log_flush",       (PyCFunction)DBEnv_log_flush,        METH_NOARGS},
       
  6536     {"log_stat",        (PyCFunction)DBEnv_log_stat,         METH_VARARGS},
       
  6537 #if (DBVER >= 44)
       
  6538     {"lsn_reset",       (PyCFunction)DBEnv_lsn_reset,        METH_VARARGS|METH_KEYWORDS},
       
  6539 #endif
       
  6540     {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
       
  6541     {"txn_recover",     (PyCFunction)DBEnv_txn_recover,       METH_NOARGS},
       
  6542     {"set_rpc_server",  (PyCFunction)DBEnv_set_rpc_server,
       
  6543         METH_VARARGS||METH_KEYWORDS},
       
  6544     {"set_verbose",     (PyCFunction)DBEnv_set_verbose,       METH_VARARGS},
       
  6545 #if (DBVER >= 42)
       
  6546     {"get_verbose",     (PyCFunction)DBEnv_get_verbose,       METH_VARARGS},
       
  6547 #endif
       
  6548     {"set_private",     (PyCFunction)DBEnv_set_private,       METH_O},
       
  6549     {"get_private",     (PyCFunction)DBEnv_get_private,       METH_NOARGS},
       
  6550     {"rep_start",       (PyCFunction)DBEnv_rep_start,
       
  6551         METH_VARARGS|METH_KEYWORDS},
       
  6552     {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
       
  6553     {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
       
  6554         METH_VARARGS},
       
  6555 #if (DBVER >= 46)
       
  6556     {"rep_elect",       (PyCFunction)DBEnv_rep_elect,         METH_VARARGS},
       
  6557 #endif
       
  6558 #if (DBVER >= 44)
       
  6559     {"rep_set_config",  (PyCFunction)DBEnv_rep_set_config,    METH_VARARGS},
       
  6560     {"rep_get_config",  (PyCFunction)DBEnv_rep_get_config,    METH_VARARGS},
       
  6561     {"rep_sync",        (PyCFunction)DBEnv_rep_sync,          METH_NOARGS},
       
  6562 #endif
       
  6563 #if (DBVER >= 45)
       
  6564     {"rep_set_limit",   (PyCFunction)DBEnv_rep_set_limit,     METH_VARARGS},
       
  6565     {"rep_get_limit",   (PyCFunction)DBEnv_rep_get_limit,     METH_NOARGS},
       
  6566 #endif
       
  6567 #if (DBVER >= 47)
       
  6568     {"rep_set_request", (PyCFunction)DBEnv_rep_set_request,   METH_VARARGS},
       
  6569     {"rep_get_request", (PyCFunction)DBEnv_rep_get_request,   METH_NOARGS},
       
  6570 #endif
       
  6571 #if (DBVER >= 45)
       
  6572     {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
       
  6573 #endif
       
  6574 #if (DBVER >= 45)
       
  6575     {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
       
  6576     {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
       
  6577     {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
       
  6578     {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
       
  6579     {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
       
  6580     {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
       
  6581 #endif
       
  6582 #if (DBVER >= 45)
       
  6583     {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
       
  6584         METH_VARARGS|METH_KEYWORDS},
       
  6585     {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
       
  6586         METH_VARARGS|METH_KEYWORDS},
       
  6587     {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
       
  6588         METH_VARARGS|METH_KEYWORDS},
       
  6589     {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
       
  6590         METH_VARARGS},
       
  6591     {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
       
  6592         METH_NOARGS},
       
  6593     {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
       
  6594         METH_NOARGS},
       
  6595 #endif
       
  6596 #if (DBVER >= 46)
       
  6597     {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
       
  6598         METH_VARARGS|METH_KEYWORDS},
       
  6599     {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
       
  6600         METH_VARARGS|METH_KEYWORDS},
       
  6601 #endif
       
  6602     {NULL,      NULL}       /* sentinel */
       
  6603 };
       
  6604 
       
  6605 
       
  6606 static PyMethodDef DBTxn_methods[] = {
       
  6607     {"commit",          (PyCFunction)DBTxn_commit,      METH_VARARGS},
       
  6608     {"prepare",         (PyCFunction)DBTxn_prepare,     METH_VARARGS},
       
  6609     {"discard",         (PyCFunction)DBTxn_discard,     METH_NOARGS},
       
  6610     {"abort",           (PyCFunction)DBTxn_abort,       METH_NOARGS},
       
  6611     {"id",              (PyCFunction)DBTxn_id,          METH_NOARGS},
       
  6612     {NULL,      NULL}       /* sentinel */
       
  6613 };
       
  6614 
       
  6615 
       
  6616 #if (DBVER >= 43)
       
  6617 static PyMethodDef DBSequence_methods[] = {
       
  6618     {"close",           (PyCFunction)DBSequence_close,          METH_VARARGS},
       
  6619     {"get",             (PyCFunction)DBSequence_get,            METH_VARARGS|METH_KEYWORDS},
       
  6620     {"get_dbp",         (PyCFunction)DBSequence_get_dbp,        METH_NOARGS},
       
  6621     {"get_key",         (PyCFunction)DBSequence_get_key,        METH_NOARGS},
       
  6622     {"init_value",      (PyCFunction)DBSequence_init_value,     METH_VARARGS},
       
  6623     {"open",            (PyCFunction)DBSequence_open,           METH_VARARGS|METH_KEYWORDS},
       
  6624     {"remove",          (PyCFunction)DBSequence_remove,         METH_VARARGS|METH_KEYWORDS},
       
  6625     {"set_cachesize",   (PyCFunction)DBSequence_set_cachesize,  METH_VARARGS},
       
  6626     {"get_cachesize",   (PyCFunction)DBSequence_get_cachesize,  METH_NOARGS},
       
  6627     {"set_flags",       (PyCFunction)DBSequence_set_flags,      METH_VARARGS},
       
  6628     {"get_flags",       (PyCFunction)DBSequence_get_flags,      METH_NOARGS},
       
  6629     {"set_range",       (PyCFunction)DBSequence_set_range,      METH_VARARGS},
       
  6630     {"get_range",       (PyCFunction)DBSequence_get_range,      METH_NOARGS},
       
  6631     {"stat",            (PyCFunction)DBSequence_stat,           METH_VARARGS|METH_KEYWORDS},
       
  6632     {NULL,      NULL}       /* sentinel */
       
  6633 };
       
  6634 #endif
       
  6635 
       
  6636 
       
  6637 static PyObject*
       
  6638 DBEnv_db_home_get(DBEnvObject* self)
       
  6639 {
       
  6640     const char *home = NULL;
       
  6641 
       
  6642     CHECK_ENV_NOT_CLOSED(self);
       
  6643 
       
  6644 #if (DBVER >= 42)
       
  6645     self->db_env->get_home(self->db_env, &home);
       
  6646 #else
       
  6647     home=self->db_env->db_home;
       
  6648 #endif
       
  6649 
       
  6650     if (home == NULL) {
       
  6651         RETURN_NONE();
       
  6652     }
       
  6653     return PyBytes_FromString(home);
       
  6654 }
       
  6655 
       
  6656 static PyGetSetDef DBEnv_getsets[] = {
       
  6657     {"db_home", (getter)DBEnv_db_home_get, NULL,},
       
  6658     {NULL}
       
  6659 };
       
  6660 
       
  6661 
       
  6662 statichere PyTypeObject DB_Type = {
       
  6663 #if (PY_VERSION_HEX < 0x03000000)
       
  6664     PyObject_HEAD_INIT(NULL)
       
  6665     0,                  /*ob_size*/
       
  6666 #else
       
  6667     PyVarObject_HEAD_INIT(NULL, 0)
       
  6668 #endif
       
  6669     "DB",               /*tp_name*/
       
  6670     sizeof(DBObject),   /*tp_basicsize*/
       
  6671     0,                  /*tp_itemsize*/
       
  6672     /* methods */
       
  6673     (destructor)DB_dealloc, /*tp_dealloc*/
       
  6674     0,          /*tp_print*/
       
  6675     0,          /*tp_getattr*/
       
  6676     0,          /*tp_setattr*/
       
  6677     0,          /*tp_compare*/
       
  6678     0,          /*tp_repr*/
       
  6679     0,          /*tp_as_number*/
       
  6680     0,          /*tp_as_sequence*/
       
  6681     &DB_mapping,/*tp_as_mapping*/
       
  6682     0,          /*tp_hash*/
       
  6683     0,			/* tp_call */
       
  6684     0,			/* tp_str */
       
  6685     0,  		/* tp_getattro */
       
  6686     0,          /* tp_setattro */
       
  6687     0,			/* tp_as_buffer */
       
  6688 #if (PY_VERSION_HEX < 0x03000000)
       
  6689     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
       
  6690 #else
       
  6691     Py_TPFLAGS_DEFAULT,      /* tp_flags */
       
  6692 #endif
       
  6693     0,          /* tp_doc */
       
  6694     0,		    /* tp_traverse */
       
  6695     0,			/* tp_clear */
       
  6696     0,			/* tp_richcompare */
       
  6697     offsetof(DBObject, in_weakreflist),   /* tp_weaklistoffset */
       
  6698     0,          /*tp_iter*/
       
  6699     0,          /*tp_iternext*/
       
  6700     DB_methods, /*tp_methods*/
       
  6701     0, /*tp_members*/
       
  6702 };
       
  6703 
       
  6704 
       
  6705 statichere PyTypeObject DBCursor_Type = {
       
  6706 #if (PY_VERSION_HEX < 0x03000000)
       
  6707     PyObject_HEAD_INIT(NULL)
       
  6708     0,                  /*ob_size*/
       
  6709 #else
       
  6710     PyVarObject_HEAD_INIT(NULL, 0)
       
  6711 #endif
       
  6712     "DBCursor",         /*tp_name*/
       
  6713     sizeof(DBCursorObject),  /*tp_basicsize*/
       
  6714     0,          /*tp_itemsize*/
       
  6715     /* methods */
       
  6716     (destructor)DBCursor_dealloc,/*tp_dealloc*/
       
  6717     0,          /*tp_print*/
       
  6718     0,          /*tp_getattr*/
       
  6719     0,          /*tp_setattr*/
       
  6720     0,          /*tp_compare*/
       
  6721     0,          /*tp_repr*/
       
  6722     0,          /*tp_as_number*/
       
  6723     0,          /*tp_as_sequence*/
       
  6724     0,          /*tp_as_mapping*/
       
  6725     0,          /*tp_hash*/
       
  6726     0,          /*tp_call*/
       
  6727     0,          /*tp_str*/
       
  6728     0,          /*tp_getattro*/
       
  6729     0,          /*tp_setattro*/
       
  6730     0,          /*tp_as_buffer*/
       
  6731 #if (PY_VERSION_HEX < 0x03000000)
       
  6732     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
       
  6733 #else
       
  6734     Py_TPFLAGS_DEFAULT,      /* tp_flags */
       
  6735 #endif
       
  6736     0,          /* tp_doc */
       
  6737     0,          /* tp_traverse */
       
  6738     0,          /* tp_clear */
       
  6739     0,          /* tp_richcompare */
       
  6740     offsetof(DBCursorObject, in_weakreflist),   /* tp_weaklistoffset */
       
  6741     0,          /*tp_iter*/
       
  6742     0,          /*tp_iternext*/
       
  6743     DBCursor_methods, /*tp_methods*/
       
  6744     0,          /*tp_members*/
       
  6745 };
       
  6746 
       
  6747 
       
  6748 statichere PyTypeObject DBEnv_Type = {
       
  6749 #if (PY_VERSION_HEX < 0x03000000)
       
  6750     PyObject_HEAD_INIT(NULL)
       
  6751     0,                  /*ob_size*/
       
  6752 #else
       
  6753     PyVarObject_HEAD_INIT(NULL, 0)
       
  6754 #endif
       
  6755     "DBEnv",            /*tp_name*/
       
  6756     sizeof(DBEnvObject),    /*tp_basicsize*/
       
  6757     0,          /*tp_itemsize*/
       
  6758     /* methods */
       
  6759     (destructor)DBEnv_dealloc, /*tp_dealloc*/
       
  6760     0,          /*tp_print*/
       
  6761     0,          /*tp_getattr*/
       
  6762     0,          /*tp_setattr*/
       
  6763     0,          /*tp_compare*/
       
  6764     0,          /*tp_repr*/
       
  6765     0,          /*tp_as_number*/
       
  6766     0,          /*tp_as_sequence*/
       
  6767     0,          /*tp_as_mapping*/
       
  6768     0,          /*tp_hash*/
       
  6769     0,			/* tp_call */
       
  6770     0,			/* tp_str */
       
  6771     0,  		/* tp_getattro */
       
  6772     0,          /* tp_setattro */
       
  6773     0,			/* tp_as_buffer */
       
  6774 #if (PY_VERSION_HEX < 0x03000000)
       
  6775     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
       
  6776 #else
       
  6777     Py_TPFLAGS_DEFAULT,      /* tp_flags */
       
  6778 #endif
       
  6779     0,          /* tp_doc */
       
  6780     0,		    /* tp_traverse */
       
  6781     0,			/* tp_clear */
       
  6782     0,			/* tp_richcompare */
       
  6783     offsetof(DBEnvObject, in_weakreflist),   /* tp_weaklistoffset */
       
  6784     0,          /* tp_iter */
       
  6785     0,          /* tp_iternext */
       
  6786     DBEnv_methods,      /* tp_methods */
       
  6787     0,          /* tp_members */
       
  6788     DBEnv_getsets,      /* tp_getsets */
       
  6789 };
       
  6790 
       
  6791 statichere PyTypeObject DBTxn_Type = {
       
  6792 #if (PY_VERSION_HEX < 0x03000000)
       
  6793     PyObject_HEAD_INIT(NULL)
       
  6794     0,                  /*ob_size*/
       
  6795 #else
       
  6796     PyVarObject_HEAD_INIT(NULL, 0)
       
  6797 #endif
       
  6798     "DBTxn",    /*tp_name*/
       
  6799     sizeof(DBTxnObject),  /*tp_basicsize*/
       
  6800     0,          /*tp_itemsize*/
       
  6801     /* methods */
       
  6802     (destructor)DBTxn_dealloc, /*tp_dealloc*/
       
  6803     0,          /*tp_print*/
       
  6804     0,          /*tp_getattr*/
       
  6805     0,          /*tp_setattr*/
       
  6806     0,          /*tp_compare*/
       
  6807     0,          /*tp_repr*/
       
  6808     0,          /*tp_as_number*/
       
  6809     0,          /*tp_as_sequence*/
       
  6810     0,          /*tp_as_mapping*/
       
  6811     0,          /*tp_hash*/
       
  6812     0,			/* tp_call */
       
  6813     0,			/* tp_str */
       
  6814     0,  		/* tp_getattro */
       
  6815     0,          /* tp_setattro */
       
  6816     0,			/* tp_as_buffer */
       
  6817 #if (PY_VERSION_HEX < 0x03000000)
       
  6818     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
       
  6819 #else
       
  6820     Py_TPFLAGS_DEFAULT,      /* tp_flags */
       
  6821 #endif
       
  6822     0,          /* tp_doc */
       
  6823     0,	        /* tp_traverse */
       
  6824     0,			/* tp_clear */
       
  6825     0,			/* tp_richcompare */
       
  6826     offsetof(DBTxnObject, in_weakreflist),   /* tp_weaklistoffset */
       
  6827     0,          /*tp_iter*/
       
  6828     0,          /*tp_iternext*/
       
  6829     DBTxn_methods, /*tp_methods*/
       
  6830     0,          /*tp_members*/
       
  6831 };
       
  6832 
       
  6833 
       
  6834 statichere PyTypeObject DBLock_Type = {
       
  6835 #if (PY_VERSION_HEX < 0x03000000)
       
  6836     PyObject_HEAD_INIT(NULL)
       
  6837     0,                  /*ob_size*/
       
  6838 #else
       
  6839     PyVarObject_HEAD_INIT(NULL, 0)
       
  6840 #endif
       
  6841     "DBLock",   /*tp_name*/
       
  6842     sizeof(DBLockObject),  /*tp_basicsize*/
       
  6843     0,          /*tp_itemsize*/
       
  6844     /* methods */
       
  6845     (destructor)DBLock_dealloc, /*tp_dealloc*/
       
  6846     0,          /*tp_print*/
       
  6847     0,          /*tp_getattr*/
       
  6848     0,          /*tp_setattr*/
       
  6849     0,          /*tp_compare*/
       
  6850     0,          /*tp_repr*/
       
  6851     0,          /*tp_as_number*/
       
  6852     0,          /*tp_as_sequence*/
       
  6853     0,          /*tp_as_mapping*/
       
  6854     0,          /*tp_hash*/
       
  6855     0,			/* tp_call */
       
  6856     0,			/* tp_str */
       
  6857     0,  		/* tp_getattro */
       
  6858     0,          /* tp_setattro */
       
  6859     0,			/* tp_as_buffer */
       
  6860 #if (PY_VERSION_HEX < 0x03000000)
       
  6861     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
       
  6862 #else
       
  6863     Py_TPFLAGS_DEFAULT,      /* tp_flags */
       
  6864 #endif
       
  6865     0,          /* tp_doc */
       
  6866     0,		    /* tp_traverse */
       
  6867     0,			/* tp_clear */
       
  6868     0,			/* tp_richcompare */
       
  6869     offsetof(DBLockObject, in_weakreflist),   /* tp_weaklistoffset */
       
  6870 };
       
  6871 
       
  6872 #if (DBVER >= 43)
       
  6873 statichere PyTypeObject DBSequence_Type = {
       
  6874 #if (PY_VERSION_HEX < 0x03000000)
       
  6875     PyObject_HEAD_INIT(NULL)
       
  6876     0,                  /*ob_size*/
       
  6877 #else
       
  6878     PyVarObject_HEAD_INIT(NULL, 0)
       
  6879 #endif
       
  6880     "DBSequence",                   /*tp_name*/
       
  6881     sizeof(DBSequenceObject),       /*tp_basicsize*/
       
  6882     0,          /*tp_itemsize*/
       
  6883     /* methods */
       
  6884     (destructor)DBSequence_dealloc, /*tp_dealloc*/
       
  6885     0,          /*tp_print*/
       
  6886     0,          /*tp_getattr*/
       
  6887     0,          /*tp_setattr*/
       
  6888     0,          /*tp_compare*/
       
  6889     0,          /*tp_repr*/
       
  6890     0,          /*tp_as_number*/
       
  6891     0,          /*tp_as_sequence*/
       
  6892     0,          /*tp_as_mapping*/
       
  6893     0,          /*tp_hash*/
       
  6894     0,			/* tp_call */
       
  6895     0,			/* tp_str */
       
  6896     0,  		/* tp_getattro */
       
  6897     0,          /* tp_setattro */
       
  6898     0,			/* tp_as_buffer */
       
  6899 #if (PY_VERSION_HEX < 0x03000000)
       
  6900     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS,      /* tp_flags */
       
  6901 #else
       
  6902     Py_TPFLAGS_DEFAULT,      /* tp_flags */
       
  6903 #endif
       
  6904     0,          /* tp_doc */
       
  6905     0,		    /* tp_traverse */
       
  6906     0,			/* tp_clear */
       
  6907     0,			/* tp_richcompare */
       
  6908     offsetof(DBSequenceObject, in_weakreflist),   /* tp_weaklistoffset */
       
  6909     0,          /*tp_iter*/
       
  6910     0,          /*tp_iternext*/
       
  6911     DBSequence_methods, /*tp_methods*/
       
  6912     0,          /*tp_members*/
       
  6913 };
       
  6914 #endif
       
  6915 
       
  6916 /* --------------------------------------------------------------------- */
       
  6917 /* Module-level functions */
       
  6918 
       
  6919 static PyObject*
       
  6920 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
       
  6921 {
       
  6922     PyObject* dbenvobj = NULL;
       
  6923     int flags = 0;
       
  6924     static char* kwnames[] = { "dbEnv", "flags", NULL};
       
  6925 
       
  6926     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
       
  6927                                      &dbenvobj, &flags))
       
  6928         return NULL;
       
  6929     if (dbenvobj == Py_None)
       
  6930         dbenvobj = NULL;
       
  6931     else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
       
  6932         makeTypeError("DBEnv", dbenvobj);
       
  6933         return NULL;
       
  6934     }
       
  6935 
       
  6936     return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
       
  6937 }
       
  6938 
       
  6939 
       
  6940 static PyObject*
       
  6941 DBEnv_construct(PyObject* self, PyObject* args)
       
  6942 {
       
  6943     int flags = 0;
       
  6944     if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
       
  6945     return (PyObject* )newDBEnvObject(flags);
       
  6946 }
       
  6947 
       
  6948 #if (DBVER >= 43)
       
  6949 static PyObject*
       
  6950 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
       
  6951 {
       
  6952     PyObject* dbobj;
       
  6953     int flags = 0;
       
  6954     static char* kwnames[] = { "db", "flags", NULL};
       
  6955 
       
  6956     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
       
  6957         return NULL;
       
  6958     if (!DBObject_Check(dbobj)) {
       
  6959         makeTypeError("DB", dbobj);
       
  6960         return NULL;
       
  6961     }
       
  6962     return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
       
  6963 }
       
  6964 #endif
       
  6965 
       
  6966 static char bsddb_version_doc[] =
       
  6967 "Returns a tuple of major, minor, and patch release numbers of the\n\
       
  6968 underlying DB library.";
       
  6969 
       
  6970 static PyObject*
       
  6971 bsddb_version(PyObject* self)
       
  6972 {
       
  6973     int major, minor, patch;
       
  6974 
       
  6975     db_version(&major, &minor, &patch);
       
  6976     return Py_BuildValue("(iii)", major, minor, patch);
       
  6977 }
       
  6978 
       
  6979 
       
  6980 /* List of functions defined in the module */
       
  6981 static PyMethodDef bsddb_methods[] = {
       
  6982     {"DB",          (PyCFunction)DB_construct,          METH_VARARGS | METH_KEYWORDS },
       
  6983     {"DBEnv",       (PyCFunction)DBEnv_construct,       METH_VARARGS},
       
  6984 #if (DBVER >= 43)
       
  6985     {"DBSequence",  (PyCFunction)DBSequence_construct,  METH_VARARGS | METH_KEYWORDS },
       
  6986 #endif
       
  6987     {"version",     (PyCFunction)bsddb_version,         METH_NOARGS, bsddb_version_doc},
       
  6988     {NULL,      NULL}       /* sentinel */
       
  6989 };
       
  6990 
       
  6991 
       
  6992 /* API structure */
       
  6993 static BSDDB_api bsddb_api;
       
  6994 
       
  6995 
       
  6996 /* --------------------------------------------------------------------- */
       
  6997 /* Module initialization */
       
  6998 
       
  6999 
       
  7000 /* Convenience routine to export an integer value.
       
  7001  * Errors are silently ignored, for better or for worse...
       
  7002  */
       
  7003 #define ADD_INT(dict, NAME)         _addIntToDict(dict, #NAME, NAME)
       
  7004 
       
  7005 #define MODULE_NAME_MAX_LEN     11
       
  7006 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
       
  7007 
       
  7008 #if (PY_VERSION_HEX >= 0x03000000)
       
  7009 static struct PyModuleDef bsddbmodule = {
       
  7010     PyModuleDef_HEAD_INIT,
       
  7011     _bsddbModuleName,   /* Name of module */
       
  7012     NULL,               /* module documentation, may be NULL */
       
  7013     -1,                 /* size of per-interpreter state of the module,
       
  7014                             or -1 if the module keeps state in global variables. */
       
  7015     bsddb_methods,
       
  7016     NULL,   /* Reload */
       
  7017     NULL,   /* Traverse */
       
  7018     NULL,   /* Clear */
       
  7019     NULL    /* Free */
       
  7020 };
       
  7021 #endif
       
  7022 
       
  7023 
       
  7024 #if (PY_VERSION_HEX < 0x03000000)
       
  7025 DL_EXPORT(void) init_bsddb(void)
       
  7026 #else
       
  7027 PyMODINIT_FUNC  PyInit__bsddb(void)    /* Note the two underscores */
       
  7028 #endif
       
  7029 {
       
  7030     PyObject* m;
       
  7031     PyObject* d;
       
  7032     PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
       
  7033     PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
       
  7034     PyObject* cvsid_s = PyBytes_FromString( rcs_id );
       
  7035     PyObject* py_api;
       
  7036 
       
  7037     /* Initialize object types */
       
  7038     if ((PyType_Ready(&DB_Type) < 0)
       
  7039         || (PyType_Ready(&DBCursor_Type) < 0)
       
  7040         || (PyType_Ready(&DBEnv_Type) < 0)
       
  7041         || (PyType_Ready(&DBTxn_Type) < 0)
       
  7042         || (PyType_Ready(&DBLock_Type) < 0)
       
  7043 #if (DBVER >= 43)
       
  7044         || (PyType_Ready(&DBSequence_Type) < 0)
       
  7045 #endif
       
  7046         ) {
       
  7047 #if (PY_VERSION_HEX < 0x03000000)
       
  7048         return;
       
  7049 #else
       
  7050         return NULL;
       
  7051 #endif
       
  7052     }
       
  7053 
       
  7054 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
       
  7055     /* Save the current interpreter, so callbacks can do the right thing. */
       
  7056     _db_interpreterState = PyThreadState_GET()->interp;
       
  7057 #endif
       
  7058 
       
  7059     /* Create the module and add the functions */
       
  7060 #if (PY_VERSION_HEX < 0x03000000)
       
  7061     m = Py_InitModule(_bsddbModuleName, bsddb_methods);
       
  7062 #else
       
  7063     m=PyModule_Create(&bsddbmodule);
       
  7064 #endif
       
  7065     if (m == NULL) {
       
  7066 #if (PY_VERSION_HEX < 0x03000000)
       
  7067         return;
       
  7068 #else
       
  7069     	return NULL;
       
  7070 #endif
       
  7071     }
       
  7072 
       
  7073     /* Add some symbolic constants to the module */
       
  7074     d = PyModule_GetDict(m);
       
  7075     PyDict_SetItemString(d, "__version__", pybsddb_version_s);
       
  7076     PyDict_SetItemString(d, "cvsid", cvsid_s);
       
  7077     PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
       
  7078     Py_DECREF(pybsddb_version_s);
       
  7079     pybsddb_version_s = NULL;
       
  7080     Py_DECREF(cvsid_s);
       
  7081     cvsid_s = NULL;
       
  7082     Py_DECREF(db_version_s);
       
  7083     db_version_s = NULL;
       
  7084 
       
  7085     ADD_INT(d, DB_VERSION_MAJOR);
       
  7086     ADD_INT(d, DB_VERSION_MINOR);
       
  7087     ADD_INT(d, DB_VERSION_PATCH);
       
  7088 
       
  7089     ADD_INT(d, DB_MAX_PAGES);
       
  7090     ADD_INT(d, DB_MAX_RECORDS);
       
  7091 
       
  7092 #if (DBVER >= 42)
       
  7093     ADD_INT(d, DB_RPCCLIENT);
       
  7094 #else
       
  7095     ADD_INT(d, DB_CLIENT);
       
  7096     /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
       
  7097     _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
       
  7098 #endif
       
  7099     ADD_INT(d, DB_XA_CREATE);
       
  7100 
       
  7101     ADD_INT(d, DB_CREATE);
       
  7102     ADD_INT(d, DB_NOMMAP);
       
  7103     ADD_INT(d, DB_THREAD);
       
  7104 #if (DBVER >= 45)
       
  7105     ADD_INT(d, DB_MULTIVERSION);
       
  7106 #endif
       
  7107 
       
  7108     ADD_INT(d, DB_FORCE);
       
  7109     ADD_INT(d, DB_INIT_CDB);
       
  7110     ADD_INT(d, DB_INIT_LOCK);
       
  7111     ADD_INT(d, DB_INIT_LOG);
       
  7112     ADD_INT(d, DB_INIT_MPOOL);
       
  7113     ADD_INT(d, DB_INIT_TXN);
       
  7114     ADD_INT(d, DB_JOINENV);
       
  7115 
       
  7116     ADD_INT(d, DB_XIDDATASIZE);
       
  7117 
       
  7118     ADD_INT(d, DB_RECOVER);
       
  7119     ADD_INT(d, DB_RECOVER_FATAL);
       
  7120     ADD_INT(d, DB_TXN_NOSYNC);
       
  7121     ADD_INT(d, DB_USE_ENVIRON);
       
  7122     ADD_INT(d, DB_USE_ENVIRON_ROOT);
       
  7123 
       
  7124     ADD_INT(d, DB_LOCKDOWN);
       
  7125     ADD_INT(d, DB_PRIVATE);
       
  7126     ADD_INT(d, DB_SYSTEM_MEM);
       
  7127 
       
  7128     ADD_INT(d, DB_TXN_SYNC);
       
  7129     ADD_INT(d, DB_TXN_NOWAIT);
       
  7130 
       
  7131     ADD_INT(d, DB_EXCL);
       
  7132     ADD_INT(d, DB_FCNTL_LOCKING);
       
  7133     ADD_INT(d, DB_ODDFILESIZE);
       
  7134     ADD_INT(d, DB_RDWRMASTER);
       
  7135     ADD_INT(d, DB_RDONLY);
       
  7136     ADD_INT(d, DB_TRUNCATE);
       
  7137     ADD_INT(d, DB_EXTENT);
       
  7138     ADD_INT(d, DB_CDB_ALLDB);
       
  7139     ADD_INT(d, DB_VERIFY);
       
  7140     ADD_INT(d, DB_UPGRADE);
       
  7141 
       
  7142     ADD_INT(d, DB_AGGRESSIVE);
       
  7143     ADD_INT(d, DB_NOORDERCHK);
       
  7144     ADD_INT(d, DB_ORDERCHKONLY);
       
  7145     ADD_INT(d, DB_PR_PAGE);
       
  7146 
       
  7147     ADD_INT(d, DB_PR_RECOVERYTEST);
       
  7148     ADD_INT(d, DB_SALVAGE);
       
  7149 
       
  7150     ADD_INT(d, DB_LOCK_NORUN);
       
  7151     ADD_INT(d, DB_LOCK_DEFAULT);
       
  7152     ADD_INT(d, DB_LOCK_OLDEST);
       
  7153     ADD_INT(d, DB_LOCK_RANDOM);
       
  7154     ADD_INT(d, DB_LOCK_YOUNGEST);
       
  7155     ADD_INT(d, DB_LOCK_MAXLOCKS);
       
  7156     ADD_INT(d, DB_LOCK_MINLOCKS);
       
  7157     ADD_INT(d, DB_LOCK_MINWRITE);
       
  7158 
       
  7159     ADD_INT(d, DB_LOCK_EXPIRE);
       
  7160 #if (DBVER >= 43)
       
  7161     ADD_INT(d, DB_LOCK_MAXWRITE);
       
  7162 #endif
       
  7163 
       
  7164     _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
       
  7165 
       
  7166     ADD_INT(d, DB_LOCK_DUMP);
       
  7167     ADD_INT(d, DB_LOCK_GET);
       
  7168     ADD_INT(d, DB_LOCK_INHERIT);
       
  7169     ADD_INT(d, DB_LOCK_PUT);
       
  7170     ADD_INT(d, DB_LOCK_PUT_ALL);
       
  7171     ADD_INT(d, DB_LOCK_PUT_OBJ);
       
  7172 
       
  7173     ADD_INT(d, DB_LOCK_NG);
       
  7174     ADD_INT(d, DB_LOCK_READ);
       
  7175     ADD_INT(d, DB_LOCK_WRITE);
       
  7176     ADD_INT(d, DB_LOCK_NOWAIT);
       
  7177     ADD_INT(d, DB_LOCK_WAIT);
       
  7178     ADD_INT(d, DB_LOCK_IWRITE);
       
  7179     ADD_INT(d, DB_LOCK_IREAD);
       
  7180     ADD_INT(d, DB_LOCK_IWR);
       
  7181 #if (DBVER < 44)
       
  7182     ADD_INT(d, DB_LOCK_DIRTY);
       
  7183 #else
       
  7184     ADD_INT(d, DB_LOCK_READ_UNCOMMITTED);  /* renamed in 4.4 */
       
  7185 #endif
       
  7186     ADD_INT(d, DB_LOCK_WWRITE);
       
  7187 
       
  7188     ADD_INT(d, DB_LOCK_RECORD);
       
  7189     ADD_INT(d, DB_LOCK_UPGRADE);
       
  7190     ADD_INT(d, DB_LOCK_SWITCH);
       
  7191     ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
       
  7192 
       
  7193     ADD_INT(d, DB_LOCK_NOWAIT);
       
  7194     ADD_INT(d, DB_LOCK_RECORD);
       
  7195     ADD_INT(d, DB_LOCK_UPGRADE);
       
  7196 
       
  7197     ADD_INT(d, DB_LSTAT_ABORTED);
       
  7198 #if (DBVER < 43)
       
  7199     ADD_INT(d, DB_LSTAT_ERR);
       
  7200 #endif
       
  7201     ADD_INT(d, DB_LSTAT_FREE);
       
  7202     ADD_INT(d, DB_LSTAT_HELD);
       
  7203 
       
  7204     ADD_INT(d, DB_LSTAT_PENDING);
       
  7205     ADD_INT(d, DB_LSTAT_WAITING);
       
  7206 
       
  7207     ADD_INT(d, DB_ARCH_ABS);
       
  7208     ADD_INT(d, DB_ARCH_DATA);
       
  7209     ADD_INT(d, DB_ARCH_LOG);
       
  7210 #if (DBVER >= 42)
       
  7211     ADD_INT(d, DB_ARCH_REMOVE);
       
  7212 #endif
       
  7213 
       
  7214     ADD_INT(d, DB_BTREE);
       
  7215     ADD_INT(d, DB_HASH);
       
  7216     ADD_INT(d, DB_RECNO);
       
  7217     ADD_INT(d, DB_QUEUE);
       
  7218     ADD_INT(d, DB_UNKNOWN);
       
  7219 
       
  7220     ADD_INT(d, DB_DUP);
       
  7221     ADD_INT(d, DB_DUPSORT);
       
  7222     ADD_INT(d, DB_RECNUM);
       
  7223     ADD_INT(d, DB_RENUMBER);
       
  7224     ADD_INT(d, DB_REVSPLITOFF);
       
  7225     ADD_INT(d, DB_SNAPSHOT);
       
  7226 
       
  7227     ADD_INT(d, DB_JOIN_NOSORT);
       
  7228 
       
  7229     ADD_INT(d, DB_AFTER);
       
  7230     ADD_INT(d, DB_APPEND);
       
  7231     ADD_INT(d, DB_BEFORE);
       
  7232 #if (DBVER < 45)
       
  7233     ADD_INT(d, DB_CACHED_COUNTS);
       
  7234 #endif
       
  7235 
       
  7236 #if (DBVER >= 41)
       
  7237     _addIntToDict(d, "DB_CHECKPOINT", 0);
       
  7238 #else
       
  7239     ADD_INT(d, DB_CHECKPOINT);
       
  7240     ADD_INT(d, DB_CURLSN);
       
  7241 #endif
       
  7242 #if (DBVER <= 41)
       
  7243     ADD_INT(d, DB_COMMIT);
       
  7244 #endif
       
  7245     ADD_INT(d, DB_CONSUME);
       
  7246     ADD_INT(d, DB_CONSUME_WAIT);
       
  7247     ADD_INT(d, DB_CURRENT);
       
  7248     ADD_INT(d, DB_FAST_STAT);
       
  7249     ADD_INT(d, DB_FIRST);
       
  7250     ADD_INT(d, DB_FLUSH);
       
  7251     ADD_INT(d, DB_GET_BOTH);
       
  7252     ADD_INT(d, DB_GET_RECNO);
       
  7253     ADD_INT(d, DB_JOIN_ITEM);
       
  7254     ADD_INT(d, DB_KEYFIRST);
       
  7255     ADD_INT(d, DB_KEYLAST);
       
  7256     ADD_INT(d, DB_LAST);
       
  7257     ADD_INT(d, DB_NEXT);
       
  7258     ADD_INT(d, DB_NEXT_DUP);
       
  7259     ADD_INT(d, DB_NEXT_NODUP);
       
  7260     ADD_INT(d, DB_NODUPDATA);
       
  7261     ADD_INT(d, DB_NOOVERWRITE);
       
  7262     ADD_INT(d, DB_NOSYNC);
       
  7263     ADD_INT(d, DB_POSITION);
       
  7264     ADD_INT(d, DB_PREV);
       
  7265     ADD_INT(d, DB_PREV_NODUP);
       
  7266 #if (DBVER < 45)
       
  7267     ADD_INT(d, DB_RECORDCOUNT);
       
  7268 #endif
       
  7269     ADD_INT(d, DB_SET);
       
  7270     ADD_INT(d, DB_SET_RANGE);
       
  7271     ADD_INT(d, DB_SET_RECNO);
       
  7272     ADD_INT(d, DB_WRITECURSOR);
       
  7273 
       
  7274     ADD_INT(d, DB_OPFLAGS_MASK);
       
  7275     ADD_INT(d, DB_RMW);
       
  7276     ADD_INT(d, DB_DIRTY_READ);
       
  7277     ADD_INT(d, DB_MULTIPLE);
       
  7278     ADD_INT(d, DB_MULTIPLE_KEY);
       
  7279 
       
  7280 #if (DBVER >= 44)
       
  7281     ADD_INT(d, DB_READ_UNCOMMITTED);    /* replaces DB_DIRTY_READ in 4.4 */
       
  7282     ADD_INT(d, DB_READ_COMMITTED);
       
  7283 #endif
       
  7284 
       
  7285     ADD_INT(d, DB_DONOTINDEX);
       
  7286 
       
  7287 #if (DBVER >= 41)
       
  7288     _addIntToDict(d, "DB_INCOMPLETE", 0);
       
  7289 #else
       
  7290     ADD_INT(d, DB_INCOMPLETE);
       
  7291 #endif
       
  7292     ADD_INT(d, DB_KEYEMPTY);
       
  7293     ADD_INT(d, DB_KEYEXIST);
       
  7294     ADD_INT(d, DB_LOCK_DEADLOCK);
       
  7295     ADD_INT(d, DB_LOCK_NOTGRANTED);
       
  7296     ADD_INT(d, DB_NOSERVER);
       
  7297     ADD_INT(d, DB_NOSERVER_HOME);
       
  7298     ADD_INT(d, DB_NOSERVER_ID);
       
  7299     ADD_INT(d, DB_NOTFOUND);
       
  7300     ADD_INT(d, DB_OLD_VERSION);
       
  7301     ADD_INT(d, DB_RUNRECOVERY);
       
  7302     ADD_INT(d, DB_VERIFY_BAD);
       
  7303     ADD_INT(d, DB_PAGE_NOTFOUND);
       
  7304     ADD_INT(d, DB_SECONDARY_BAD);
       
  7305     ADD_INT(d, DB_STAT_CLEAR);
       
  7306     ADD_INT(d, DB_REGION_INIT);
       
  7307     ADD_INT(d, DB_NOLOCKING);
       
  7308     ADD_INT(d, DB_YIELDCPU);
       
  7309     ADD_INT(d, DB_PANIC_ENVIRONMENT);
       
  7310     ADD_INT(d, DB_NOPANIC);
       
  7311 
       
  7312 #if (DBVER >= 41)
       
  7313     ADD_INT(d, DB_OVERWRITE);
       
  7314 #endif
       
  7315 
       
  7316 #ifdef DB_REGISTER
       
  7317     ADD_INT(d, DB_REGISTER);
       
  7318 #endif
       
  7319 
       
  7320 #if (DBVER >= 42)
       
  7321     ADD_INT(d, DB_TIME_NOTGRANTED);
       
  7322     ADD_INT(d, DB_TXN_NOT_DURABLE);
       
  7323     ADD_INT(d, DB_TXN_WRITE_NOSYNC);
       
  7324     ADD_INT(d, DB_DIRECT_DB);
       
  7325     ADD_INT(d, DB_INIT_REP);
       
  7326     ADD_INT(d, DB_ENCRYPT);
       
  7327     ADD_INT(d, DB_CHKSUM);
       
  7328 #endif
       
  7329 
       
  7330 #if (DBVER >= 42) && (DBVER < 47)
       
  7331     ADD_INT(d, DB_LOG_AUTOREMOVE);
       
  7332     ADD_INT(d, DB_DIRECT_LOG);
       
  7333 #endif
       
  7334 
       
  7335 #if (DBVER >= 47)
       
  7336     ADD_INT(d, DB_LOG_DIRECT);
       
  7337     ADD_INT(d, DB_LOG_DSYNC);
       
  7338     ADD_INT(d, DB_LOG_IN_MEMORY);
       
  7339     ADD_INT(d, DB_LOG_AUTO_REMOVE);
       
  7340     ADD_INT(d, DB_LOG_ZERO);
       
  7341 #endif
       
  7342 
       
  7343 #if (DBVER >= 44)
       
  7344     ADD_INT(d, DB_DSYNC_DB);
       
  7345 #endif
       
  7346 
       
  7347 #if (DBVER >= 45)
       
  7348     ADD_INT(d, DB_TXN_SNAPSHOT);
       
  7349 #endif
       
  7350 
       
  7351     ADD_INT(d, DB_VERB_DEADLOCK);
       
  7352 #if (DBVER >= 46)
       
  7353     ADD_INT(d, DB_VERB_FILEOPS);
       
  7354     ADD_INT(d, DB_VERB_FILEOPS_ALL);
       
  7355 #endif
       
  7356     ADD_INT(d, DB_VERB_RECOVERY);
       
  7357 #if (DBVER >= 44)
       
  7358     ADD_INT(d, DB_VERB_REGISTER);
       
  7359 #endif
       
  7360     ADD_INT(d, DB_VERB_REPLICATION);
       
  7361     ADD_INT(d, DB_VERB_WAITSFOR);
       
  7362 
       
  7363 #if (DBVER >= 45)
       
  7364     ADD_INT(d, DB_EVENT_PANIC);
       
  7365     ADD_INT(d, DB_EVENT_REP_CLIENT);
       
  7366 #if (DBVER >= 46)
       
  7367     ADD_INT(d, DB_EVENT_REP_ELECTED);
       
  7368 #endif
       
  7369     ADD_INT(d, DB_EVENT_REP_MASTER);
       
  7370     ADD_INT(d, DB_EVENT_REP_NEWMASTER);
       
  7371 #if (DBVER >= 46)
       
  7372     ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
       
  7373 #endif
       
  7374     ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
       
  7375     ADD_INT(d, DB_EVENT_WRITE_FAILED);
       
  7376 #endif
       
  7377 
       
  7378     ADD_INT(d, DB_REP_DUPMASTER);
       
  7379     ADD_INT(d, DB_REP_HOLDELECTION);
       
  7380 #if (DBVER >= 44)
       
  7381     ADD_INT(d, DB_REP_IGNORE);
       
  7382     ADD_INT(d, DB_REP_JOIN_FAILURE);
       
  7383 #endif
       
  7384 #if (DBVER >= 42)
       
  7385     ADD_INT(d, DB_REP_ISPERM);
       
  7386     ADD_INT(d, DB_REP_NOTPERM);
       
  7387 #endif
       
  7388     ADD_INT(d, DB_REP_NEWSITE);
       
  7389 
       
  7390     ADD_INT(d, DB_REP_MASTER);
       
  7391     ADD_INT(d, DB_REP_CLIENT);
       
  7392 #if (DBVER >= 45)
       
  7393     ADD_INT(d, DB_REP_ELECTION);
       
  7394 
       
  7395     ADD_INT(d, DB_REP_ACK_TIMEOUT);
       
  7396     ADD_INT(d, DB_REP_CONNECTION_RETRY);
       
  7397     ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
       
  7398     ADD_INT(d, DB_REP_ELECTION_RETRY);
       
  7399 #endif
       
  7400 #if (DBVER >= 46)
       
  7401     ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
       
  7402     ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
       
  7403 #endif
       
  7404 
       
  7405 #if (DBVER >= 45)
       
  7406     ADD_INT(d, DB_REPMGR_PEER);
       
  7407     ADD_INT(d, DB_REPMGR_ACKS_ALL);
       
  7408     ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
       
  7409     ADD_INT(d, DB_REPMGR_ACKS_NONE);
       
  7410     ADD_INT(d, DB_REPMGR_ACKS_ONE);
       
  7411     ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
       
  7412     ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
       
  7413     ADD_INT(d, DB_REPMGR_CONNECTED);
       
  7414     ADD_INT(d, DB_REPMGR_DISCONNECTED);
       
  7415     ADD_INT(d, DB_STAT_CLEAR);
       
  7416     ADD_INT(d, DB_STAT_ALL);
       
  7417 #endif
       
  7418 
       
  7419 #if (DBVER >= 43)
       
  7420     ADD_INT(d, DB_BUFFER_SMALL);
       
  7421     ADD_INT(d, DB_SEQ_DEC);
       
  7422     ADD_INT(d, DB_SEQ_INC);
       
  7423     ADD_INT(d, DB_SEQ_WRAP);
       
  7424 #endif
       
  7425 
       
  7426 #if (DBVER >= 43) && (DBVER < 47)
       
  7427     ADD_INT(d, DB_LOG_INMEMORY);
       
  7428     ADD_INT(d, DB_DSYNC_LOG);
       
  7429 #endif
       
  7430 
       
  7431 #if (DBVER >= 41)
       
  7432     ADD_INT(d, DB_ENCRYPT_AES);
       
  7433     ADD_INT(d, DB_AUTO_COMMIT);
       
  7434 #else
       
  7435     /* allow Berkeley DB 4.1 aware apps to run on older versions */
       
  7436     _addIntToDict(d, "DB_AUTO_COMMIT", 0);
       
  7437 #endif
       
  7438 
       
  7439     ADD_INT(d, EINVAL);
       
  7440     ADD_INT(d, EACCES);
       
  7441     ADD_INT(d, ENOSPC);
       
  7442     ADD_INT(d, ENOMEM);
       
  7443     ADD_INT(d, EAGAIN);
       
  7444     ADD_INT(d, EBUSY);
       
  7445     ADD_INT(d, EEXIST);
       
  7446     ADD_INT(d, ENOENT);
       
  7447     ADD_INT(d, EPERM);
       
  7448 
       
  7449     ADD_INT(d, DB_SET_LOCK_TIMEOUT);
       
  7450     ADD_INT(d, DB_SET_TXN_TIMEOUT);
       
  7451 
       
  7452     /* The exception name must be correct for pickled exception *
       
  7453      * objects to unpickle properly.                            */
       
  7454 #ifdef PYBSDDB_STANDALONE  /* different value needed for standalone pybsddb */
       
  7455 #define PYBSDDB_EXCEPTION_BASE  "bsddb3.db."
       
  7456 #else
       
  7457 #define PYBSDDB_EXCEPTION_BASE  "bsddb.db."
       
  7458 #endif
       
  7459 
       
  7460     /* All the rest of the exceptions derive only from DBError */
       
  7461 #define MAKE_EX(name)   name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
       
  7462                         PyDict_SetItemString(d, #name, name)
       
  7463 
       
  7464     /* The base exception class is DBError */
       
  7465     DBError = NULL;     /* used in MAKE_EX so that it derives from nothing */
       
  7466     MAKE_EX(DBError);
       
  7467 
       
  7468 #if (PY_VERSION_HEX < 0x03000000)
       
  7469     /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
       
  7470      * from both DBError and KeyError, since the API only supports
       
  7471      * using one base class. */
       
  7472     PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
       
  7473     PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
       
  7474 	         "class DBKeyEmptyError(DBError, KeyError): pass",
       
  7475                  Py_file_input, d, d);
       
  7476     DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
       
  7477     DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
       
  7478     PyDict_DelItemString(d, "KeyError");
       
  7479 #else
       
  7480     /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
       
  7481     ** derive from several classes. We use this new API only for Python 3.0,
       
  7482     ** though.
       
  7483     */
       
  7484     {
       
  7485         PyObject* bases;
       
  7486 
       
  7487         bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
       
  7488 
       
  7489 #define MAKE_EX2(name)   name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
       
  7490                          PyDict_SetItemString(d, #name, name)
       
  7491         MAKE_EX2(DBNotFoundError);
       
  7492         MAKE_EX2(DBKeyEmptyError);
       
  7493 
       
  7494 #undef MAKE_EX2
       
  7495 
       
  7496         Py_XDECREF(bases);
       
  7497     }
       
  7498 #endif
       
  7499 
       
  7500 
       
  7501 #if !INCOMPLETE_IS_WARNING
       
  7502     MAKE_EX(DBIncompleteError);
       
  7503 #endif
       
  7504     MAKE_EX(DBCursorClosedError);
       
  7505     MAKE_EX(DBKeyEmptyError);
       
  7506     MAKE_EX(DBKeyExistError);
       
  7507     MAKE_EX(DBLockDeadlockError);
       
  7508     MAKE_EX(DBLockNotGrantedError);
       
  7509     MAKE_EX(DBOldVersionError);
       
  7510     MAKE_EX(DBRunRecoveryError);
       
  7511     MAKE_EX(DBVerifyBadError);
       
  7512     MAKE_EX(DBNoServerError);
       
  7513     MAKE_EX(DBNoServerHomeError);
       
  7514     MAKE_EX(DBNoServerIDError);
       
  7515     MAKE_EX(DBPageNotFoundError);
       
  7516     MAKE_EX(DBSecondaryBadError);
       
  7517 
       
  7518     MAKE_EX(DBInvalidArgError);
       
  7519     MAKE_EX(DBAccessError);
       
  7520     MAKE_EX(DBNoSpaceError);
       
  7521     MAKE_EX(DBNoMemoryError);
       
  7522     MAKE_EX(DBAgainError);
       
  7523     MAKE_EX(DBBusyError);
       
  7524     MAKE_EX(DBFileExistsError);
       
  7525     MAKE_EX(DBNoSuchFileError);
       
  7526     MAKE_EX(DBPermissionsError);
       
  7527 
       
  7528 #if (DBVER >= 42)
       
  7529     MAKE_EX(DBRepHandleDeadError);
       
  7530 #endif
       
  7531 
       
  7532     MAKE_EX(DBRepUnavailError);
       
  7533 
       
  7534 #undef MAKE_EX
       
  7535 
       
  7536     /* Initiliase the C API structure and add it to the module */
       
  7537     bsddb_api.db_type         = &DB_Type;
       
  7538     bsddb_api.dbcursor_type   = &DBCursor_Type;
       
  7539     bsddb_api.dbenv_type      = &DBEnv_Type;
       
  7540     bsddb_api.dbtxn_type      = &DBTxn_Type;
       
  7541     bsddb_api.dblock_type     = &DBLock_Type;
       
  7542 #if (DBVER >= 43)
       
  7543     bsddb_api.dbsequence_type = &DBSequence_Type;
       
  7544 #endif
       
  7545     bsddb_api.makeDBError     = makeDBError;
       
  7546 
       
  7547     py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
       
  7548     PyDict_SetItemString(d, "api", py_api);
       
  7549     Py_DECREF(py_api);
       
  7550 
       
  7551     /* Check for errors */
       
  7552     if (PyErr_Occurred()) {
       
  7553         PyErr_Print();
       
  7554         Py_FatalError("can't initialize module _bsddb/_pybsddb");
       
  7555         Py_DECREF(m);
       
  7556         m = NULL;
       
  7557     }
       
  7558 #if (PY_VERSION_HEX < 0x03000000)
       
  7559     return;
       
  7560 #else
       
  7561     return m;
       
  7562 #endif
       
  7563 }
       
  7564 
       
  7565 /* allow this module to be named _pybsddb so that it can be installed
       
  7566  * and imported on top of python >= 2.3 that includes its own older
       
  7567  * copy of the library named _bsddb without importing the old version. */
       
  7568 #if (PY_VERSION_HEX < 0x03000000)
       
  7569 DL_EXPORT(void) init_pybsddb(void)
       
  7570 #else
       
  7571 PyMODINIT_FUNC PyInit__pybsddb(void)  /* Note the two underscores */
       
  7572 #endif
       
  7573 {
       
  7574     strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
       
  7575 #if (PY_VERSION_HEX < 0x03000000)
       
  7576     init_bsddb();
       
  7577 #else
       
  7578     return PyInit__bsddb();   /* Note the two underscores */
       
  7579 #endif
       
  7580 }
       
  7581