Python-2.7.3/Modules/_bsddb.c

Location Tool Test ID Function Issue
/builddir/build/BUILD/Python-2.7.3/Modules/_bsddb.c:3326:0 cppcheck resourceLeak Resource leak: outFile
/builddir/build/BUILD/Python-2.7.3/Modules/_bsddb.c:3326:0 cppcheck resourceLeak Resource leak: outFile
    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  * More datatypes added:
   77  *
   78  * DBLogCursor  (Log Cursor)
   79  *
   80  */
   81 
   82 /* --------------------------------------------------------------------- */
   83 
   84 /*
   85  * Portions of this module, associated unit tests and build scripts are the
   86  * result of a contract with The Written Word (http://thewrittenword.com/)
   87  * Many thanks go out to them for causing me to raise the bar on quality and
   88  * functionality, resulting in a better bsddb3 package for all of us to use.
   89  *
   90  * --Robin
   91  */
   92 
   93 /* --------------------------------------------------------------------- */
   94 
   95 #include <stddef.h>   /* for offsetof() */
   96 #include <Python.h>
   97 
   98 #define COMPILING_BSDDB_C
   99 #include "bsddb.h"
  100 #undef COMPILING_BSDDB_C
  101 
  102 static char *rcs_id = "$Id$";
  103 
  104 /* --------------------------------------------------------------------- */
  105 /* Various macro definitions */
  106 
  107 #if (PY_VERSION_HEX < 0x02050000)
  108 typedef int Py_ssize_t;
  109 #endif
  110 
  111 #if (PY_VERSION_HEX < 0x02060000)  /* really: before python trunk r63675 */
  112 /* This code now uses PyBytes* API function names instead of PyString*.
  113  * These #defines map to their equivalent on earlier python versions.    */
  114 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
  115 #define PyBytes_FromString PyString_FromString
  116 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
  117 #define PyBytes_Check PyString_Check
  118 #define PyBytes_GET_SIZE PyString_GET_SIZE
  119 #define PyBytes_AS_STRING PyString_AS_STRING
  120 #endif
  121 
  122 #if (PY_VERSION_HEX >= 0x03000000)
  123 #define NUMBER_Check    PyLong_Check
  124 #define NUMBER_AsLong   PyLong_AsLong
  125 #define NUMBER_FromLong PyLong_FromLong
  126 #else
  127 #define NUMBER_Check    PyInt_Check
  128 #define NUMBER_AsLong   PyInt_AsLong
  129 #define NUMBER_FromLong PyInt_FromLong
  130 #endif
  131 
  132 #ifdef WITH_THREAD
  133 
  134 /* These are for when calling Python --> C */
  135 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
  136 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
  137 
  138 /* For 2.3, use the PyGILState_ calls */
  139 #if (PY_VERSION_HEX >= 0x02030000)
  140 #define MYDB_USE_GILSTATE
  141 #endif
  142 
  143 /* and these are for calling C --> Python */
  144 #if defined(MYDB_USE_GILSTATE)
  145 #define MYDB_BEGIN_BLOCK_THREADS \
  146                 PyGILState_STATE __savestate = PyGILState_Ensure();
  147 #define MYDB_END_BLOCK_THREADS \
  148                 PyGILState_Release(__savestate);
  149 #else /* MYDB_USE_GILSTATE */
  150 /* Pre GILState API - do it the long old way */
  151 static PyInterpreterState* _db_interpreterState = NULL;
  152 #define MYDB_BEGIN_BLOCK_THREADS {                              \
  153         PyThreadState* prevState;                               \
  154         PyThreadState* newState;                                \
  155         PyEval_AcquireLock();                                   \
  156         newState  = PyThreadState_New(_db_interpreterState);    \
  157         prevState = PyThreadState_Swap(newState);
  158 
  159 #define MYDB_END_BLOCK_THREADS                                  \
  160         newState = PyThreadState_Swap(prevState);               \
  161         PyThreadState_Clear(newState);                          \
  162         PyEval_ReleaseLock();                                   \
  163         PyThreadState_Delete(newState);                         \
  164         }
  165 #endif /* MYDB_USE_GILSTATE */
  166 
  167 #else
  168 /* Compiled without threads - avoid all this cruft */
  169 #define MYDB_BEGIN_ALLOW_THREADS
  170 #define MYDB_END_ALLOW_THREADS
  171 #define MYDB_BEGIN_BLOCK_THREADS
  172 #define MYDB_END_BLOCK_THREADS
  173 
  174 #endif
  175 
  176 /* --------------------------------------------------------------------- */
  177 /* Exceptions */
  178 
  179 static PyObject* DBError;               /* Base class, all others derive from this */
  180 static PyObject* DBCursorClosedError;   /* raised when trying to use a closed cursor object */
  181 static PyObject* DBKeyEmptyError;       /* DB_KEYEMPTY: also derives from KeyError */
  182 static PyObject* DBKeyExistError;       /* DB_KEYEXIST */
  183 static PyObject* DBLockDeadlockError;   /* DB_LOCK_DEADLOCK */
  184 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
  185 static PyObject* DBNotFoundError;       /* DB_NOTFOUND: also derives from KeyError */
  186 static PyObject* DBOldVersionError;     /* DB_OLD_VERSION */
  187 static PyObject* DBRunRecoveryError;    /* DB_RUNRECOVERY */
  188 static PyObject* DBVerifyBadError;      /* DB_VERIFY_BAD */
  189 static PyObject* DBNoServerError;       /* DB_NOSERVER */
  190 static PyObject* DBNoServerHomeError;   /* DB_NOSERVER_HOME */
  191 static PyObject* DBNoServerIDError;     /* DB_NOSERVER_ID */
  192 static PyObject* DBPageNotFoundError;   /* DB_PAGE_NOTFOUND */
  193 static PyObject* DBSecondaryBadError;   /* DB_SECONDARY_BAD */
  194 
  195 static PyObject* DBInvalidArgError;     /* EINVAL */
  196 static PyObject* DBAccessError;         /* EACCES */
  197 static PyObject* DBNoSpaceError;        /* ENOSPC */
  198 static PyObject* DBNoMemoryError;       /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
  199 static PyObject* DBAgainError;          /* EAGAIN */
  200 static PyObject* DBBusyError;           /* EBUSY  */
  201 static PyObject* DBFileExistsError;     /* EEXIST */
  202 static PyObject* DBNoSuchFileError;     /* ENOENT */
  203 static PyObject* DBPermissionsError;    /* EPERM  */
  204 
  205 #if (DBVER >= 42)
  206 static PyObject* DBRepHandleDeadError;  /* DB_REP_HANDLE_DEAD */
  207 #endif
  208 #if (DBVER >= 44)
  209 static PyObject* DBRepLockoutError;     /* DB_REP_LOCKOUT */
  210 #endif
  211 
  212 #if (DBVER >= 46)
  213 static PyObject* DBRepLeaseExpiredError; /* DB_REP_LEASE_EXPIRED */
  214 #endif
  215 
  216 #if (DBVER >= 47)
  217 static PyObject* DBForeignConflictError; /* DB_FOREIGN_CONFLICT */
  218 #endif
  219 
  220 
  221 static PyObject* DBRepUnavailError;     /* DB_REP_UNAVAIL */
  222 
  223 #if (DBVER < 43)
  224 #define DB_BUFFER_SMALL         ENOMEM
  225 #endif
  226 
  227 #if (DBVER < 48)
  228 #define DB_GID_SIZE DB_XIDDATASIZE
  229 #endif
  230 
  231 
  232 /* --------------------------------------------------------------------- */
  233 /* Structure definitions */
  234 
  235 #if PYTHON_API_VERSION < 1010
  236 #error "Python 2.1 or later required"
  237 #endif
  238 
  239 
  240 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
  241 #define DEFAULT_GET_RETURNS_NONE                1
  242 #define DEFAULT_CURSOR_SET_RETURNS_NONE         1   /* 0 in pybsddb < 4.2, python < 2.4 */
  243 
  244 
  245 /* See comment in Python 2.6 "object.h" */
  246 #ifndef staticforward
  247 #define staticforward static
  248 #endif
  249 #ifndef statichere
  250 #define statichere static
  251 #endif
  252 
  253 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
  254               DBLock_Type, DBLogCursor_Type;
  255 #if (DBVER >= 43)
  256 staticforward PyTypeObject DBSequence_Type;
  257 #endif
  258 
  259 #ifndef Py_TYPE
  260 /* for compatibility with Python 2.5 and earlier */
  261 #define Py_TYPE(ob)              (((PyObject*)(ob))->ob_type)
  262 #endif
  263 
  264 #define DBObject_Check(v)           (Py_TYPE(v) == &DB_Type)
  265 #define DBCursorObject_Check(v)     (Py_TYPE(v) == &DBCursor_Type)
  266 #define DBLogCursorObject_Check(v)  (Py_TYPE(v) == &DBLogCursor_Type)
  267 #define DBEnvObject_Check(v)        (Py_TYPE(v) == &DBEnv_Type)
  268 #define DBTxnObject_Check(v)        (Py_TYPE(v) == &DBTxn_Type)
  269 #define DBLockObject_Check(v)       (Py_TYPE(v) == &DBLock_Type)
  270 #if (DBVER >= 43)
  271 #define DBSequenceObject_Check(v)   (Py_TYPE(v) == &DBSequence_Type)
  272 #endif
  273 
  274 #if (DBVER < 46)
  275   #define _DBC_close(dbc)           dbc->c_close(dbc)
  276   #define _DBC_count(dbc,a,b)       dbc->c_count(dbc,a,b)
  277   #define _DBC_del(dbc,a)           dbc->c_del(dbc,a)
  278   #define _DBC_dup(dbc,a,b)         dbc->c_dup(dbc,a,b)
  279   #define _DBC_get(dbc,a,b,c)       dbc->c_get(dbc,a,b,c)
  280   #define _DBC_pget(dbc,a,b,c,d)    dbc->c_pget(dbc,a,b,c,d)
  281   #define _DBC_put(dbc,a,b,c)       dbc->c_put(dbc,a,b,c)
  282 #else
  283   #define _DBC_close(dbc)           dbc->close(dbc)
  284   #define _DBC_count(dbc,a,b)       dbc->count(dbc,a,b)
  285   #define _DBC_del(dbc,a)           dbc->del(dbc,a)
  286   #define _DBC_dup(dbc,a,b)         dbc->dup(dbc,a,b)
  287   #define _DBC_get(dbc,a,b,c)       dbc->get(dbc,a,b,c)
  288   #define _DBC_pget(dbc,a,b,c,d)    dbc->pget(dbc,a,b,c,d)
  289   #define _DBC_put(dbc,a,b,c)       dbc->put(dbc,a,b,c)
  290 #endif
  291 
  292 
  293 /* --------------------------------------------------------------------- */
  294 /* Utility macros and functions */
  295 
  296 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object)                   \
  297     {                                                                   \
  298         object->sibling_next=backlink;                                  \
  299         object->sibling_prev_p=&(backlink);                             \
  300         backlink=object;                                                \
  301         if (object->sibling_next) {                                     \
  302           object->sibling_next->sibling_prev_p=&(object->sibling_next); \
  303         }                                                               \
  304     }
  305 
  306 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object)                          \
  307     {                                                                    \
  308         if (object->sibling_next) {                                      \
  309             object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
  310         }                                                                \
  311         *(object->sibling_prev_p)=object->sibling_next;                  \
  312     }
  313 
  314 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object)               \
  315     {                                                                    \
  316         if (object->sibling_next) {                                      \
  317             object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
  318         }                                                                \
  319         if (object->sibling_prev_p) {                                    \
  320             *(object->sibling_prev_p)=object->sibling_next;              \
  321         }                                                                \
  322     }
  323 
  324 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object)  \
  325     {                                                      \
  326         object->sibling_next_txn=backlink;                 \
  327         object->sibling_prev_p_txn=&(backlink);            \
  328         backlink=object;                                   \
  329         if (object->sibling_next_txn) {                    \
  330             object->sibling_next_txn->sibling_prev_p_txn=  \
  331                 &(object->sibling_next_txn);               \
  332         }                                                  \
  333     }
  334 
  335 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object)             \
  336     {                                                           \
  337         if (object->sibling_next_txn) {                         \
  338             object->sibling_next_txn->sibling_prev_p_txn=       \
  339                 object->sibling_prev_p_txn;                     \
  340         }                                                       \
  341         *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
  342     }
  343 
  344 
  345 #define RETURN_IF_ERR()          \
  346     if (makeDBError(err)) {      \
  347         return NULL;             \
  348     }
  349 
  350 #define RETURN_NONE()  Py_INCREF(Py_None); return Py_None;
  351 
  352 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
  353     if ((nonNull) == NULL) {          \
  354         PyObject *errTuple = NULL;    \
  355         errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
  356         if (errTuple) { \
  357             PyErr_SetObject((pyErrObj), errTuple);  \
  358             Py_DECREF(errTuple);          \
  359         } \
  360         return NULL;                  \
  361     }
  362 
  363 #define CHECK_DB_NOT_CLOSED(dbobj) \
  364         _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
  365 
  366 #define CHECK_ENV_NOT_CLOSED(env) \
  367         _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
  368 
  369 #define CHECK_CURSOR_NOT_CLOSED(curs) \
  370         _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
  371 
  372 #define CHECK_LOGCURSOR_NOT_CLOSED(logcurs) \
  373         _CHECK_OBJECT_NOT_CLOSED(logcurs->logc, DBCursorClosedError, DBLogCursor)
  374 
  375 #if (DBVER >= 43)
  376 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
  377         _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
  378 #endif
  379 
  380 #define CHECK_DBFLAG(mydb, flag)    (((mydb)->flags & (flag)) || \
  381                                      (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
  382 
  383 #define CLEAR_DBT(dbt)              (memset(&(dbt), 0, sizeof(dbt)))
  384 
  385 #define FREE_DBT(dbt)               if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
  386                                          dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
  387 
  388 
  389 static int makeDBError(int err);
  390 
  391 
  392 /* Return the access method type of the DBObject */
  393 static int _DB_get_type(DBObject* self)
  394 {
  395     DBTYPE type;
  396     int err;
  397 
  398     err = self->db->get_type(self->db, &type);
  399     if (makeDBError(err)) {
  400         return -1;
  401     }
  402     return type;
  403 }
  404 
  405 
  406 /* Create a DBT structure (containing key and data values) from Python
  407    strings.  Returns 1 on success, 0 on an error. */
  408 static int make_dbt(PyObject* obj, DBT* dbt)
  409 {
  410     CLEAR_DBT(*dbt);
  411     if (obj == Py_None) {
  412         /* no need to do anything, the structure has already been zeroed */
  413     }
  414     else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
  415         PyErr_SetString(PyExc_TypeError,
  416 #if (PY_VERSION_HEX < 0x03000000)
  417                         "Data values must be of type string or None.");
  418 #else
  419                         "Data values must be of type bytes or None.");
  420 #endif
  421         return 0;
  422     }
  423     return 1;
  424 }
  425 
  426 
  427 /* Recno and Queue DBs can have integer keys.  This function figures out
  428    what's been given, verifies that it's allowed, and then makes the DBT.
  429 
  430    Caller MUST call FREE_DBT(key) when done. */
  431 static int
  432 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
  433 {
  434     db_recno_t recno;
  435     int type;
  436 
  437     CLEAR_DBT(*key);
  438     if (keyobj == Py_None) {
  439         type = _DB_get_type(self);
  440         if (type == -1)
  441             return 0;
  442         if (type == DB_RECNO || type == DB_QUEUE) {
  443             PyErr_SetString(
  444                 PyExc_TypeError,
  445                 "None keys not allowed for Recno and Queue DB's");
  446             return 0;
  447         }
  448         /* no need to do anything, the structure has already been zeroed */
  449     }
  450 
  451     else if (PyBytes_Check(keyobj)) {
  452         /* verify access method type */
  453         type = _DB_get_type(self);
  454         if (type == -1)
  455             return 0;
  456         if (type == DB_RECNO || type == DB_QUEUE) {
  457             PyErr_SetString(
  458                 PyExc_TypeError,
  459 #if (PY_VERSION_HEX < 0x03000000)
  460                 "String keys not allowed for Recno and Queue DB's");
  461 #else
  462                 "Bytes keys not allowed for Recno and Queue DB's");
  463 #endif
  464             return 0;
  465         }
  466 
  467         /*
  468          * NOTE(gps): I don't like doing a data copy here, it seems
  469          * wasteful.  But without a clean way to tell FREE_DBT if it
  470          * should free key->data or not we have to.  Other places in
  471          * the code check for DB_THREAD and forceably set DBT_MALLOC
  472          * when we otherwise would leave flags 0 to indicate that.
  473          */
  474         key->data = malloc(PyBytes_GET_SIZE(keyobj));
  475         if (key->data == NULL) {
  476             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
  477             return 0;
  478         }
  479         memcpy(key->data, PyBytes_AS_STRING(keyobj),
  480                PyBytes_GET_SIZE(keyobj));
  481         key->flags = DB_DBT_REALLOC;
  482         key->size = PyBytes_GET_SIZE(keyobj);
  483     }
  484 
  485     else if (NUMBER_Check(keyobj)) {
  486         /* verify access method type */
  487         type = _DB_get_type(self);
  488         if (type == -1)
  489             return 0;
  490         if (type == DB_BTREE && pflags != NULL) {
  491             /* if BTREE then an Integer key is allowed with the
  492              * DB_SET_RECNO flag */
  493             *pflags |= DB_SET_RECNO;
  494         }
  495         else if (type != DB_RECNO && type != DB_QUEUE) {
  496             PyErr_SetString(
  497                 PyExc_TypeError,
  498                 "Integer keys only allowed for Recno and Queue DB's");
  499             return 0;
  500         }
  501 
  502         /* Make a key out of the requested recno, use allocated space so DB
  503          * will be able to realloc room for the real key if needed. */
  504         recno = NUMBER_AsLong(keyobj);
  505         key->data = malloc(sizeof(db_recno_t));
  506         if (key->data == NULL) {
  507             PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
  508             return 0;
  509         }
  510         key->ulen = key->size = sizeof(db_recno_t);
  511         memcpy(key->data, &recno, sizeof(db_recno_t));
  512         key->flags = DB_DBT_REALLOC;
  513     }
  514     else {
  515         PyErr_Format(PyExc_TypeError,
  516 #if (PY_VERSION_HEX < 0x03000000)
  517                      "String or Integer object expected for key, %s found",
  518 #else
  519                      "Bytes or Integer object expected for key, %s found",
  520 #endif
  521                      Py_TYPE(keyobj)->tp_name);
  522         return 0;
  523     }
  524 
  525     return 1;
  526 }
  527 
  528 
  529 /* Add partial record access to an existing DBT data struct.
  530    If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
  531    and the data storage/retrieval will be done using dlen and doff. */
  532 static int add_partial_dbt(DBT* d, int dlen, int doff) {
  533     /* if neither were set we do nothing (-1 is the default value) */
  534     if ((dlen == -1) && (doff == -1)) {
  535         return 1;
  536     }
  537 
  538     if ((dlen < 0) || (doff < 0)) {
  539         PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
  540         return 0;
  541     }
  542 
  543     d->flags = d->flags | DB_DBT_PARTIAL;
  544     d->dlen = (unsigned int) dlen;
  545     d->doff = (unsigned int) doff;
  546     return 1;
  547 }
  548 
  549 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
  550 /* TODO: make this use the native libc strlcpy() when available (BSD)      */
  551 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
  552 {
  553     unsigned int srclen, copylen;
  554 
  555     srclen = strlen(src);
  556     if (n <= 0)
  557         return srclen;
  558     copylen = (srclen > n-1) ? n-1 : srclen;
  559     /* populate dest[0] thru dest[copylen-1] */
  560     memcpy(dest, src, copylen);
  561     /* guarantee null termination */
  562     dest[copylen] = 0;
  563 
  564     return srclen;
  565 }
  566 
  567 /* Callback used to save away more information about errors from the DB
  568  * library. */
  569 static char _db_errmsg[1024];
  570 #if (DBVER <= 42)
  571 static void _db_errorCallback(const char* prefix, char* msg)
  572 #else
  573 static void _db_errorCallback(const DB_ENV *db_env,
  574         const char* prefix, const char* msg)
  575 #endif
  576 {
  577     our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
  578 }
  579 
  580 
  581 /*
  582 ** We need these functions because some results
  583 ** are undefined if pointer is NULL. Some other
  584 ** give None instead of "".
  585 **
  586 ** This functions are static and will be
  587 ** -I hope- inlined.
  588 */
  589 static const char *DummyString = "This string is a simple placeholder";
  590 static PyObject *Build_PyString(const char *p,int s)
  591 {
  592   if (!p) {
  593     p=DummyString;
  594     assert(s==0);
  595   }
  596   return PyBytes_FromStringAndSize(p,s);
  597 }
  598 
  599 static PyObject *BuildValue_S(const void *p,int s)
  600 {
  601   if (!p) {
  602     p=DummyString;
  603     assert(s==0);
  604   }
  605   return PyBytes_FromStringAndSize(p, s);
  606 }
  607 
  608 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
  609 {
  610 PyObject *a, *b, *r;
  611 
  612   if (!p1) {
  613     p1=DummyString;
  614     assert(s1==0);
  615   }
  616   if (!p2) {
  617     p2=DummyString;
  618     assert(s2==0);
  619   }
  620 
  621   if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
  622       return NULL;
  623   }
  624   if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
  625       Py_DECREF(a);
  626       return NULL;
  627   }
  628 
  629 #if (PY_VERSION_HEX >= 0x02040000)
  630   r = PyTuple_Pack(2, a, b) ;
  631 #else
  632   r = Py_BuildValue("OO", a, b);
  633 #endif
  634   Py_DECREF(a);
  635   Py_DECREF(b);
  636   return r;
  637 }
  638 
  639 static PyObject *BuildValue_IS(int i,const void *p,int s)
  640 {
  641   PyObject *a, *r;
  642 
  643   if (!p) {
  644     p=DummyString;
  645     assert(s==0);
  646   }
  647 
  648   if (!(a = PyBytes_FromStringAndSize(p, s))) {
  649       return NULL;
  650   }
  651 
  652   r = Py_BuildValue("iO", i, a);
  653   Py_DECREF(a);
  654   return r;
  655 }
  656 
  657 static PyObject *BuildValue_LS(long l,const void *p,int s)
  658 {
  659   PyObject *a, *r;
  660 
  661   if (!p) {
  662     p=DummyString;
  663     assert(s==0);
  664   }
  665 
  666   if (!(a = PyBytes_FromStringAndSize(p, s))) {
  667       return NULL;
  668   }
  669 
  670   r = Py_BuildValue("lO", l, a);
  671   Py_DECREF(a);
  672   return r;
  673 }
  674 
  675 
  676 
  677 /* make a nice exception object to raise for errors. */
  678 static int makeDBError(int err)
  679 {
  680     char errTxt[2048];  /* really big, just in case... */
  681     PyObject *errObj = NULL;
  682     PyObject *errTuple = NULL;
  683     int exceptionRaised = 0;
  684     unsigned int bytes_left;
  685 
  686     switch (err) {
  687         case 0:                     /* successful, no error */
  688             return 0;
  689 
  690         case DB_KEYEMPTY:           errObj = DBKeyEmptyError;       break;
  691         case DB_KEYEXIST:           errObj = DBKeyExistError;       break;
  692         case DB_LOCK_DEADLOCK:      errObj = DBLockDeadlockError;   break;
  693         case DB_LOCK_NOTGRANTED:    errObj = DBLockNotGrantedError; break;
  694         case DB_NOTFOUND:           errObj = DBNotFoundError;       break;
  695         case DB_OLD_VERSION:        errObj = DBOldVersionError;     break;
  696         case DB_RUNRECOVERY:        errObj = DBRunRecoveryError;    break;
  697         case DB_VERIFY_BAD:         errObj = DBVerifyBadError;      break;
  698         case DB_NOSERVER:           errObj = DBNoServerError;       break;
  699         case DB_NOSERVER_HOME:      errObj = DBNoServerHomeError;   break;
  700         case DB_NOSERVER_ID:        errObj = DBNoServerIDError;     break;
  701         case DB_PAGE_NOTFOUND:      errObj = DBPageNotFoundError;   break;
  702         case DB_SECONDARY_BAD:      errObj = DBSecondaryBadError;   break;
  703         case DB_BUFFER_SMALL:       errObj = DBNoMemoryError;       break;
  704 
  705 #if (DBVER >= 43)
  706         /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
  707         case ENOMEM:  errObj = PyExc_MemoryError;   break;
  708 #endif
  709         case EINVAL:  errObj = DBInvalidArgError;   break;
  710         case EACCES:  errObj = DBAccessError;       break;
  711         case ENOSPC:  errObj = DBNoSpaceError;      break;
  712         case EAGAIN:  errObj = DBAgainError;        break;
  713         case EBUSY :  errObj = DBBusyError;         break;
  714         case EEXIST:  errObj = DBFileExistsError;   break;
  715         case ENOENT:  errObj = DBNoSuchFileError;   break;
  716         case EPERM :  errObj = DBPermissionsError;  break;
  717 
  718 #if (DBVER >= 42)
  719         case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
  720 #endif
  721 #if (DBVER >= 44)
  722         case DB_REP_LOCKOUT : errObj = DBRepLockoutError; break;
  723 #endif
  724 
  725 #if (DBVER >= 46)
  726         case DB_REP_LEASE_EXPIRED : errObj = DBRepLeaseExpiredError; break;
  727 #endif
  728 
  729 #if (DBVER >= 47)
  730         case DB_FOREIGN_CONFLICT : errObj = DBForeignConflictError; break;
  731 #endif
  732 
  733         case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
  734 
  735         default:      errObj = DBError;             break;
  736     }
  737 
  738     if (errObj != NULL) {
  739         bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
  740         /* Ensure that bytes_left never goes negative */
  741         if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
  742             bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
  743             assert(bytes_left >= 0);
  744             strcat(errTxt, " -- ");
  745             strncat(errTxt, _db_errmsg, bytes_left);
  746         }
  747         _db_errmsg[0] = 0;
  748 
  749         errTuple = Py_BuildValue("(is)", err, errTxt);
  750         if (errTuple == NULL) {
  751             Py_DECREF(errObj);
  752             return !0;
  753         }
  754         PyErr_SetObject(errObj, errTuple);
  755         Py_DECREF(errTuple);
  756     }
  757 
  758     return ((errObj != NULL) || exceptionRaised);
  759 }
  760 
  761 
  762 
  763 /* set a type exception */
  764 static void makeTypeError(char* expected, PyObject* found)
  765 {
  766     PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
  767                  expected, Py_TYPE(found)->tp_name);
  768 }
  769 
  770 
  771 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
  772 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
  773 {
  774     if (txnobj == Py_None || txnobj == NULL) {
  775         *txn = NULL;
  776         return 1;
  777     }
  778     if (DBTxnObject_Check(txnobj)) {
  779         *txn = ((DBTxnObject*)txnobj)->txn;
  780         return 1;
  781     }
  782     else
  783         makeTypeError("DBTxn", txnobj);
  784     return 0;
  785 }
  786 
  787 
  788 /* Delete a key from a database
  789   Returns 0 on success, -1 on an error.  */
  790 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
  791 {
  792     int err;
  793 
  794     MYDB_BEGIN_ALLOW_THREADS;
  795     err = self->db->del(self->db, txn, key, 0);
  796     MYDB_END_ALLOW_THREADS;
  797     if (makeDBError(err)) {
  798         return -1;
  799     }
  800     return 0;
  801 }
  802 
  803 
  804 /* Store a key into a database
  805    Returns 0 on success, -1 on an error.  */
  806 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
  807 {
  808     int err;
  809 
  810     MYDB_BEGIN_ALLOW_THREADS;
  811     err = self->db->put(self->db, txn, key, data, flags);
  812     MYDB_END_ALLOW_THREADS;
  813     if (makeDBError(err)) {
  814         return -1;
  815     }
  816     return 0;
  817 }
  818 
  819 /* Get a key/data pair from a cursor */
  820 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
  821                                PyObject *args, PyObject *kwargs, char *format)
  822 {
  823     int err;
  824     PyObject* retval = NULL;
  825     DBT key, data;
  826     int dlen = -1;
  827     int doff = -1;
  828     int flags = 0;
  829     static char* kwnames[] = { "flags", "dlen", "doff", NULL };
  830 
  831     if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
  832                                      &flags, &dlen, &doff))
  833       return NULL;
  834 
  835     CHECK_CURSOR_NOT_CLOSED(self);
  836 
  837     flags |= extra_flags;
  838     CLEAR_DBT(key);
  839     CLEAR_DBT(data);
  840     if (!add_partial_dbt(&data, dlen, doff))
  841         return NULL;
  842 
  843     MYDB_BEGIN_ALLOW_THREADS;
  844     err = _DBC_get(self->dbc, &key, &data, flags);
  845     MYDB_END_ALLOW_THREADS;
  846 
  847     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
  848             && self->mydb->moduleFlags.getReturnsNone) {
  849         Py_INCREF(Py_None);
  850         retval = Py_None;
  851     }
  852     else if (makeDBError(err)) {
  853         retval = NULL;
  854     }
  855     else {  /* otherwise, success! */
  856 
  857         /* if Recno or Queue, return the key as an Int */
  858         switch (_DB_get_type(self->mydb)) {
  859         case -1:
  860             retval = NULL;
  861             break;
  862 
  863         case DB_RECNO:
  864         case DB_QUEUE:
  865             retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
  866             break;
  867         case DB_HASH:
  868         case DB_BTREE:
  869         default:
  870             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
  871             break;
  872         }
  873     }
  874     return retval;
  875 }
  876 
  877 
  878 /* add an integer to a dictionary using the given name as a key */
  879 static void _addIntToDict(PyObject* dict, char *name, int value)
  880 {
  881     PyObject* v = NUMBER_FromLong((long) value);
  882     if (!v || PyDict_SetItemString(dict, name, v))
  883         PyErr_Clear();
  884 
  885     Py_XDECREF(v);
  886 }
  887 
  888 /* The same, when the value is a time_t */
  889 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
  890 {
  891     PyObject* v;
  892         /* if the value fits in regular int, use that. */
  893 #ifdef PY_LONG_LONG
  894         if (sizeof(time_t) > sizeof(long))
  895                 v = PyLong_FromLongLong((PY_LONG_LONG) value);
  896         else
  897 #endif
  898                 v = NUMBER_FromLong((long) value);
  899     if (!v || PyDict_SetItemString(dict, name, v))
  900         PyErr_Clear();
  901 
  902     Py_XDECREF(v);
  903 }
  904 
  905 #if (DBVER >= 43)
  906 /* add an db_seq_t to a dictionary using the given name as a key */
  907 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
  908 {
  909     PyObject* v = PyLong_FromLongLong(value);
  910     if (!v || PyDict_SetItemString(dict, name, v))
  911         PyErr_Clear();
  912 
  913     Py_XDECREF(v);
  914 }
  915 #endif
  916 
  917 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
  918 {
  919     PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
  920     if (!v || PyDict_SetItemString(dict, name, v))
  921         PyErr_Clear();
  922 
  923     Py_XDECREF(v);
  924 }
  925 
  926 /* --------------------------------------------------------------------- */
  927 /* Allocators and deallocators */
  928 
  929 static DBObject*
  930 newDBObject(DBEnvObject* arg, int flags)
  931 {
  932     DBObject* self;
  933     DB_ENV* db_env = NULL;
  934     int err;
  935 
  936     self = PyObject_New(DBObject, &DB_Type);
  937     if (self == NULL)
  938         return NULL;
  939 
  940     self->flags = 0;
  941     self->setflags = 0;
  942     self->myenvobj = NULL;
  943     self->db = NULL;
  944     self->children_cursors = NULL;
  945 #if (DBVER >=43)
  946     self->children_sequences = NULL;
  947 #endif
  948     self->associateCallback = NULL;
  949     self->btCompareCallback = NULL;
  950     self->primaryDBType = 0;
  951     Py_INCREF(Py_None);
  952     self->private_obj = Py_None;
  953     self->in_weakreflist = NULL;
  954 
  955     /* keep a reference to our python DBEnv object */
  956     if (arg) {
  957         Py_INCREF(arg);
  958         self->myenvobj = arg;
  959         db_env = arg->db_env;
  960         INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
  961     } else {
  962       self->sibling_prev_p=NULL;
  963       self->sibling_next=NULL;
  964     }
  965     self->txn=NULL;
  966     self->sibling_prev_p_txn=NULL;
  967     self->sibling_next_txn=NULL;
  968 
  969     if (self->myenvobj)
  970         self->moduleFlags = self->myenvobj->moduleFlags;
  971     else
  972         self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
  973         self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
  974 
  975     MYDB_BEGIN_ALLOW_THREADS;
  976     err = db_create(&self->db, db_env, flags);
  977     if (self->db != NULL) {
  978         self->db->set_errcall(self->db, _db_errorCallback);
  979         self->db->app_private = (void*)self;
  980     }
  981     MYDB_END_ALLOW_THREADS;
  982     /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
  983      * list so that a DBEnv can refuse to close without aborting any open
  984      * DBTxns and closing any open DBs first. */
  985     if (makeDBError(err)) {
  986         if (self->myenvobj) {
  987             Py_DECREF(self->myenvobj);
  988             self->myenvobj = NULL;
  989         }
  990         Py_DECREF(self);
  991         self = NULL;
  992     }
  993     return self;
  994 }
  995 
  996 
  997 /* Forward declaration */
  998 static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
  999 
 1000 static void
 1001 DB_dealloc(DBObject* self)
 1002 {
 1003   PyObject *dummy;
 1004 
 1005     if (self->db != NULL) {
 1006         dummy=DB_close_internal(self, 0, 0);
 1007         /*
 1008         ** Raising exceptions while doing
 1009         ** garbage collection is a fatal error.
 1010         */
 1011         if (dummy)
 1012             Py_DECREF(dummy);
 1013         else
 1014             PyErr_Clear();
 1015     }
 1016     if (self->in_weakreflist != NULL) {
 1017         PyObject_ClearWeakRefs((PyObject *) self);
 1018     }
 1019     if (self->myenvobj) {
 1020         Py_DECREF(self->myenvobj);
 1021         self->myenvobj = NULL;
 1022     }
 1023     if (self->associateCallback != NULL) {
 1024         Py_DECREF(self->associateCallback);
 1025         self->associateCallback = NULL;
 1026     }
 1027     if (self->btCompareCallback != NULL) {
 1028         Py_DECREF(self->btCompareCallback);
 1029         self->btCompareCallback = NULL;
 1030     }
 1031     Py_DECREF(self->private_obj);
 1032     PyObject_Del(self);
 1033 }
 1034 
 1035 static DBCursorObject*
 1036 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
 1037 {
 1038     DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
 1039     if (self == NULL)
 1040         return NULL;
 1041 
 1042     self->dbc = dbc;
 1043     self->mydb = db;
 1044 
 1045     INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
 1046     if (txn && ((PyObject *)txn!=Py_None)) {
 1047             INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
 1048             self->txn=txn;
 1049     } else {
 1050             self->txn=NULL;
 1051     }
 1052 
 1053     self->in_weakreflist = NULL;
 1054     Py_INCREF(self->mydb);
 1055     return self;
 1056 }
 1057 
 1058 
 1059 /* Forward declaration */
 1060 static PyObject *DBC_close_internal(DBCursorObject* self);
 1061 
 1062 static void
 1063 DBCursor_dealloc(DBCursorObject* self)
 1064 {
 1065     PyObject *dummy;
 1066 
 1067     if (self->dbc != NULL) {
 1068         dummy=DBC_close_internal(self);
 1069         /*
 1070         ** Raising exceptions while doing
 1071         ** garbage collection is a fatal error.
 1072         */
 1073         if (dummy)
 1074             Py_DECREF(dummy);
 1075         else
 1076             PyErr_Clear();
 1077     }
 1078     if (self->in_weakreflist != NULL) {
 1079         PyObject_ClearWeakRefs((PyObject *) self);
 1080     }
 1081     Py_DECREF(self->mydb);
 1082     PyObject_Del(self);
 1083 }
 1084 
 1085 
 1086 static DBLogCursorObject*
 1087 newDBLogCursorObject(DB_LOGC* dblogc, DBEnvObject* env)
 1088 {
 1089     DBLogCursorObject* self;
 1090 
 1091     self = PyObject_New(DBLogCursorObject, &DBLogCursor_Type);
 1092 
 1093     if (self == NULL)
 1094         return NULL;
 1095 
 1096     self->logc = dblogc;
 1097     self->env = env;
 1098 
 1099     INSERT_IN_DOUBLE_LINKED_LIST(self->env->children_logcursors, self);
 1100 
 1101     self->in_weakreflist = NULL;
 1102     Py_INCREF(self->env);
 1103     return self;
 1104 }
 1105 
 1106 
 1107 /* Forward declaration */
 1108 static PyObject *DBLogCursor_close_internal(DBLogCursorObject* self);
 1109 
 1110 static void
 1111 DBLogCursor_dealloc(DBLogCursorObject* self)
 1112 {
 1113     PyObject *dummy;
 1114 
 1115     if (self->logc != NULL) {
 1116         dummy = DBLogCursor_close_internal(self);
 1117         /*
 1118         ** Raising exceptions while doing
 1119         ** garbage collection is a fatal error.
 1120         */
 1121         if (dummy)
 1122             Py_DECREF(dummy);
 1123         else
 1124             PyErr_Clear();
 1125     }
 1126     if (self->in_weakreflist != NULL) {
 1127         PyObject_ClearWeakRefs((PyObject *) self);
 1128     }
 1129     Py_DECREF(self->env);
 1130     PyObject_Del(self);
 1131 }
 1132 
 1133 
 1134 static DBEnvObject*
 1135 newDBEnvObject(int flags)
 1136 {
 1137     int err;
 1138     DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
 1139     if (self == NULL)
 1140         return NULL;
 1141 
 1142     self->db_env = NULL;
 1143     self->closed = 1;
 1144     self->flags = flags;
 1145     self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
 1146     self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
 1147     self->children_dbs = NULL;
 1148     self->children_txns = NULL;
 1149     self->children_logcursors = NULL ;
 1150     Py_INCREF(Py_None);
 1151     self->private_obj = Py_None;
 1152     Py_INCREF(Py_None);
 1153     self->rep_transport = Py_None;
 1154     self->in_weakreflist = NULL;
 1155     self->event_notifyCallback = NULL;
 1156 
 1157     MYDB_BEGIN_ALLOW_THREADS;
 1158     err = db_env_create(&self->db_env, flags);
 1159     MYDB_END_ALLOW_THREADS;
 1160     if (makeDBError(err)) {
 1161         Py_DECREF(self);
 1162         self = NULL;
 1163     }
 1164     else {
 1165         self->db_env->set_errcall(self->db_env, _db_errorCallback);
 1166         self->db_env->app_private = self;
 1167     }
 1168     return self;
 1169 }
 1170 
 1171 /* Forward declaration */
 1172 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
 1173 
 1174 static void
 1175 DBEnv_dealloc(DBEnvObject* self)
 1176 {
 1177   PyObject *dummy;
 1178 
 1179     if (self->db_env) {
 1180         dummy=DBEnv_close_internal(self, 0);
 1181         /*
 1182         ** Raising exceptions while doing
 1183         ** garbage collection is a fatal error.
 1184         */
 1185         if (dummy)
 1186             Py_DECREF(dummy);
 1187         else
 1188             PyErr_Clear();
 1189     }
 1190 
 1191     Py_XDECREF(self->event_notifyCallback);
 1192     self->event_notifyCallback = NULL;
 1193 
 1194     if (self->in_weakreflist != NULL) {
 1195         PyObject_ClearWeakRefs((PyObject *) self);
 1196     }
 1197     Py_DECREF(self->private_obj);
 1198     Py_DECREF(self->rep_transport);
 1199     PyObject_Del(self);
 1200 }
 1201 
 1202 
 1203 static DBTxnObject*
 1204 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
 1205 {
 1206     int err;
 1207     DB_TXN *parent_txn = NULL;
 1208 
 1209     DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
 1210     if (self == NULL)
 1211         return NULL;
 1212 
 1213     self->in_weakreflist = NULL;
 1214     self->children_txns = NULL;
 1215     self->children_dbs = NULL;
 1216     self->children_cursors = NULL;
 1217     self->children_sequences = NULL;
 1218     self->flag_prepare = 0;
 1219     self->parent_txn = NULL;
 1220     self->env = NULL;
 1221     /* We initialize just in case "txn_begin" fails */
 1222     self->txn = NULL;
 1223 
 1224     if (parent && ((PyObject *)parent!=Py_None)) {
 1225         parent_txn = parent->txn;
 1226     }
 1227 
 1228     if (txn) {
 1229         self->txn = txn;
 1230     } else {
 1231         MYDB_BEGIN_ALLOW_THREADS;
 1232         err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
 1233         MYDB_END_ALLOW_THREADS;
 1234 
 1235         if (makeDBError(err)) {
 1236             /* Free object half initialized */
 1237             Py_DECREF(self);
 1238             return NULL;
 1239         }
 1240     }
 1241 
 1242     /* Can't use 'parent' because could be 'parent==Py_None' */
 1243     if (parent_txn) {
 1244         self->parent_txn = parent;
 1245         Py_INCREF(parent);
 1246         self->env = NULL;
 1247         INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
 1248     } else {
 1249         self->parent_txn = NULL;
 1250         Py_INCREF(myenv);
 1251         self->env = myenv;
 1252         INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
 1253     }
 1254 
 1255     return self;
 1256 }
 1257 
 1258 /* Forward declaration */
 1259 static PyObject *
 1260 DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
 1261 
 1262 static void
 1263 DBTxn_dealloc(DBTxnObject* self)
 1264 {
 1265   PyObject *dummy;
 1266 
 1267     if (self->txn) {
 1268         int flag_prepare = self->flag_prepare;
 1269 
 1270         dummy=DBTxn_abort_discard_internal(self, 0);
 1271         /*
 1272         ** Raising exceptions while doing
 1273         ** garbage collection is a fatal error.
 1274         */
 1275         if (dummy)
 1276             Py_DECREF(dummy);
 1277         else
 1278             PyErr_Clear();
 1279 
 1280         if (!flag_prepare) {
 1281             PyErr_Warn(PyExc_RuntimeWarning,
 1282               "DBTxn aborted in destructor.  No prior commit() or abort().");
 1283         }
 1284     }
 1285 
 1286     if (self->in_weakreflist != NULL) {
 1287         PyObject_ClearWeakRefs((PyObject *) self);
 1288     }
 1289 
 1290     if (self->env) {
 1291         Py_DECREF(self->env);
 1292     } else {
 1293         /*
 1294         ** We can have "self->env==NULL" and "self->parent_txn==NULL"
 1295         ** if something happens when creating the transaction object
 1296         ** and we abort the object while half done.
 1297         */
 1298         Py_XDECREF(self->parent_txn);
 1299     }
 1300     PyObject_Del(self);
 1301 }
 1302 
 1303 
 1304 static DBLockObject*
 1305 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
 1306                 db_lockmode_t lock_mode, int flags)
 1307 {
 1308     int err;
 1309     DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
 1310     if (self == NULL)
 1311         return NULL;
 1312     self->in_weakreflist = NULL;
 1313     self->lock_initialized = 0;  /* Just in case the call fails */
 1314 
 1315     MYDB_BEGIN_ALLOW_THREADS;
 1316     err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
 1317                                   &self->lock);
 1318     MYDB_END_ALLOW_THREADS;
 1319     if (makeDBError(err)) {
 1320         Py_DECREF(self);
 1321         self = NULL;
 1322     } else {
 1323         self->lock_initialized = 1;
 1324     }
 1325 
 1326     return self;
 1327 }
 1328 
 1329 
 1330 static void
 1331 DBLock_dealloc(DBLockObject* self)
 1332 {
 1333     if (self->in_weakreflist != NULL) {
 1334         PyObject_ClearWeakRefs((PyObject *) self);
 1335     }
 1336     /* TODO: is this lock held? should we release it? */
 1337     /* CAUTION: The lock can be not initialized if the creation has failed */
 1338 
 1339     PyObject_Del(self);
 1340 }
 1341 
 1342 
 1343 #if (DBVER >= 43)
 1344 static DBSequenceObject*
 1345 newDBSequenceObject(DBObject* mydb,  int flags)
 1346 {
 1347     int err;
 1348     DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
 1349     if (self == NULL)
 1350         return NULL;
 1351     Py_INCREF(mydb);
 1352     self->mydb = mydb;
 1353 
 1354     INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
 1355     self->txn = NULL;
 1356 
 1357     self->in_weakreflist = NULL;
 1358     self->sequence = NULL;  /* Just in case the call fails */
 1359 
 1360     MYDB_BEGIN_ALLOW_THREADS;
 1361     err = db_sequence_create(&self->sequence, self->mydb->db, flags);
 1362     MYDB_END_ALLOW_THREADS;
 1363     if (makeDBError(err)) {
 1364         Py_DECREF(self);
 1365         self = NULL;
 1366     }
 1367 
 1368     return self;
 1369 }
 1370 
 1371 /* Forward declaration */
 1372 static PyObject
 1373 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
 1374 
 1375 static void
 1376 DBSequence_dealloc(DBSequenceObject* self)
 1377 {
 1378     PyObject *dummy;
 1379 
 1380     if (self->sequence != NULL) {
 1381         dummy=DBSequence_close_internal(self,0,0);
 1382         /*
 1383         ** Raising exceptions while doing
 1384         ** garbage collection is a fatal error.
 1385         */
 1386         if (dummy)
 1387             Py_DECREF(dummy);
 1388         else
 1389             PyErr_Clear();
 1390     }
 1391 
 1392     if (self->in_weakreflist != NULL) {
 1393         PyObject_ClearWeakRefs((PyObject *) self);
 1394     }
 1395 
 1396     Py_DECREF(self->mydb);
 1397     PyObject_Del(self);
 1398 }
 1399 #endif
 1400 
 1401 /* --------------------------------------------------------------------- */
 1402 /* DB methods */
 1403 
 1404 static PyObject*
 1405 DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
 1406 {
 1407     PyObject* txnobj = NULL;
 1408     PyObject* dataobj;
 1409     db_recno_t recno;
 1410     DBT key, data;
 1411     DB_TXN *txn = NULL;
 1412     static char* kwnames[] = { "data", "txn", NULL };
 1413 
 1414     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
 1415                                      &dataobj, &txnobj))
 1416         return NULL;
 1417 
 1418     CHECK_DB_NOT_CLOSED(self);
 1419 
 1420     /* make a dummy key out of a recno */
 1421     recno = 0;
 1422     CLEAR_DBT(key);
 1423     key.data = &recno;
 1424     key.size = sizeof(recno);
 1425     key.ulen = key.size;
 1426     key.flags = DB_DBT_USERMEM;
 1427 
 1428     if (!make_dbt(dataobj, &data)) return NULL;
 1429     if (!checkTxnObj(txnobj, &txn)) return NULL;
 1430 
 1431     if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
 1432         return NULL;
 1433 
 1434     return NUMBER_FromLong(recno);
 1435 }
 1436 
 1437 
 1438 static int
 1439 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
 1440                       DBT* secKey)
 1441 {
 1442     int       retval = DB_DONOTINDEX;
 1443     DBObject* secondaryDB = (DBObject*)db->app_private;
 1444     PyObject* callback = secondaryDB->associateCallback;
 1445     int       type = secondaryDB->primaryDBType;
 1446     PyObject* args;
 1447     PyObject* result = NULL;
 1448 
 1449 
 1450     if (callback != NULL) {
 1451         MYDB_BEGIN_BLOCK_THREADS;
 1452 
 1453         if (type == DB_RECNO || type == DB_QUEUE)
 1454             args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
 1455         else
 1456             args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
 1457         if (args != NULL) {
 1458                 result = PyEval_CallObject(callback, args);
 1459         }
 1460         if (args == NULL || result == NULL) {
 1461             PyErr_Print();
 1462         }
 1463         else if (result == Py_None) {
 1464             retval = DB_DONOTINDEX;
 1465         }
 1466         else if (NUMBER_Check(result)) {
 1467             retval = NUMBER_AsLong(result);
 1468         }
 1469         else if (PyBytes_Check(result)) {
 1470             char* data;
 1471             Py_ssize_t size;
 1472 
 1473             CLEAR_DBT(*secKey);
 1474             PyBytes_AsStringAndSize(result, &data, &size);
 1475             secKey->flags = DB_DBT_APPMALLOC;   /* DB will free */
 1476             secKey->data = malloc(size);        /* TODO, check this */
 1477             if (secKey->data) {
 1478                 memcpy(secKey->data, data, size);
 1479                 secKey->size = size;
 1480                 retval = 0;
 1481             }
 1482             else {
 1483                 PyErr_SetString(PyExc_MemoryError,
 1484                                 "malloc failed in _db_associateCallback");
 1485                 PyErr_Print();
 1486             }
 1487         }
 1488 #if (DBVER >= 46)
 1489         else if (PyList_Check(result))
 1490         {
 1491             char* data;
 1492             Py_ssize_t size;
 1493             int i, listlen;
 1494             DBT* dbts;
 1495 
 1496             listlen = PyList_Size(result);
 1497 
 1498             dbts = (DBT *)malloc(sizeof(DBT) * listlen);
 1499 
 1500             for (i=0; i<listlen; i++)
 1501             {
 1502                 if (!PyBytes_Check(PyList_GetItem(result, i)))
 1503                 {
 1504                     PyErr_SetString(
 1505                        PyExc_TypeError,
 1506 #if (PY_VERSION_HEX < 0x03000000)
 1507 "The list returned by DB->associate callback should be a list of strings.");
 1508 #else
 1509 "The list returned by DB->associate callback should be a list of bytes.");
 1510 #endif
 1511                     PyErr_Print();
 1512                 }
 1513 
 1514                 PyBytes_AsStringAndSize(
 1515                     PyList_GetItem(result, i),
 1516                     &data, &size);
 1517 
 1518                 CLEAR_DBT(dbts[i]);
 1519                 dbts[i].data = malloc(size);          /* TODO, check this */
 1520 
 1521                 if (dbts[i].data)
 1522                 {
 1523                     memcpy(dbts[i].data, data, size);
 1524                     dbts[i].size = size;
 1525                     dbts[i].ulen = dbts[i].size;
 1526                     dbts[i].flags = DB_DBT_APPMALLOC;  /* DB will free */
 1527                 }
 1528                 else
 1529                 {
 1530                     PyErr_SetString(PyExc_MemoryError,
 1531                         "malloc failed in _db_associateCallback (list)");
 1532                     PyErr_Print();
 1533                 }
 1534             }
 1535 
 1536             CLEAR_DBT(*secKey);
 1537 
 1538             secKey->data = dbts;
 1539             secKey->size = listlen;
 1540             secKey->flags = DB_DBT_APPMALLOC | DB_DBT_MULTIPLE;
 1541             retval = 0;
 1542         }
 1543 #endif
 1544         else {
 1545             PyErr_SetString(
 1546                PyExc_TypeError,
 1547 #if (PY_VERSION_HEX < 0x03000000)
 1548 "DB associate callback should return DB_DONOTINDEX/string/list of strings.");
 1549 #else
 1550 "DB associate callback should return DB_DONOTINDEX/bytes/list of bytes.");
 1551 #endif
 1552             PyErr_Print();
 1553         }
 1554 
 1555         Py_XDECREF(args);
 1556         Py_XDECREF(result);
 1557 
 1558         MYDB_END_BLOCK_THREADS;
 1559     }
 1560     return retval;
 1561 }
 1562 
 1563 
 1564 static PyObject*
 1565 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
 1566 {
 1567     int err, flags=0;
 1568     DBObject* secondaryDB;
 1569     PyObject* callback;
 1570     PyObject *txnobj = NULL;
 1571     DB_TXN *txn = NULL;
 1572     static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
 1573                                     NULL};
 1574 
 1575     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
 1576                                      &secondaryDB, &callback, &flags,
 1577                                      &txnobj)) {
 1578         return NULL;
 1579     }
 1580 
 1581     if (!checkTxnObj(txnobj, &txn)) return NULL;
 1582 
 1583     CHECK_DB_NOT_CLOSED(self);
 1584     if (!DBObject_Check(secondaryDB)) {
 1585         makeTypeError("DB", (PyObject*)secondaryDB);
 1586         return NULL;
 1587     }
 1588     CHECK_DB_NOT_CLOSED(secondaryDB);
 1589     if (callback == Py_None) {
 1590         callback = NULL;
 1591     }
 1592     else if (!PyCallable_Check(callback)) {
 1593         makeTypeError("Callable", callback);
 1594         return NULL;
 1595     }
 1596 
 1597     /* Save a reference to the callback in the secondary DB. */
 1598     Py_XDECREF(secondaryDB->associateCallback);
 1599     Py_XINCREF(callback);
 1600     secondaryDB->associateCallback = callback;
 1601     secondaryDB->primaryDBType = _DB_get_type(self);
 1602 
 1603     /* PyEval_InitThreads is called here due to a quirk in python 1.5
 1604      * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
 1605      * The global interepreter lock is not initialized until the first
 1606      * thread is created using thread.start_new_thread() or fork() is
 1607      * called.  that would cause the ALLOW_THREADS here to segfault due
 1608      * to a null pointer reference if no threads or child processes
 1609      * have been created.  This works around that and is a no-op if
 1610      * threads have already been initialized.
 1611      *  (see pybsddb-users mailing list post on 2002-08-07)
 1612      */
 1613 #ifdef WITH_THREAD
 1614     PyEval_InitThreads();
 1615 #endif
 1616     MYDB_BEGIN_ALLOW_THREADS;
 1617     err = self->db->associate(self->db,
 1618                               txn,
 1619                               secondaryDB->db,
 1620                               _db_associateCallback,
 1621                               flags);
 1622     MYDB_END_ALLOW_THREADS;
 1623 
 1624     if (err) {
 1625         Py_XDECREF(secondaryDB->associateCallback);
 1626         secondaryDB->associateCallback = NULL;
 1627         secondaryDB->primaryDBType = 0;
 1628     }
 1629 
 1630     RETURN_IF_ERR();
 1631     RETURN_NONE();
 1632 }
 1633 
 1634 
 1635 static PyObject*
 1636 DB_close_internal(DBObject* self, int flags, int do_not_close)
 1637 {
 1638     PyObject *dummy;
 1639     int err = 0;
 1640 
 1641     if (self->db != NULL) {
 1642         /* Can be NULL if db is not in an environment */
 1643         EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
 1644 
 1645         if (self->txn) {
 1646             EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
 1647             self->txn=NULL;
 1648         }
 1649 
 1650         while(self->children_cursors) {
 1651           dummy=DBC_close_internal(self->children_cursors);
 1652           Py_XDECREF(dummy);
 1653         }
 1654 
 1655 #if (DBVER >= 43)
 1656         while(self->children_sequences) {
 1657             dummy=DBSequence_close_internal(self->children_sequences,0,0);
 1658             Py_XDECREF(dummy);
 1659         }
 1660 #endif
 1661 
 1662         /*
 1663         ** "do_not_close" is used to dispose all related objects in the
 1664         ** tree, without actually releasing the "root" object.
 1665         ** This is done, for example, because function calls like
 1666         ** "DB.verify()" implicitly close the underlying handle. So
 1667         ** the handle doesn't need to be closed, but related objects
 1668         ** must be cleaned up.
 1669         */
 1670         if (!do_not_close) {
 1671             MYDB_BEGIN_ALLOW_THREADS;
 1672             err = self->db->close(self->db, flags);
 1673             MYDB_END_ALLOW_THREADS;
 1674             self->db = NULL;
 1675         }
 1676         RETURN_IF_ERR();
 1677     }
 1678     RETURN_NONE();
 1679 }
 1680 
 1681 static PyObject*
 1682 DB_close(DBObject* self, PyObject* args)
 1683 {
 1684     int flags=0;
 1685     if (!PyArg_ParseTuple(args,"|i:close", &flags))
 1686         return NULL;
 1687     return DB_close_internal(self, flags, 0);
 1688 }
 1689 
 1690 
 1691 static PyObject*
 1692 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
 1693 {
 1694     int err, flags=0, type;
 1695     PyObject* txnobj = NULL;
 1696     PyObject* retval = NULL;
 1697     DBT key, data;
 1698     DB_TXN *txn = NULL;
 1699     static char* kwnames[] = { "txn", "flags", NULL };
 1700 
 1701     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
 1702                                      &txnobj, &flags))
 1703         return NULL;
 1704 
 1705     CHECK_DB_NOT_CLOSED(self);
 1706     type = _DB_get_type(self);
 1707     if (type == -1)
 1708         return NULL;
 1709     if (type != DB_QUEUE) {
 1710         PyErr_SetString(PyExc_TypeError,
 1711                         "Consume methods only allowed for Queue DB's");
 1712         return NULL;
 1713     }
 1714     if (!checkTxnObj(txnobj, &txn))
 1715         return NULL;
 1716 
 1717     CLEAR_DBT(key);
 1718     CLEAR_DBT(data);
 1719     if (CHECK_DBFLAG(self, DB_THREAD)) {
 1720         /* Tell Berkeley DB to malloc the return value (thread safe) */
 1721         data.flags = DB_DBT_MALLOC;
 1722         key.flags = DB_DBT_MALLOC;
 1723     }
 1724 
 1725     MYDB_BEGIN_ALLOW_THREADS;
 1726     err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
 1727     MYDB_END_ALLOW_THREADS;
 1728 
 1729     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 1730             && self->moduleFlags.getReturnsNone) {
 1731         err = 0;
 1732         Py_INCREF(Py_None);
 1733         retval = Py_None;
 1734     }
 1735     else if (!err) {
 1736         retval = BuildValue_SS(key.data, key.size, data.data, data.size);
 1737         FREE_DBT(key);
 1738         FREE_DBT(data);
 1739     }
 1740 
 1741     RETURN_IF_ERR();
 1742     return retval;
 1743 }
 1744 
 1745 static PyObject*
 1746 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
 1747 {
 1748     return _DB_consume(self, args, kwargs, DB_CONSUME);
 1749 }
 1750 
 1751 static PyObject*
 1752 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
 1753                 int consume_flag)
 1754 {
 1755     return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
 1756 }
 1757 
 1758 
 1759 static PyObject*
 1760 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
 1761 {
 1762     int err, flags=0;
 1763     DBC* dbc;
 1764     PyObject* txnobj = NULL;
 1765     DB_TXN *txn = NULL;
 1766     static char* kwnames[] = { "txn", "flags", NULL };
 1767 
 1768     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
 1769                                      &txnobj, &flags))
 1770         return NULL;
 1771     CHECK_DB_NOT_CLOSED(self);
 1772     if (!checkTxnObj(txnobj, &txn))
 1773         return NULL;
 1774 
 1775     MYDB_BEGIN_ALLOW_THREADS;
 1776     err = self->db->cursor(self->db, txn, &dbc, flags);
 1777     MYDB_END_ALLOW_THREADS;
 1778     RETURN_IF_ERR();
 1779     return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
 1780 }
 1781 
 1782 
 1783 static PyObject*
 1784 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
 1785 {
 1786     PyObject* txnobj = NULL;
 1787     int flags = 0;
 1788     PyObject* keyobj;
 1789     DBT key;
 1790     DB_TXN *txn = NULL;
 1791     static char* kwnames[] = { "key", "txn", "flags", NULL };
 1792 
 1793     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
 1794                                      &keyobj, &txnobj, &flags))
 1795         return NULL;
 1796     CHECK_DB_NOT_CLOSED(self);
 1797     if (!make_key_dbt(self, keyobj, &key, NULL))
 1798         return NULL;
 1799     if (!checkTxnObj(txnobj, &txn)) {
 1800         FREE_DBT(key);
 1801         return NULL;
 1802     }
 1803 
 1804     if (-1 == _DB_delete(self, txn, &key, 0)) {
 1805         FREE_DBT(key);
 1806         return NULL;
 1807     }
 1808 
 1809     FREE_DBT(key);
 1810     RETURN_NONE();
 1811 }
 1812 
 1813 
 1814 #if (DBVER >= 47)
 1815 /*
 1816 ** This function is available since Berkeley DB 4.4,
 1817 ** but 4.6 version is so buggy that we only support
 1818 ** it from BDB 4.7 and newer.
 1819 */
 1820 static PyObject*
 1821 DB_compact(DBObject* self, PyObject* args, PyObject* kwargs)
 1822 {
 1823     PyObject* txnobj = NULL;
 1824     PyObject *startobj = NULL, *stopobj = NULL;
 1825     int flags = 0;
 1826     DB_TXN *txn = NULL;
 1827     DBT *start_p = NULL, *stop_p = NULL;
 1828     DBT start, stop;
 1829     int err;
 1830     DB_COMPACT c_data = { 0 };
 1831     static char* kwnames[] = { "txn", "start", "stop", "flags",
 1832                                "compact_fillpercent", "compact_pages",
 1833                                "compact_timeout", NULL };
 1834 
 1835 
 1836     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOOiiiI:compact", kwnames,
 1837                                      &txnobj, &startobj, &stopobj, &flags,
 1838                                      &c_data.compact_fillpercent,
 1839                                      &c_data.compact_pages,
 1840                                      &c_data.compact_timeout))
 1841         return NULL;
 1842 
 1843     CHECK_DB_NOT_CLOSED(self);
 1844     if (!checkTxnObj(txnobj, &txn)) {
 1845         return NULL;
 1846     }
 1847 
 1848     if (startobj && make_key_dbt(self, startobj, &start, NULL)) {
 1849         start_p = &start;
 1850     }
 1851     if (stopobj && make_key_dbt(self, stopobj, &stop, NULL)) {
 1852         stop_p = &stop;
 1853     }
 1854 
 1855     MYDB_BEGIN_ALLOW_THREADS;
 1856     err = self->db->compact(self->db, txn, start_p, stop_p, &c_data,
 1857                             flags, NULL);
 1858     MYDB_END_ALLOW_THREADS;
 1859 
 1860     if (startobj)
 1861         FREE_DBT(start);
 1862     if (stopobj)
 1863         FREE_DBT(stop);
 1864 
 1865     RETURN_IF_ERR();
 1866 
 1867     return PyLong_FromUnsignedLong(c_data.compact_pages_truncated);
 1868 }
 1869 #endif
 1870 
 1871 
 1872 static PyObject*
 1873 DB_fd(DBObject* self)
 1874 {
 1875     int err, the_fd;
 1876 
 1877     CHECK_DB_NOT_CLOSED(self);
 1878 
 1879     MYDB_BEGIN_ALLOW_THREADS;
 1880     err = self->db->fd(self->db, &the_fd);
 1881     MYDB_END_ALLOW_THREADS;
 1882     RETURN_IF_ERR();
 1883     return NUMBER_FromLong(the_fd);
 1884 }
 1885 
 1886 
 1887 #if (DBVER >= 46)
 1888 static PyObject*
 1889 DB_exists(DBObject* self, PyObject* args, PyObject* kwargs)
 1890 {
 1891     int err, flags=0;
 1892     PyObject* txnobj = NULL;
 1893     PyObject* keyobj;
 1894     DBT key;
 1895     DB_TXN *txn;
 1896 
 1897     static char* kwnames[] = {"key", "txn", "flags", NULL};
 1898 
 1899     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:exists", kwnames,
 1900                 &keyobj, &txnobj, &flags))
 1901         return NULL;
 1902 
 1903     CHECK_DB_NOT_CLOSED(self);
 1904     if (!make_key_dbt(self, keyobj, &key, NULL))
 1905         return NULL;
 1906     if (!checkTxnObj(txnobj, &txn)) {
 1907         FREE_DBT(key);
 1908         return NULL;
 1909     }
 1910 
 1911     MYDB_BEGIN_ALLOW_THREADS;
 1912     err = self->db->exists(self->db, txn, &key, flags);
 1913     MYDB_END_ALLOW_THREADS;
 1914 
 1915     FREE_DBT(key);
 1916 
 1917     if (!err) {
 1918         Py_INCREF(Py_True);
 1919         return Py_True;
 1920     }
 1921     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)) {
 1922         Py_INCREF(Py_False);
 1923         return Py_False;
 1924     }
 1925 
 1926     /*
 1927     ** If we reach there, there was an error. The
 1928     ** "return" should be unreachable.
 1929     */
 1930     RETURN_IF_ERR();
 1931     assert(0);  /* This coude SHOULD be unreachable */
 1932     return NULL;
 1933 }
 1934 #endif
 1935 
 1936 static PyObject*
 1937 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
 1938 {
 1939     int err, flags=0;
 1940     PyObject* txnobj = NULL;
 1941     PyObject* keyobj;
 1942     PyObject* dfltobj = NULL;
 1943     PyObject* retval = NULL;
 1944     int dlen = -1;
 1945     int doff = -1;
 1946     DBT key, data;
 1947     DB_TXN *txn = NULL;
 1948     static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
 1949                                     "doff", NULL};
 1950 
 1951     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
 1952                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen,
 1953                                      &doff))
 1954         return NULL;
 1955 
 1956     CHECK_DB_NOT_CLOSED(self);
 1957     if (!make_key_dbt(self, keyobj, &key, &flags))
 1958         return NULL;
 1959     if (!checkTxnObj(txnobj, &txn)) {
 1960         FREE_DBT(key);
 1961         return NULL;
 1962     }
 1963 
 1964     CLEAR_DBT(data);
 1965     if (CHECK_DBFLAG(self, DB_THREAD)) {
 1966         /* Tell Berkeley DB to malloc the return value (thread safe) */
 1967         data.flags = DB_DBT_MALLOC;
 1968     }
 1969     if (!add_partial_dbt(&data, dlen, doff)) {
 1970         FREE_DBT(key);
 1971         return NULL;
 1972     }
 1973 
 1974     MYDB_BEGIN_ALLOW_THREADS;
 1975     err = self->db->get(self->db, txn, &key, &data, flags);
 1976     MYDB_END_ALLOW_THREADS;
 1977 
 1978     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
 1979         err = 0;
 1980         Py_INCREF(dfltobj);
 1981         retval = dfltobj;
 1982     }
 1983     else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 1984              && self->moduleFlags.getReturnsNone) {
 1985         err = 0;
 1986         Py_INCREF(Py_None);
 1987         retval = Py_None;
 1988     }
 1989     else if (!err) {
 1990         if (flags & DB_SET_RECNO) /* return both key and data */
 1991             retval = BuildValue_SS(key.data, key.size, data.data, data.size);
 1992         else /* return just the data */
 1993             retval = Build_PyString(data.data, data.size);
 1994         FREE_DBT(data);
 1995     }
 1996     FREE_DBT(key);
 1997 
 1998     RETURN_IF_ERR();
 1999     return retval;
 2000 }
 2001 
 2002 static PyObject*
 2003 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
 2004 {
 2005     int err, flags=0;
 2006     PyObject* txnobj = NULL;
 2007     PyObject* keyobj;
 2008     PyObject* dfltobj = NULL;
 2009     PyObject* retval = NULL;
 2010     int dlen = -1;
 2011     int doff = -1;
 2012     DBT key, pkey, data;
 2013     DB_TXN *txn = NULL;
 2014     static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
 2015                                     "doff", NULL};
 2016 
 2017     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
 2018                                      &keyobj, &dfltobj, &txnobj, &flags, &dlen,
 2019                                      &doff))
 2020         return NULL;
 2021 
 2022     CHECK_DB_NOT_CLOSED(self);
 2023     if (!make_key_dbt(self, keyobj, &key, &flags))
 2024         return NULL;
 2025     if (!checkTxnObj(txnobj, &txn)) {
 2026         FREE_DBT(key);
 2027         return NULL;
 2028     }
 2029 
 2030     CLEAR_DBT(data);
 2031     if (CHECK_DBFLAG(self, DB_THREAD)) {
 2032         /* Tell Berkeley DB to malloc the return value (thread safe) */
 2033         data.flags = DB_DBT_MALLOC;
 2034     }
 2035     if (!add_partial_dbt(&data, dlen, doff)) {
 2036         FREE_DBT(key);
 2037         return NULL;
 2038     }
 2039 
 2040     CLEAR_DBT(pkey);
 2041     pkey.flags = DB_DBT_MALLOC;
 2042 
 2043     MYDB_BEGIN_ALLOW_THREADS;
 2044     err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
 2045     MYDB_END_ALLOW_THREADS;
 2046 
 2047     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
 2048         err = 0;
 2049         Py_INCREF(dfltobj);
 2050         retval = dfltobj;
 2051     }
 2052     else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 2053              && self->moduleFlags.getReturnsNone) {
 2054         err = 0;
 2055         Py_INCREF(Py_None);
 2056         retval = Py_None;
 2057     }
 2058     else if (!err) {
 2059         PyObject *pkeyObj;
 2060         PyObject *dataObj;
 2061         dataObj = Build_PyString(data.data, data.size);
 2062 
 2063         if (self->primaryDBType == DB_RECNO ||
 2064             self->primaryDBType == DB_QUEUE)
 2065             pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
 2066         else
 2067             pkeyObj = Build_PyString(pkey.data, pkey.size);
 2068 
 2069         if (flags & DB_SET_RECNO) /* return key , pkey and data */
 2070         {
 2071             PyObject *keyObj;
 2072             int type = _DB_get_type(self);
 2073             if (type == DB_RECNO || type == DB_QUEUE)
 2074                 keyObj = NUMBER_FromLong(*(int *)key.data);
 2075             else
 2076                 keyObj = Build_PyString(key.data, key.size);
 2077 #if (PY_VERSION_HEX >= 0x02040000)
 2078             retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
 2079 #else
 2080             retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
 2081 #endif
 2082             Py_DECREF(keyObj);
 2083         }
 2084         else /* return just the pkey and data */
 2085         {
 2086 #if (PY_VERSION_HEX >= 0x02040000)
 2087             retval = PyTuple_Pack(2, pkeyObj, dataObj);
 2088 #else
 2089             retval = Py_BuildValue("OO", pkeyObj, dataObj);
 2090 #endif
 2091         }
 2092         Py_DECREF(dataObj);
 2093         Py_DECREF(pkeyObj);
 2094         FREE_DBT(pkey);
 2095         FREE_DBT(data);
 2096     }
 2097     FREE_DBT(key);
 2098 
 2099     RETURN_IF_ERR();
 2100     return retval;
 2101 }
 2102 
 2103 
 2104 /* Return size of entry */
 2105 static PyObject*
 2106 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
 2107 {
 2108     int err, flags=0;
 2109     PyObject* txnobj = NULL;
 2110     PyObject* keyobj;
 2111     PyObject* retval = NULL;
 2112     DBT key, data;
 2113     DB_TXN *txn = NULL;
 2114     static char* kwnames[] = { "key", "txn", NULL };
 2115 
 2116     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
 2117                                      &keyobj, &txnobj))
 2118         return NULL;
 2119     CHECK_DB_NOT_CLOSED(self);
 2120     if (!make_key_dbt(self, keyobj, &key, &flags))
 2121         return NULL;
 2122     if (!checkTxnObj(txnobj, &txn)) {
 2123         FREE_DBT(key);
 2124         return NULL;
 2125     }
 2126     CLEAR_DBT(data);
 2127 
 2128     /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
 2129        thus getting the record size. */
 2130     data.flags = DB_DBT_USERMEM;
 2131     data.ulen = 0;
 2132     MYDB_BEGIN_ALLOW_THREADS;
 2133     err = self->db->get(self->db, txn, &key, &data, flags);
 2134     MYDB_END_ALLOW_THREADS;
 2135     if (err == DB_BUFFER_SMALL) {
 2136         retval = NUMBER_FromLong((long)data.size);
 2137         err = 0;
 2138     }
 2139 
 2140     FREE_DBT(key);
 2141     FREE_DBT(data);
 2142     RETURN_IF_ERR();
 2143     return retval;
 2144 }
 2145 
 2146 
 2147 static PyObject*
 2148 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
 2149 {
 2150     int err, flags=0;
 2151     PyObject* txnobj = NULL;
 2152     PyObject* keyobj;
 2153     PyObject* dataobj;
 2154     PyObject* retval = NULL;
 2155     DBT key, data;
 2156     void *orig_data;
 2157     DB_TXN *txn = NULL;
 2158     static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
 2159 
 2160     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
 2161                                      &keyobj, &dataobj, &txnobj, &flags))
 2162         return NULL;
 2163 
 2164     CHECK_DB_NOT_CLOSED(self);
 2165     if (!make_key_dbt(self, keyobj, &key, NULL))
 2166         return NULL;
 2167     if ( !make_dbt(dataobj, &data) ||
 2168          !checkTxnObj(txnobj, &txn) )
 2169     {
 2170         FREE_DBT(key);
 2171         return NULL;
 2172     }
 2173 
 2174     flags |= DB_GET_BOTH;
 2175     orig_data = data.data;
 2176 
 2177     if (CHECK_DBFLAG(self, DB_THREAD)) {
 2178         /* Tell Berkeley DB to malloc the return value (thread safe) */
 2179         /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
 2180         data.flags = DB_DBT_MALLOC;
 2181     }
 2182 
 2183     MYDB_BEGIN_ALLOW_THREADS;
 2184     err = self->db->get(self->db, txn, &key, &data, flags);
 2185     MYDB_END_ALLOW_THREADS;
 2186 
 2187     if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
 2188             && self->moduleFlags.getReturnsNone) {
 2189         err = 0;
 2190         Py_INCREF(Py_None);
 2191         retval = Py_None;
 2192     }
 2193     else if (!err) {
 2194         /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
 2195         retval = Build_PyString(data.data, data.size);
 2196 
 2197         /* Even though the flags require DB_DBT_MALLOC, data is not always
 2198            allocated.  4.4: allocated, 4.5: *not* allocated. :-( */
 2199         if (data.data != orig_data)
 2200             FREE_DBT(data);
 2201     }
 2202 
 2203     FREE_DBT(key);
 2204     RETURN_IF_ERR();
 2205     return retval;
 2206 }
 2207 
 2208 
 2209 static PyObject*
 2210 DB_get_byteswapped(DBObject* self)
 2211 {
 2212     int err = 0;
 2213     int retval = -1;
 2214 
 2215     CHECK_DB_NOT_CLOSED(self);
 2216 
 2217     MYDB_BEGIN_ALLOW_THREADS;
 2218     err = self->db->get_byteswapped(self->db, &retval);
 2219     MYDB_END_ALLOW_THREADS;
 2220     RETURN_IF_ERR();
 2221     return NUMBER_FromLong(retval);
 2222 }
 2223 
 2224 
 2225 static PyObject*
 2226 DB_get_type(DBObject* self)
 2227 {
 2228     int type;
 2229 
 2230     CHECK_DB_NOT_CLOSED(self);
 2231 
 2232     type = _DB_get_type(self);
 2233     if (type == -1)
 2234         return NULL;
 2235     return NUMBER_FromLong(type);
 2236 }
 2237 
 2238 
 2239 static PyObject*
 2240 DB_join(DBObject* self, PyObject* args)
 2241 {
 2242     int err, flags=0;
 2243     int length, x;
 2244     PyObject* cursorsObj;
 2245     DBC** cursors;
 2246     DBC*  dbc;
 2247 
 2248     if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
 2249         return NULL;
 2250 
 2251     CHECK_DB_NOT_CLOSED(self);
 2252 
 2253     if (!PySequence_Check(cursorsObj)) {
 2254         PyErr_SetString(PyExc_TypeError,
 2255                         "Sequence of DBCursor objects expected");
 2256         return NULL;
 2257     }
 2258 
 2259     length = PyObject_Length(cursorsObj);
 2260     cursors = malloc((length+1) * sizeof(DBC*));
 2261     if (!cursors) {
 2262         PyErr_NoMemory();
 2263         return NULL;
 2264     }
 2265 
 2266     cursors[length] = NULL;
 2267     for (x=0; x<length; x++) {
 2268         PyObject* item = PySequence_GetItem(cursorsObj, x);
 2269         if (item == NULL) {
 2270             free(cursors);
 2271             return NULL;
 2272         }
 2273         if (!DBCursorObject_Check(item)) {
 2274             PyErr_SetString(PyExc_TypeError,
 2275                             "Sequence of DBCursor objects expected");
 2276             free(cursors);
 2277             return NULL;
 2278         }
 2279         cursors[x] = ((DBCursorObject*)item)->dbc;
 2280         Py_DECREF(item);
 2281     }
 2282 
 2283     MYDB_BEGIN_ALLOW_THREADS;
 2284     err = self->db->join(self->db, cursors, &dbc, flags);
 2285     MYDB_END_ALLOW_THREADS;
 2286     free(cursors);
 2287     RETURN_IF_ERR();
 2288 
 2289     /* FIXME: this is a buggy interface.  The returned cursor
 2290        contains internal references to the passed in cursors
 2291        but does not hold python references to them or prevent
 2292        them from being closed prematurely.  This can cause
 2293        python to crash when things are done in the wrong order. */
 2294     return (PyObject*) newDBCursorObject(dbc, NULL, self);
 2295 }
 2296 
 2297 
 2298 static PyObject*
 2299 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
 2300 {
 2301     int err, flags=0;
 2302     PyObject* txnobj = NULL;
 2303     PyObject* keyobj;
 2304     DBT key;
 2305     DB_TXN *txn = NULL;
 2306     DB_KEY_RANGE range;
 2307     static char* kwnames[] = { "key", "txn", "flags", NULL };
 2308 
 2309     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
 2310                                      &keyobj, &txnobj, &flags))
 2311         return NULL;
 2312     CHECK_DB_NOT_CLOSED(self);
 2313     if (!make_dbt(keyobj, &key))
 2314         /* BTree only, don't need to allow for an int key */
 2315         return NULL;
 2316     if (!checkTxnObj(txnobj, &txn))
 2317         return NULL;
 2318 
 2319     MYDB_BEGIN_ALLOW_THREADS;
 2320     err = self->db->key_range(self->db, txn, &key, &range, flags);
 2321     MYDB_END_ALLOW_THREADS;
 2322 
 2323     RETURN_IF_ERR();
 2324     return Py_BuildValue("ddd", range.less, range.equal, range.greater);
 2325 }
 2326 
 2327 
 2328 static PyObject*
 2329 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
 2330 {
 2331     int err, type = DB_UNKNOWN, flags=0, mode=0660;
 2332     char* filename = NULL;
 2333     char* dbname = NULL;
 2334     PyObject *txnobj = NULL;
 2335     DB_TXN *txn = NULL;
 2336     /* with dbname */
 2337     static char* kwnames[] = {
 2338         "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
 2339     /* without dbname */
 2340     static char* kwnames_basic[] = {
 2341         "filename", "dbtype", "flags", "mode", "txn", NULL};
 2342 
 2343     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
 2344                                      &filename, &dbname, &type, &flags, &mode,
 2345                                      &txnobj))
 2346     {
 2347         PyErr_Clear();
 2348         type = DB_UNKNOWN; flags = 0; mode = 0660;
 2349         filename = NULL; dbname = NULL;
 2350         if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
 2351                                          kwnames_basic,
 2352                                          &filename, &type, &flags, &mode,
 2353                                          &txnobj))
 2354             return NULL;
 2355     }
 2356 
 2357     if (!checkTxnObj(txnobj, &txn)) return NULL;
 2358 
 2359     if (NULL == self->db) {
 2360         PyObject *t = Py_BuildValue("(is)", 0,
 2361                                 "Cannot call open() twice for DB object");
 2362         if (t) {
 2363             PyErr_SetObject(DBError, t);
 2364             Py_DECREF(t);
 2365         }
 2366         return NULL;
 2367     }
 2368 
 2369     if (txn) {  /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
 2370         INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
 2371         self->txn=(DBTxnObject *)txnobj;
 2372     } else {
 2373         self->txn=NULL;
 2374     }
 2375 
 2376     MYDB_BEGIN_ALLOW_THREADS;
 2377     err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
 2378     MYDB_END_ALLOW_THREADS;
 2379 
 2380     if (makeDBError(err)) {
 2381         PyObject *dummy;
 2382 
 2383         dummy=DB_close_internal(self, 0, 0);
 2384         Py_XDECREF(dummy);
 2385         return NULL;
 2386     }
 2387 
 2388 #if (DBVER >= 42)
 2389     self->db->get_flags(self->db, &self->setflags);
 2390 #endif
 2391 
 2392     self->flags = flags;
 2393 
 2394     RETURN_NONE();
 2395 }
 2396 
 2397 
 2398 static PyObject*
 2399 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
 2400 {
 2401     int flags=0;
 2402     PyObject* txnobj = NULL;
 2403     int dlen = -1;
 2404     int doff = -1;
 2405     PyObject* keyobj, *dataobj, *retval;
 2406     DBT key, data;
 2407     DB_TXN *txn = NULL;
 2408     static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
 2409                                      "doff", NULL };
 2410 
 2411     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
 2412                          &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
 2413         return NULL;
 2414 
 2415     CHECK_DB_NOT_CLOSED(self);
 2416     if (!make_key_dbt(self, keyobj, &key, NULL))
 2417         return NULL;
 2418     if ( !make_dbt(dataobj, &data) ||
 2419          !add_partial_dbt(&data, dlen, doff) ||
 2420          !checkTxnObj(txnobj, &txn) )
 2421     {
 2422         FREE_DBT(key);
 2423         return NULL;
 2424     }
 2425 
 2426     if (-1 == _DB_put(self, txn, &key, &data, flags)) {
 2427         FREE_DBT(key);
 2428         return NULL;
 2429     }
 2430 
 2431     if (flags & DB_APPEND)
 2432         retval = NUMBER_FromLong(*((db_recno_t*)key.data));
 2433     else {
 2434         retval = Py_None;
 2435         Py_INCREF(retval);
 2436     }
 2437     FREE_DBT(key);
 2438     return retval;
 2439 }
 2440 
 2441 
 2442 
 2443 static PyObject*
 2444 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
 2445 {
 2446     char* filename;
 2447     char* database = NULL;
 2448     int err, flags=0;
 2449     static char* kwnames[] = { "filename", "dbname", "flags", NULL};
 2450 
 2451     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
 2452                                      &filename, &database, &flags))
 2453         return NULL;
 2454     CHECK_DB_NOT_CLOSED(self);
 2455 
 2456     EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
 2457 
 2458     MYDB_BEGIN_ALLOW_THREADS;
 2459     err = self->db->remove(self->db, filename, database, flags);
 2460     MYDB_END_ALLOW_THREADS;
 2461 
 2462     self->db = NULL;
 2463     RETURN_IF_ERR();
 2464     RETURN_NONE();
 2465 }
 2466 
 2467 
 2468 
 2469 static PyObject*
 2470 DB_rename(DBObject* self, PyObject* args)
 2471 {
 2472     char* filename;
 2473     char* database;
 2474     char* newname;
 2475     int err, flags=0;
 2476 
 2477     if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
 2478                           &flags))
 2479         return NULL;
 2480     CHECK_DB_NOT_CLOSED(self);
 2481 
 2482     MYDB_BEGIN_ALLOW_THREADS;
 2483     err = self->db->rename(self->db, filename, database, newname, flags);
 2484     MYDB_END_ALLOW_THREADS;
 2485     RETURN_IF_ERR();
 2486     RETURN_NONE();
 2487 }
 2488 
 2489 
 2490 static PyObject*
 2491 DB_get_private(DBObject* self)
 2492 {
 2493     /* We can give out the private field even if db is closed */
 2494     Py_INCREF(self->private_obj);
 2495     return self->private_obj;
 2496 }
 2497 
 2498 static PyObject*
 2499 DB_set_private(DBObject* self, PyObject* private_obj)
 2500 {
 2501     /* We can set the private field even if db is closed */
 2502     Py_DECREF(self->private_obj);
 2503     Py_INCREF(private_obj);
 2504     self->private_obj = private_obj;
 2505     RETURN_NONE();
 2506 }
 2507 
 2508 #if (DBVER >= 46)
 2509 static PyObject*
 2510 DB_set_priority(DBObject* self, PyObject* args)
 2511 {
 2512     int err, priority;
 2513 
 2514     if (!PyArg_ParseTuple(args,"i:set_priority", &priority))
 2515         return NULL;
 2516     CHECK_DB_NOT_CLOSED(self);
 2517 
 2518     MYDB_BEGIN_ALLOW_THREADS;
 2519     err = self->db->set_priority(self->db, priority);
 2520     MYDB_END_ALLOW_THREADS;
 2521     RETURN_IF_ERR();
 2522     RETURN_NONE();
 2523 }
 2524 
 2525 static PyObject*
 2526 DB_get_priority(DBObject* self)
 2527 {
 2528     int err = 0;
 2529     DB_CACHE_PRIORITY priority;
 2530 
 2531     CHECK_DB_NOT_CLOSED(self);
 2532 
 2533     MYDB_BEGIN_ALLOW_THREADS;
 2534     err = self->db->get_priority(self->db, &priority);
 2535     MYDB_END_ALLOW_THREADS;
 2536     RETURN_IF_ERR();
 2537     return NUMBER_FromLong(priority);
 2538 }
 2539 #endif
 2540 
 2541 static PyObject*
 2542 DB_set_q_extentsize(DBObject* self, PyObject* args)
 2543 {
 2544     int err;
 2545     u_int32_t extentsize;
 2546 
 2547     if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
 2548         return NULL;
 2549     CHECK_DB_NOT_CLOSED(self);
 2550 
 2551     MYDB_BEGIN_ALLOW_THREADS;
 2552     err = self->db->set_q_extentsize(self->db, extentsize);
 2553     MYDB_END_ALLOW_THREADS;
 2554     RETURN_IF_ERR();
 2555     RETURN_NONE();
 2556 }
 2557 
 2558 #if (DBVER >= 42)
 2559 static PyObject*
 2560 DB_get_q_extentsize(DBObject* self)
 2561 {
 2562     int err = 0;
 2563     u_int32_t extentsize;
 2564 
 2565     CHECK_DB_NOT_CLOSED(self);
 2566 
 2567     MYDB_BEGIN_ALLOW_THREADS;
 2568     err = self->db->get_q_extentsize(self->db, &extentsize);
 2569     MYDB_END_ALLOW_THREADS;
 2570     RETURN_IF_ERR();
 2571     return NUMBER_FromLong(extentsize);
 2572 }
 2573 #endif
 2574 
 2575 static PyObject*
 2576 DB_set_bt_minkey(DBObject* self, PyObject* args)
 2577 {
 2578     int err, minkey;
 2579 
 2580     if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey))
 2581         return NULL;
 2582     CHECK_DB_NOT_CLOSED(self);
 2583 
 2584     MYDB_BEGIN_ALLOW_THREADS;
 2585     err = self->db->set_bt_minkey(self->db, minkey);
 2586     MYDB_END_ALLOW_THREADS;
 2587     RETURN_IF_ERR();
 2588     RETURN_NONE();
 2589 }
 2590 
 2591 #if (DBVER >= 42)
 2592 static PyObject*
 2593 DB_get_bt_minkey(DBObject* self)
 2594 {
 2595     int err;
 2596     u_int32_t bt_minkey;
 2597 
 2598     CHECK_DB_NOT_CLOSED(self);
 2599 
 2600     MYDB_BEGIN_ALLOW_THREADS;
 2601     err = self->db->get_bt_minkey(self->db, &bt_minkey);
 2602     MYDB_END_ALLOW_THREADS;
 2603     RETURN_IF_ERR();
 2604     return NUMBER_FromLong(bt_minkey);
 2605 }
 2606 #endif
 2607 
 2608 static int
 2609 _default_cmp(const DBT *leftKey,
 2610              const DBT *rightKey)
 2611 {
 2612   int res;
 2613   int lsize = leftKey->size, rsize = rightKey->size;
 2614 
 2615   res = memcmp(leftKey->data, rightKey->data,
 2616                lsize < rsize ? lsize : rsize);
 2617 
 2618   if (res == 0) {
 2619       if (lsize < rsize) {
 2620           res = -1;
 2621       }
 2622       else if (lsize > rsize) {
 2623           res = 1;
 2624       }
 2625   }
 2626   return res;
 2627 }
 2628 
 2629 static int
 2630 _db_compareCallback(DB* db,
 2631                     const DBT *leftKey,
 2632                     const DBT *rightKey)
 2633 {
 2634     int res = 0;
 2635     PyObject *args;
 2636     PyObject *result = NULL;
 2637     DBObject *self = (DBObject *)db->app_private;
 2638 
 2639     if (self == NULL || self->btCompareCallback == NULL) {
 2640         MYDB_BEGIN_BLOCK_THREADS;
 2641         PyErr_SetString(PyExc_TypeError,
 2642                         (self == 0
 2643                          ? "DB_bt_compare db is NULL."
 2644                          : "DB_bt_compare callback is NULL."));
 2645         /* we're in a callback within the DB code, we can't raise */
 2646         PyErr_Print();
 2647         res = _default_cmp(leftKey, rightKey);
 2648         MYDB_END_BLOCK_THREADS;
 2649     } else {
 2650         MYDB_BEGIN_BLOCK_THREADS;
 2651 
 2652         args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
 2653         if (args != NULL) {
 2654                 result = PyEval_CallObject(self->btCompareCallback, args);
 2655         }
 2656         if (args == NULL || result == NULL) {
 2657             /* we're in a callback within the DB code, we can't raise */
 2658             PyErr_Print();
 2659             res = _default_cmp(leftKey, rightKey);
 2660         } else if (NUMBER_Check(result)) {
 2661             res = NUMBER_AsLong(result);
 2662         } else {
 2663             PyErr_SetString(PyExc_TypeError,
 2664                             "DB_bt_compare callback MUST return an int.");
 2665             /* we're in a callback within the DB code, we can't raise */
 2666             PyErr_Print();
 2667             res = _default_cmp(leftKey, rightKey);
 2668         }
 2669 
 2670         Py_XDECREF(args);
 2671         Py_XDECREF(result);
 2672 
 2673         MYDB_END_BLOCK_THREADS;
 2674     }
 2675     return res;
 2676 }
 2677 
 2678 static PyObject*
 2679 DB_set_bt_compare(DBObject* self, PyObject* comparator)
 2680 {
 2681     int err;
 2682     PyObject *tuple, *result;
 2683 
 2684     CHECK_DB_NOT_CLOSED(self);
 2685 
 2686     if (!PyCallable_Check(comparator)) {
 2687         makeTypeError("Callable", comparator);
 2688         return NULL;
 2689     }
 2690 
 2691     /*
 2692      * Perform a test call of the comparator function with two empty
 2693      * string objects here.  verify that it returns an int (0).
 2694      * err if not.
 2695      */
 2696     tuple = Py_BuildValue("(ss)", "", "");
 2697     result = PyEval_CallObject(comparator, tuple);
 2698     Py_DECREF(tuple);
 2699     if (result == NULL)
 2700         return NULL;
 2701     if (!NUMBER_Check(result)) {
 2702         Py_DECREF(result);
 2703         PyErr_SetString(PyExc_TypeError,
 2704                         "callback MUST return an int");
 2705         return NULL;
 2706     } else if (NUMBER_AsLong(result) != 0) {
 2707         Py_DECREF(result);
 2708         PyErr_SetString(PyExc_TypeError,
 2709                         "callback failed to return 0 on two empty strings");
 2710         return NULL;
 2711     }
 2712     Py_DECREF(result);
 2713 
 2714     /* We don't accept multiple set_bt_compare operations, in order to
 2715      * simplify the code. This would have no real use, as one cannot
 2716      * change the function once the db is opened anyway */
 2717     if (self->btCompareCallback != NULL) {
 2718         PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
 2719         return NULL;
 2720     }
 2721 
 2722     Py_INCREF(comparator);
 2723     self->btCompareCallback = comparator;
 2724 
 2725     /* This is to workaround a problem with un-initialized threads (see
 2726        comment in DB_associate) */
 2727 #ifdef WITH_THREAD
 2728     PyEval_InitThreads();
 2729 #endif
 2730 
 2731     err = self->db->set_bt_compare(self->db, _db_compareCallback);
 2732 
 2733     if (err) {
 2734         /* restore the old state in case of error */
 2735         Py_DECREF(comparator);
 2736         self->btCompareCallback = NULL;
 2737     }
 2738 
 2739     RETURN_IF_ERR();
 2740     RETURN_NONE();
 2741 }
 2742 
 2743 
 2744 static PyObject*
 2745 DB_set_cachesize(DBObject* self, PyObject* args)
 2746 {
 2747     int err;
 2748     int gbytes = 0, bytes = 0, ncache = 0;
 2749 
 2750     if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
 2751                           &gbytes,&bytes,&ncache))
 2752         return NULL;
 2753     CHECK_DB_NOT_CLOSED(self);
 2754 
 2755     MYDB_BEGIN_ALLOW_THREADS;
 2756     err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
 2757     MYDB_END_ALLOW_THREADS;
 2758     RETURN_IF_ERR();
 2759     RETURN_NONE();
 2760 }
 2761 
 2762 #if (DBVER >= 42)
 2763 static PyObject*
 2764 DB_get_cachesize(DBObject* self)
 2765 {
 2766     int err;
 2767     u_int32_t gbytes, bytes;
 2768     int ncache;
 2769 
 2770     CHECK_DB_NOT_CLOSED(self);
 2771 
 2772     MYDB_BEGIN_ALLOW_THREADS;
 2773     err = self->db->get_cachesize(self->db, &gbytes, &bytes, &ncache);
 2774     MYDB_END_ALLOW_THREADS;
 2775 
 2776     RETURN_IF_ERR();
 2777 
 2778     return Py_BuildValue("(iii)", gbytes, bytes, ncache);
 2779 }
 2780 #endif
 2781 
 2782 static PyObject*
 2783 DB_set_flags(DBObject* self, PyObject* args)
 2784 {
 2785     int err, flags;
 2786 
 2787     if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
 2788         return NULL;
 2789     CHECK_DB_NOT_CLOSED(self);
 2790 
 2791     MYDB_BEGIN_ALLOW_THREADS;
 2792     err = self->db->set_flags(self->db, flags);
 2793     MYDB_END_ALLOW_THREADS;
 2794     RETURN_IF_ERR();
 2795 
 2796     self->setflags |= flags;
 2797     RETURN_NONE();
 2798 }
 2799 
 2800 #if (DBVER >= 42)
 2801 static PyObject*
 2802 DB_get_flags(DBObject* self)
 2803 {
 2804     int err;
 2805     u_int32_t flags;
 2806 
 2807     CHECK_DB_NOT_CLOSED(self);
 2808 
 2809     MYDB_BEGIN_ALLOW_THREADS;
 2810     err = self->db->get_flags(self->db, &flags);
 2811     MYDB_END_ALLOW_THREADS;
 2812     RETURN_IF_ERR();
 2813     return NUMBER_FromLong(flags);
 2814 }
 2815 #endif
 2816 
 2817 static PyObject*
 2818 DB_set_h_ffactor(DBObject* self, PyObject* args)
 2819 {
 2820     int err, ffactor;
 2821 
 2822     if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
 2823         return NULL;
 2824     CHECK_DB_NOT_CLOSED(self);
 2825 
 2826     MYDB_BEGIN_ALLOW_THREADS;
 2827     err = self->db->set_h_ffactor(self->db, ffactor);
 2828     MYDB_END_ALLOW_THREADS;
 2829     RETURN_IF_ERR();
 2830     RETURN_NONE();
 2831 }
 2832 
 2833 #if (DBVER >= 42)
 2834 static PyObject*
 2835 DB_get_h_ffactor(DBObject* self)
 2836 {
 2837     int err;
 2838     u_int32_t ffactor;
 2839 
 2840     CHECK_DB_NOT_CLOSED(self);
 2841 
 2842     MYDB_BEGIN_ALLOW_THREADS;
 2843     err = self->db->get_h_ffactor(self->db, &ffactor);
 2844     MYDB_END_ALLOW_THREADS;
 2845     RETURN_IF_ERR();
 2846     return NUMBER_FromLong(ffactor);
 2847 }
 2848 #endif
 2849 
 2850 static PyObject*
 2851 DB_set_h_nelem(DBObject* self, PyObject* args)
 2852 {
 2853     int err, nelem;
 2854 
 2855     if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
 2856         return NULL;
 2857     CHECK_DB_NOT_CLOSED(self);
 2858 
 2859     MYDB_BEGIN_ALLOW_THREADS;
 2860     err = self->db->set_h_nelem(self->db, nelem);
 2861     MYDB_END_ALLOW_THREADS;
 2862     RETURN_IF_ERR();
 2863     RETURN_NONE();
 2864 }
 2865 
 2866 #if (DBVER >= 42)
 2867 static PyObject*
 2868 DB_get_h_nelem(DBObject* self)
 2869 {
 2870     int err;
 2871     u_int32_t nelem;
 2872 
 2873     CHECK_DB_NOT_CLOSED(self);
 2874 
 2875     MYDB_BEGIN_ALLOW_THREADS;
 2876     err = self->db->get_h_nelem(self->db, &nelem);
 2877     MYDB_END_ALLOW_THREADS;
 2878     RETURN_IF_ERR();
 2879     return NUMBER_FromLong(nelem);
 2880 }
 2881 #endif
 2882 
 2883 static PyObject*
 2884 DB_set_lorder(DBObject* self, PyObject* args)
 2885 {
 2886     int err, lorder;
 2887 
 2888     if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
 2889         return NULL;
 2890     CHECK_DB_NOT_CLOSED(self);
 2891 
 2892     MYDB_BEGIN_ALLOW_THREADS;
 2893     err = self->db->set_lorder(self->db, lorder);
 2894     MYDB_END_ALLOW_THREADS;
 2895     RETURN_IF_ERR();
 2896     RETURN_NONE();
 2897 }
 2898 
 2899 #if (DBVER >= 42)
 2900 static PyObject*
 2901 DB_get_lorder(DBObject* self)
 2902 {
 2903     int err;
 2904     int lorder;
 2905 
 2906     CHECK_DB_NOT_CLOSED(self);
 2907 
 2908     MYDB_BEGIN_ALLOW_THREADS;
 2909     err = self->db->get_lorder(self->db, &lorder);
 2910     MYDB_END_ALLOW_THREADS;
 2911     RETURN_IF_ERR();
 2912     return NUMBER_FromLong(lorder);
 2913 }
 2914 #endif
 2915 
 2916 static PyObject*
 2917 DB_set_pagesize(DBObject* self, PyObject* args)
 2918 {
 2919     int err, pagesize;
 2920 
 2921     if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
 2922         return NULL;
 2923     CHECK_DB_NOT_CLOSED(self);
 2924 
 2925     MYDB_BEGIN_ALLOW_THREADS;
 2926     err = self->db->set_pagesize(self->db, pagesize);
 2927     MYDB_END_ALLOW_THREADS;
 2928     RETURN_IF_ERR();
 2929     RETURN_NONE();
 2930 }
 2931 
 2932 #if (DBVER >= 42)
 2933 static PyObject*
 2934 DB_get_pagesize(DBObject* self)
 2935 {
 2936     int err;
 2937     u_int32_t pagesize;
 2938 
 2939     CHECK_DB_NOT_CLOSED(self);
 2940 
 2941     MYDB_BEGIN_ALLOW_THREADS;
 2942     err = self->db->get_pagesize(self->db, &pagesize);
 2943     MYDB_END_ALLOW_THREADS;
 2944     RETURN_IF_ERR();
 2945     return NUMBER_FromLong(pagesize);
 2946 }
 2947 #endif
 2948 
 2949 static PyObject*
 2950 DB_set_re_delim(DBObject* self, PyObject* args)
 2951 {
 2952     int err;
 2953     char delim;
 2954 
 2955     if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
 2956         PyErr_Clear();
 2957         if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
 2958             return NULL;
 2959     }
 2960 
 2961     CHECK_DB_NOT_CLOSED(self);
 2962 
 2963     MYDB_BEGIN_ALLOW_THREADS;
 2964     err = self->db->set_re_delim(self->db, delim);
 2965     MYDB_END_ALLOW_THREADS;
 2966     RETURN_IF_ERR();
 2967     RETURN_NONE();
 2968 }
 2969 
 2970 #if (DBVER >= 42)
 2971 static PyObject*
 2972 DB_get_re_delim(DBObject* self)
 2973 {
 2974     int err, re_delim;
 2975 
 2976     CHECK_DB_NOT_CLOSED(self);
 2977 
 2978     MYDB_BEGIN_ALLOW_THREADS;
 2979     err = self->db->get_re_delim(self->db, &re_delim);
 2980     MYDB_END_ALLOW_THREADS;
 2981     RETURN_IF_ERR();
 2982     return NUMBER_FromLong(re_delim);
 2983 }
 2984 #endif
 2985 
 2986 static PyObject*
 2987 DB_set_re_len(DBObject* self, PyObject* args)
 2988 {
 2989     int err, len;
 2990 
 2991     if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
 2992         return NULL;
 2993     CHECK_DB_NOT_CLOSED(self);
 2994 
 2995     MYDB_BEGIN_ALLOW_THREADS;
 2996     err = self->db->set_re_len(self->db, len);
 2997     MYDB_END_ALLOW_THREADS;
 2998     RETURN_IF_ERR();
 2999     RETURN_NONE();
 3000 }
 3001 
 3002 #if (DBVER >= 42)
 3003 static PyObject*
 3004 DB_get_re_len(DBObject* self)
 3005 {
 3006     int err;
 3007     u_int32_t re_len;
 3008 
 3009     CHECK_DB_NOT_CLOSED(self);
 3010 
 3011     MYDB_BEGIN_ALLOW_THREADS;
 3012     err = self->db->get_re_len(self->db, &re_len);
 3013     MYDB_END_ALLOW_THREADS;
 3014     RETURN_IF_ERR();
 3015     return NUMBER_FromLong(re_len);
 3016 }
 3017 #endif
 3018 
 3019 static PyObject*
 3020 DB_set_re_pad(DBObject* self, PyObject* args)
 3021 {
 3022     int err;
 3023     char pad;
 3024 
 3025     if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
 3026         PyErr_Clear();
 3027         if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
 3028             return NULL;
 3029     }
 3030     CHECK_DB_NOT_CLOSED(self);
 3031 
 3032     MYDB_BEGIN_ALLOW_THREADS;
 3033     err = self->db->set_re_pad(self->db, pad);
 3034     MYDB_END_ALLOW_THREADS;
 3035     RETURN_IF_ERR();
 3036     RETURN_NONE();
 3037 }
 3038 
 3039 #if (DBVER >= 42)
 3040 static PyObject*
 3041 DB_get_re_pad(DBObject* self)
 3042 {
 3043     int err, re_pad;
 3044 
 3045     CHECK_DB_NOT_CLOSED(self);
 3046 
 3047     MYDB_BEGIN_ALLOW_THREADS;
 3048     err = self->db->get_re_pad(self->db, &re_pad);
 3049     MYDB_END_ALLOW_THREADS;
 3050     RETURN_IF_ERR();
 3051     return NUMBER_FromLong(re_pad);
 3052 }
 3053 #endif
 3054 
 3055 static PyObject*
 3056 DB_set_re_source(DBObject* self, PyObject* args)
 3057 {
 3058     int err;
 3059     char *source;
 3060 
 3061     if (!PyArg_ParseTuple(args,"s:set_re_source", &source))
 3062         return NULL;
 3063     CHECK_DB_NOT_CLOSED(self);
 3064 
 3065     MYDB_BEGIN_ALLOW_THREADS;
 3066     err = self->db->set_re_source(self->db, source);
 3067     MYDB_END_ALLOW_THREADS;
 3068     RETURN_IF_ERR();
 3069     RETURN_NONE();
 3070 }
 3071 
 3072 #if (DBVER >= 42)
 3073 static PyObject*
 3074 DB_get_re_source(DBObject* self)
 3075 {
 3076     int err;
 3077     const char *source;
 3078 
 3079     CHECK_DB_NOT_CLOSED(self);
 3080 
 3081     MYDB_BEGIN_ALLOW_THREADS;
 3082     err = self->db->get_re_source(self->db, &source);
 3083     MYDB_END_ALLOW_THREADS;
 3084     RETURN_IF_ERR();
 3085     return PyBytes_FromString(source);
 3086 }
 3087 #endif
 3088 
 3089 static PyObject*
 3090 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
 3091 {
 3092     int err, flags = 0, type;
 3093     void* sp;
 3094     PyObject* d;
 3095 #if (DBVER >= 43)
 3096     PyObject* txnobj = NULL;
 3097     DB_TXN *txn = NULL;
 3098     static char* kwnames[] = { "flags", "txn", NULL };
 3099 #else
 3100     static char* kwnames[] = { "flags", NULL };
 3101 #endif
 3102 
 3103 #if (DBVER >= 43)
 3104     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
 3105                                      &flags, &txnobj))
 3106         return NULL;
 3107     if (!checkTxnObj(txnobj, &txn))
 3108         return NULL;
 3109 #else
 3110     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
 3111         return NULL;
 3112 #endif
 3113     CHECK_DB_NOT_CLOSED(self);
 3114 
 3115     MYDB_BEGIN_ALLOW_THREADS;
 3116 #if (DBVER >= 43)
 3117     err = self->db->stat(self->db, txn, &sp, flags);
 3118 #else
 3119     err = self->db->stat(self->db, &sp, flags);
 3120 #endif
 3121     MYDB_END_ALLOW_THREADS;
 3122     RETURN_IF_ERR();
 3123 
 3124     /* Turn the stat structure into a dictionary */
 3125     type = _DB_get_type(self);
 3126     if ((type == -1) || ((d = PyDict_New()) == NULL)) {
 3127         free(sp);
 3128         return NULL;
 3129     }
 3130 
 3131 #define MAKE_HASH_ENTRY(name)  _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
 3132 #define MAKE_BT_ENTRY(name)    _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
 3133 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
 3134 
 3135     switch (type) {
 3136     case DB_HASH:
 3137         MAKE_HASH_ENTRY(magic);
 3138         MAKE_HASH_ENTRY(version);
 3139         MAKE_HASH_ENTRY(nkeys);
 3140         MAKE_HASH_ENTRY(ndata);
 3141 #if (DBVER >= 46)
 3142         MAKE_HASH_ENTRY(pagecnt);
 3143 #endif
 3144         MAKE_HASH_ENTRY(pagesize);
 3145         MAKE_HASH_ENTRY(ffactor);
 3146         MAKE_HASH_ENTRY(buckets);
 3147         MAKE_HASH_ENTRY(free);
 3148         MAKE_HASH_ENTRY(bfree);
 3149         MAKE_HASH_ENTRY(bigpages);
 3150         MAKE_HASH_ENTRY(big_bfree);
 3151         MAKE_HASH_ENTRY(overflows);
 3152         MAKE_HASH_ENTRY(ovfl_free);
 3153         MAKE_HASH_ENTRY(dup);
 3154         MAKE_HASH_ENTRY(dup_free);
 3155         break;
 3156 
 3157     case DB_BTREE:
 3158     case DB_RECNO:
 3159         MAKE_BT_ENTRY(magic);
 3160         MAKE_BT_ENTRY(version);
 3161         MAKE_BT_ENTRY(nkeys);
 3162         MAKE_BT_ENTRY(ndata);
 3163 #if (DBVER >= 46)
 3164         MAKE_BT_ENTRY(pagecnt);
 3165 #endif
 3166         MAKE_BT_ENTRY(pagesize);
 3167         MAKE_BT_ENTRY(minkey);
 3168         MAKE_BT_ENTRY(re_len);
 3169         MAKE_BT_ENTRY(re_pad);
 3170         MAKE_BT_ENTRY(levels);
 3171         MAKE_BT_ENTRY(int_pg);
 3172         MAKE_BT_ENTRY(leaf_pg);
 3173         MAKE_BT_ENTRY(dup_pg);
 3174         MAKE_BT_ENTRY(over_pg);
 3175 #if (DBVER >= 43)
 3176         MAKE_BT_ENTRY(empty_pg);
 3177 #endif
 3178         MAKE_BT_ENTRY(free);
 3179         MAKE_BT_ENTRY(int_pgfree);
 3180         MAKE_BT_ENTRY(leaf_pgfree);
 3181         MAKE_BT_ENTRY(dup_pgfree);
 3182         MAKE_BT_ENTRY(over_pgfree);
 3183         break;
 3184 
 3185     case DB_QUEUE:
 3186         MAKE_QUEUE_ENTRY(magic);
 3187         MAKE_QUEUE_ENTRY(version);
 3188         MAKE_QUEUE_ENTRY(nkeys);
 3189         MAKE_QUEUE_ENTRY(ndata);
 3190         MAKE_QUEUE_ENTRY(pagesize);
 3191         MAKE_QUEUE_ENTRY(extentsize);
 3192         MAKE_QUEUE_ENTRY(pages);
 3193         MAKE_QUEUE_ENTRY(re_len);
 3194         MAKE_QUEUE_ENTRY(re_pad);
 3195         MAKE_QUEUE_ENTRY(pgfree);
 3196 #if (DBVER == 31)
 3197         MAKE_QUEUE_ENTRY(start);
 3198 #endif
 3199         MAKE_QUEUE_ENTRY(first_recno);
 3200         MAKE_QUEUE_ENTRY(cur_recno);
 3201         break;
 3202 
 3203     default:
 3204         PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
 3205         Py_DECREF(d);
 3206         d = NULL;
 3207     }
 3208 
 3209 #undef MAKE_HASH_ENTRY
 3210 #undef MAKE_BT_ENTRY
 3211 #undef MAKE_QUEUE_ENTRY
 3212 
 3213     free(sp);
 3214     return d;
 3215 }
 3216 
 3217 #if (DBVER >= 43)
 3218 static PyObject*
 3219 DB_stat_print(DBObject* self, PyObject* args, PyObject *kwargs)
 3220 {
 3221     int err;
 3222     int flags=0;
 3223     static char* kwnames[] = { "flags", NULL };
 3224 
 3225     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print",
 3226                 kwnames, &flags))
 3227     {
 3228         return NULL;
 3229     }
 3230     CHECK_DB_NOT_CLOSED(self);
 3231     MYDB_BEGIN_ALLOW_THREADS;
 3232     err = self->db->stat_print(self->db, flags);
 3233     MYDB_END_ALLOW_THREADS;
 3234     RETURN_IF_ERR();
 3235     RETURN_NONE();
 3236 }
 3237 #endif
 3238 
 3239 
 3240 static PyObject*
 3241 DB_sync(DBObject* self, PyObject* args)
 3242 {
 3243     int err;
 3244     int flags = 0;
 3245 
 3246     if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
 3247         return NULL;
 3248     CHECK_DB_NOT_CLOSED(self);
 3249 
 3250     MYDB_BEGIN_ALLOW_THREADS;
 3251     err = self->db->sync(self->db, flags);
 3252     MYDB_END_ALLOW_THREADS;
 3253     RETURN_IF_ERR();
 3254     RETURN_NONE();
 3255 }
 3256 
 3257 
 3258 static PyObject*
 3259 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
 3260 {
 3261     int err, flags=0;
 3262     u_int32_t count=0;
 3263     PyObject* txnobj = NULL;
 3264     DB_TXN *txn = NULL;
 3265     static char* kwnames[] = { "txn", "flags", NULL };
 3266 
 3267     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
 3268                                      &txnobj, &flags))
 3269         return NULL;
 3270     CHECK_DB_NOT_CLOSED(self);
 3271     if (!checkTxnObj(txnobj, &txn))
 3272         return NULL;
 3273 
 3274     MYDB_BEGIN_ALLOW_THREADS;
 3275     err = self->db->truncate(self->db, txn, &count, flags);
 3276     MYDB_END_ALLOW_THREADS;
 3277     RETURN_IF_ERR();
 3278     return NUMBER_FromLong(count);
 3279 }
 3280 
 3281 
 3282 static PyObject*
 3283 DB_upgrade(DBObject* self, PyObject* args)
 3284 {
 3285     int err, flags=0;
 3286     char *filename;
 3287 
 3288     if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
 3289         return NULL;
 3290     CHECK_DB_NOT_CLOSED(self);
 3291 
 3292     MYDB_BEGIN_ALLOW_THREADS;
 3293     err = self->db->upgrade(self->db, filename, flags);
 3294     MYDB_END_ALLOW_THREADS;
 3295     RETURN_IF_ERR();
 3296     RETURN_NONE();
 3297 }
 3298 
 3299 
 3300 static PyObject*
 3301 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
 3302 {
 3303     int err, flags=0;
 3304     char* fileName;
 3305     char* dbName=NULL;
 3306     char* outFileName=NULL;
 3307     FILE* outFile=NULL;
 3308     static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
 3309                                      NULL };
 3310 
 3311     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
 3312                                      &fileName, &dbName, &outFileName, &flags))
 3313         return NULL;
 3314 
 3315     CHECK_DB_NOT_CLOSED(self);
 3316     if (outFileName)
 3317         outFile = fopen(outFileName, "w");
 3318         /* XXX(nnorwitz): it should probably be an exception if outFile
 3319            can't be opened. */
 3320 
 3321     {  /* DB.verify acts as a DB handle destructor (like close) */
 3322         PyObject *error;
 3323 
 3324         error=DB_close_internal(self, 0, 1);
 3325         if (error) {
 3326           return error;
Resource leak: outFile
(emitted by cppcheck)
Resource leak: outFile
(emitted by cppcheck)
3327 } 3328 } 3329 3330 MYDB_BEGIN_ALLOW_THREADS; 3331 err = self->db->verify(self->db, fileName, dbName, outFile, flags); 3332 MYDB_END_ALLOW_THREADS; 3333 3334 self->db = NULL; /* Implicit close; related objects already released */ 3335 3336 if (outFile) 3337 fclose(outFile); 3338 3339 RETURN_IF_ERR(); 3340 RETURN_NONE(); 3341 } 3342 3343 3344 static PyObject* 3345 DB_set_get_returns_none(DBObject* self, PyObject* args) 3346 { 3347 int flags=0; 3348 int oldValue=0; 3349 3350 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags)) 3351 return NULL; 3352 CHECK_DB_NOT_CLOSED(self); 3353 3354 if (self->moduleFlags.getReturnsNone) 3355 ++oldValue; 3356 if (self->moduleFlags.cursorSetReturnsNone) 3357 ++oldValue; 3358 self->moduleFlags.getReturnsNone = (flags >= 1); 3359 self->moduleFlags.cursorSetReturnsNone = (flags >= 2); 3360 return NUMBER_FromLong(oldValue); 3361 } 3362 3363 static PyObject* 3364 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs) 3365 { 3366 int err; 3367 u_int32_t flags=0; 3368 char *passwd = NULL; 3369 static char* kwnames[] = { "passwd", "flags", NULL }; 3370 3371 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, 3372 &passwd, &flags)) { 3373 return NULL; 3374 } 3375 3376 MYDB_BEGIN_ALLOW_THREADS; 3377 err = self->db->set_encrypt(self->db, passwd, flags); 3378 MYDB_END_ALLOW_THREADS; 3379 3380 RETURN_IF_ERR(); 3381 RETURN_NONE(); 3382 } 3383 3384 #if (DBVER >= 42) 3385 static PyObject* 3386 DB_get_encrypt_flags(DBObject* self) 3387 { 3388 int err; 3389 u_int32_t flags; 3390 3391 MYDB_BEGIN_ALLOW_THREADS; 3392 err = self->db->get_encrypt_flags(self->db, &flags); 3393 MYDB_END_ALLOW_THREADS; 3394 3395 RETURN_IF_ERR(); 3396 3397 return NUMBER_FromLong(flags); 3398 } 3399 #endif 3400 3401 3402 3403 /*-------------------------------------------------------------- */ 3404 /* Mapping and Dictionary-like access routines */ 3405 3406 Py_ssize_t DB_length(PyObject* _self) 3407 { 3408 int err; 3409 Py_ssize_t size = 0; 3410 void* sp; 3411 DBObject* self = (DBObject*)_self; 3412 3413 if (self->db == NULL) { 3414 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); 3415 if (t) { 3416 PyErr_SetObject(DBError, t); 3417 Py_DECREF(t); 3418 } 3419 return -1; 3420 } 3421 3422 MYDB_BEGIN_ALLOW_THREADS; 3423 #if (DBVER >= 43) 3424 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, 0); 3425 #else 3426 err = self->db->stat(self->db, &sp, 0); 3427 #endif 3428 MYDB_END_ALLOW_THREADS; 3429 3430 /* All the stat structures have matching fields upto the ndata field, 3431 so we can use any of them for the type cast */ 3432 size = ((DB_BTREE_STAT*)sp)->bt_ndata; 3433 3434 if (err) 3435 return -1; 3436 3437 free(sp); 3438 return size; 3439 } 3440 3441 3442 PyObject* DB_subscript(DBObject* self, PyObject* keyobj) 3443 { 3444 int err; 3445 PyObject* retval; 3446 DBT key; 3447 DBT data; 3448 3449 CHECK_DB_NOT_CLOSED(self); 3450 if (!make_key_dbt(self, keyobj, &key, NULL)) 3451 return NULL; 3452 3453 CLEAR_DBT(data); 3454 if (CHECK_DBFLAG(self, DB_THREAD)) { 3455 /* Tell Berkeley DB to malloc the return value (thread safe) */ 3456 data.flags = DB_DBT_MALLOC; 3457 } 3458 MYDB_BEGIN_ALLOW_THREADS; 3459 err = self->db->get(self->db, NULL, &key, &data, 0); 3460 MYDB_END_ALLOW_THREADS; 3461 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { 3462 PyErr_SetObject(PyExc_KeyError, keyobj); 3463 retval = NULL; 3464 } 3465 else if (makeDBError(err)) { 3466 retval = NULL; 3467 } 3468 else { 3469 retval = Build_PyString(data.data, data.size); 3470 FREE_DBT(data); 3471 } 3472 3473 FREE_DBT(key); 3474 return retval; 3475 } 3476 3477 3478 static int 3479 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj) 3480 { 3481 DBT key, data; 3482 int retval; 3483 int flags = 0; 3484 3485 if (self->db == NULL) { 3486 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed"); 3487 if (t) { 3488 PyErr_SetObject(DBError, t); 3489 Py_DECREF(t); 3490 } 3491 return -1; 3492 } 3493 3494 if (!make_key_dbt(self, keyobj, &key, NULL)) 3495 return -1; 3496 3497 if (dataobj != NULL) { 3498 if (!make_dbt(dataobj, &data)) 3499 retval = -1; 3500 else { 3501 if (self->setflags & (DB_DUP|DB_DUPSORT)) 3502 /* dictionaries shouldn't have duplicate keys */ 3503 flags = DB_NOOVERWRITE; 3504 retval = _DB_put(self, NULL, &key, &data, flags); 3505 3506 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) { 3507 /* try deleting any old record that matches and then PUT it 3508 * again... */ 3509 _DB_delete(self, NULL, &key, 0); 3510 PyErr_Clear(); 3511 retval = _DB_put(self, NULL, &key, &data, flags); 3512 } 3513 } 3514 } 3515 else { 3516 /* dataobj == NULL, so delete the key */ 3517 retval = _DB_delete(self, NULL, &key, 0); 3518 } 3519 FREE_DBT(key); 3520 return retval; 3521 } 3522 3523 3524 static PyObject* 3525 _DB_has_key(DBObject* self, PyObject* keyobj, PyObject* txnobj) 3526 { 3527 int err; 3528 DBT key; 3529 DB_TXN *txn = NULL; 3530 3531 CHECK_DB_NOT_CLOSED(self); 3532 if (!make_key_dbt(self, keyobj, &key, NULL)) 3533 return NULL; 3534 if (!checkTxnObj(txnobj, &txn)) { 3535 FREE_DBT(key); 3536 return NULL; 3537 } 3538 3539 #if (DBVER < 46) 3540 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because 3541 it has a record but can't allocate a buffer for the data. This saves 3542 having to deal with data we won't be using. 3543 */ 3544 { 3545 DBT data ; 3546 CLEAR_DBT(data); 3547 data.flags = DB_DBT_USERMEM; 3548 3549 MYDB_BEGIN_ALLOW_THREADS; 3550 err = self->db->get(self->db, txn, &key, &data, 0); 3551 MYDB_END_ALLOW_THREADS; 3552 } 3553 #else 3554 MYDB_BEGIN_ALLOW_THREADS; 3555 err = self->db->exists(self->db, txn, &key, 0); 3556 MYDB_END_ALLOW_THREADS; 3557 #endif 3558 3559 FREE_DBT(key); 3560 3561 /* 3562 ** DB_BUFFER_SMALL is only used if we use "get". 3563 ** We can drop it when we only use "exists", 3564 ** when we drop suport for Berkeley DB < 4.6. 3565 */ 3566 if (err == DB_BUFFER_SMALL || err == 0) { 3567 Py_INCREF(Py_True); 3568 return Py_True; 3569 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { 3570 Py_INCREF(Py_False); 3571 return Py_False; 3572 } 3573 3574 makeDBError(err); 3575 return NULL; 3576 } 3577 3578 static PyObject* 3579 DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs) 3580 { 3581 PyObject* keyobj; 3582 PyObject* txnobj = NULL; 3583 static char* kwnames[] = {"key","txn", NULL}; 3584 3585 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames, 3586 &keyobj, &txnobj)) 3587 return NULL; 3588 3589 return _DB_has_key(self, keyobj, txnobj); 3590 } 3591 3592 3593 static int DB_contains(DBObject* self, PyObject* keyobj) 3594 { 3595 PyObject* result; 3596 int result2 = 0; 3597 3598 result = _DB_has_key(self, keyobj, NULL) ; 3599 if (result == NULL) { 3600 return -1; /* Propague exception */ 3601 } 3602 if (result != Py_False) { 3603 result2 = 1; 3604 } 3605 3606 Py_DECREF(result); 3607 return result2; 3608 } 3609 3610 3611 #define _KEYS_LIST 1 3612 #define _VALUES_LIST 2 3613 #define _ITEMS_LIST 3 3614 3615 static PyObject* 3616 _DB_make_list(DBObject* self, DB_TXN* txn, int type) 3617 { 3618 int err, dbtype; 3619 DBT key; 3620 DBT data; 3621 DBC *cursor; 3622 PyObject* list; 3623 PyObject* item = NULL; 3624 3625 CHECK_DB_NOT_CLOSED(self); 3626 CLEAR_DBT(key); 3627 CLEAR_DBT(data); 3628 3629 dbtype = _DB_get_type(self); 3630 if (dbtype == -1) 3631 return NULL; 3632 3633 list = PyList_New(0); 3634 if (list == NULL) 3635 return NULL; 3636 3637 /* get a cursor */ 3638 MYDB_BEGIN_ALLOW_THREADS; 3639 err = self->db->cursor(self->db, txn, &cursor, 0); 3640 MYDB_END_ALLOW_THREADS; 3641 if (makeDBError(err)) { 3642 Py_DECREF(list); 3643 return NULL; 3644 } 3645 3646 while (1) { /* use the cursor to traverse the DB, collecting items */ 3647 MYDB_BEGIN_ALLOW_THREADS; 3648 err = _DBC_get(cursor, &key, &data, DB_NEXT); 3649 MYDB_END_ALLOW_THREADS; 3650 3651 if (err) { 3652 /* for any error, break out of the loop */ 3653 break; 3654 } 3655 3656 switch (type) { 3657 case _KEYS_LIST: 3658 switch(dbtype) { 3659 case DB_BTREE: 3660 case DB_HASH: 3661 default: 3662 item = Build_PyString(key.data, key.size); 3663 break; 3664 case DB_RECNO: 3665 case DB_QUEUE: 3666 item = NUMBER_FromLong(*((db_recno_t*)key.data)); 3667 break; 3668 } 3669 break; 3670 3671 case _VALUES_LIST: 3672 item = Build_PyString(data.data, data.size); 3673 break; 3674 3675 case _ITEMS_LIST: 3676 switch(dbtype) { 3677 case DB_BTREE: 3678 case DB_HASH: 3679 default: 3680 item = BuildValue_SS(key.data, key.size, data.data, data.size); 3681 break; 3682 case DB_RECNO: 3683 case DB_QUEUE: 3684 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); 3685 break; 3686 } 3687 break; 3688 default: 3689 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type); 3690 item = NULL; 3691 break; 3692 } 3693 if (item == NULL) { 3694 Py_DECREF(list); 3695 list = NULL; 3696 goto done; 3697 } 3698 if (PyList_Append(list, item)) { 3699 Py_DECREF(list); 3700 Py_DECREF(item); 3701 list = NULL; 3702 goto done; 3703 } 3704 Py_DECREF(item); 3705 } 3706 3707 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */ 3708 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) { 3709 Py_DECREF(list); 3710 list = NULL; 3711 } 3712 3713 done: 3714 MYDB_BEGIN_ALLOW_THREADS; 3715 _DBC_close(cursor); 3716 MYDB_END_ALLOW_THREADS; 3717 return list; 3718 } 3719 3720 3721 static PyObject* 3722 DB_keys(DBObject* self, PyObject* args) 3723 { 3724 PyObject* txnobj = NULL; 3725 DB_TXN *txn = NULL; 3726 3727 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj)) 3728 return NULL; 3729 if (!checkTxnObj(txnobj, &txn)) 3730 return NULL; 3731 return _DB_make_list(self, txn, _KEYS_LIST); 3732 } 3733 3734 3735 static PyObject* 3736 DB_items(DBObject* self, PyObject* args) 3737 { 3738 PyObject* txnobj = NULL; 3739 DB_TXN *txn = NULL; 3740 3741 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj)) 3742 return NULL; 3743 if (!checkTxnObj(txnobj, &txn)) 3744 return NULL; 3745 return _DB_make_list(self, txn, _ITEMS_LIST); 3746 } 3747 3748 3749 static PyObject* 3750 DB_values(DBObject* self, PyObject* args) 3751 { 3752 PyObject* txnobj = NULL; 3753 DB_TXN *txn = NULL; 3754 3755 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj)) 3756 return NULL; 3757 if (!checkTxnObj(txnobj, &txn)) 3758 return NULL; 3759 return _DB_make_list(self, txn, _VALUES_LIST); 3760 } 3761 3762 /* --------------------------------------------------------------------- */ 3763 /* DBLogCursor methods */ 3764 3765 3766 static PyObject* 3767 DBLogCursor_close_internal(DBLogCursorObject* self) 3768 { 3769 int err = 0; 3770 3771 if (self->logc != NULL) { 3772 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); 3773 3774 MYDB_BEGIN_ALLOW_THREADS; 3775 err = self->logc->close(self->logc, 0); 3776 MYDB_END_ALLOW_THREADS; 3777 self->logc = NULL; 3778 } 3779 RETURN_IF_ERR(); 3780 RETURN_NONE(); 3781 } 3782 3783 static PyObject* 3784 DBLogCursor_close(DBLogCursorObject* self) 3785 { 3786 return DBLogCursor_close_internal(self); 3787 } 3788 3789 3790 static PyObject* 3791 _DBLogCursor_get(DBLogCursorObject* self, int flag, DB_LSN *lsn2) 3792 { 3793 int err; 3794 DBT data; 3795 DB_LSN lsn = {0, 0}; 3796 PyObject *dummy, *retval; 3797 3798 CLEAR_DBT(data); 3799 data.flags = DB_DBT_MALLOC; /* Berkeley DB must do the malloc */ 3800 3801 CHECK_LOGCURSOR_NOT_CLOSED(self); 3802 3803 if (lsn2) 3804 lsn = *lsn2; 3805 3806 MYDB_BEGIN_ALLOW_THREADS; 3807 err = self->logc->get(self->logc, &lsn, &data, flag); 3808 MYDB_END_ALLOW_THREADS; 3809 3810 if (err == DB_NOTFOUND) { 3811 Py_INCREF(Py_None); 3812 retval = Py_None; 3813 } 3814 else if (makeDBError(err)) { 3815 retval = NULL; 3816 } 3817 else { 3818 retval = dummy = BuildValue_S(data.data, data.size); 3819 if (dummy) { 3820 retval = Py_BuildValue("(ii)O", lsn.file, lsn.offset, dummy); 3821 Py_DECREF(dummy); 3822 } 3823 } 3824 3825 FREE_DBT(data); 3826 return retval; 3827 } 3828 3829 static PyObject* 3830 DBLogCursor_current(DBLogCursorObject* self) 3831 { 3832 return _DBLogCursor_get(self, DB_CURRENT, NULL); 3833 } 3834 3835 static PyObject* 3836 DBLogCursor_first(DBLogCursorObject* self) 3837 { 3838 return _DBLogCursor_get(self, DB_FIRST, NULL); 3839 } 3840 3841 static PyObject* 3842 DBLogCursor_last(DBLogCursorObject* self) 3843 { 3844 return _DBLogCursor_get(self, DB_LAST, NULL); 3845 } 3846 3847 static PyObject* 3848 DBLogCursor_next(DBLogCursorObject* self) 3849 { 3850 return _DBLogCursor_get(self, DB_NEXT, NULL); 3851 } 3852 3853 static PyObject* 3854 DBLogCursor_prev(DBLogCursorObject* self) 3855 { 3856 return _DBLogCursor_get(self, DB_PREV, NULL); 3857 } 3858 3859 static PyObject* 3860 DBLogCursor_set(DBLogCursorObject* self, PyObject* args) 3861 { 3862 DB_LSN lsn; 3863 3864 if (!PyArg_ParseTuple(args, "(ii):set", &lsn.file, &lsn.offset)) 3865 return NULL; 3866 3867 return _DBLogCursor_get(self, DB_SET, &lsn); 3868 } 3869 3870 3871 3872 /* --------------------------------------------------------------------- */ 3873 /* DBCursor methods */ 3874 3875 3876 static PyObject* 3877 DBC_close_internal(DBCursorObject* self) 3878 { 3879 int err = 0; 3880 3881 if (self->dbc != NULL) { 3882 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); 3883 if (self->txn) { 3884 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); 3885 self->txn=NULL; 3886 } 3887 3888 MYDB_BEGIN_ALLOW_THREADS; 3889 err = _DBC_close(self->dbc); 3890 MYDB_END_ALLOW_THREADS; 3891 self->dbc = NULL; 3892 } 3893 RETURN_IF_ERR(); 3894 RETURN_NONE(); 3895 } 3896 3897 static PyObject* 3898 DBC_close(DBCursorObject* self) 3899 { 3900 return DBC_close_internal(self); 3901 } 3902 3903 3904 static PyObject* 3905 DBC_count(DBCursorObject* self, PyObject* args) 3906 { 3907 int err = 0; 3908 db_recno_t count; 3909 int flags = 0; 3910 3911 if (!PyArg_ParseTuple(args, "|i:count", &flags)) 3912 return NULL; 3913 3914 CHECK_CURSOR_NOT_CLOSED(self); 3915 3916 MYDB_BEGIN_ALLOW_THREADS; 3917 err = _DBC_count(self->dbc, &count, flags); 3918 MYDB_END_ALLOW_THREADS; 3919 RETURN_IF_ERR(); 3920 3921 return NUMBER_FromLong(count); 3922 } 3923 3924 3925 static PyObject* 3926 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs) 3927 { 3928 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current"); 3929 } 3930 3931 3932 static PyObject* 3933 DBC_delete(DBCursorObject* self, PyObject* args) 3934 { 3935 int err, flags=0; 3936 3937 if (!PyArg_ParseTuple(args, "|i:delete", &flags)) 3938 return NULL; 3939 3940 CHECK_CURSOR_NOT_CLOSED(self); 3941 3942 MYDB_BEGIN_ALLOW_THREADS; 3943 err = _DBC_del(self->dbc, flags); 3944 MYDB_END_ALLOW_THREADS; 3945 RETURN_IF_ERR(); 3946 3947 RETURN_NONE(); 3948 } 3949 3950 3951 static PyObject* 3952 DBC_dup(DBCursorObject* self, PyObject* args) 3953 { 3954 int err, flags =0; 3955 DBC* dbc = NULL; 3956 3957 if (!PyArg_ParseTuple(args, "|i:dup", &flags)) 3958 return NULL; 3959 3960 CHECK_CURSOR_NOT_CLOSED(self); 3961 3962 MYDB_BEGIN_ALLOW_THREADS; 3963 err = _DBC_dup(self->dbc, &dbc, flags); 3964 MYDB_END_ALLOW_THREADS; 3965 RETURN_IF_ERR(); 3966 3967 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb); 3968 } 3969 3970 static PyObject* 3971 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs) 3972 { 3973 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first"); 3974 } 3975 3976 3977 static PyObject* 3978 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs) 3979 { 3980 int err, flags=0; 3981 PyObject* keyobj = NULL; 3982 PyObject* dataobj = NULL; 3983 PyObject* retval = NULL; 3984 int dlen = -1; 3985 int doff = -1; 3986 DBT key, data; 3987 static char* kwnames[] = { "key","data", "flags", "dlen", "doff", 3988 NULL }; 3989 3990 CLEAR_DBT(key); 3991 CLEAR_DBT(data); 3992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2], 3993 &flags, &dlen, &doff)) 3994 { 3995 PyErr_Clear(); 3996 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", 3997 &kwnames[1], 3998 &keyobj, &flags, &dlen, &doff)) 3999 { 4000 PyErr_Clear(); 4001 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get", 4002 kwnames, &keyobj, &dataobj, 4003 &flags, &dlen, &doff)) 4004 { 4005 return NULL; 4006 } 4007 } 4008 } 4009 4010 CHECK_CURSOR_NOT_CLOSED(self); 4011 4012 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) 4013 return NULL; 4014 if ( (dataobj && !make_dbt(dataobj, &data)) || 4015 (!add_partial_dbt(&data, dlen, doff)) ) 4016 { 4017 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4018 return NULL; 4019 } 4020 4021 MYDB_BEGIN_ALLOW_THREADS; 4022 err = _DBC_get(self->dbc, &key, &data, flags); 4023 MYDB_END_ALLOW_THREADS; 4024 4025 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) 4026 && self->mydb->moduleFlags.getReturnsNone) { 4027 Py_INCREF(Py_None); 4028 retval = Py_None; 4029 } 4030 else if (makeDBError(err)) { 4031 retval = NULL; 4032 } 4033 else { 4034 switch (_DB_get_type(self->mydb)) { 4035 case -1: 4036 retval = NULL; 4037 break; 4038 case DB_BTREE: 4039 case DB_HASH: 4040 default: 4041 retval = BuildValue_SS(key.data, key.size, data.data, data.size); 4042 break; 4043 case DB_RECNO: 4044 case DB_QUEUE: 4045 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); 4046 break; 4047 } 4048 } 4049 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4050 return retval; 4051 } 4052 4053 static PyObject* 4054 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4055 { 4056 int err, flags=0; 4057 PyObject* keyobj = NULL; 4058 PyObject* dataobj = NULL; 4059 PyObject* retval = NULL; 4060 int dlen = -1; 4061 int doff = -1; 4062 DBT key, pkey, data; 4063 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL }; 4064 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL }; 4065 4066 CLEAR_DBT(key); 4067 CLEAR_DBT(data); 4068 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2], 4069 &flags, &dlen, &doff)) 4070 { 4071 PyErr_Clear(); 4072 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget", 4073 kwnames_keyOnly, 4074 &keyobj, &flags, &dlen, &doff)) 4075 { 4076 PyErr_Clear(); 4077 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget", 4078 kwnames, &keyobj, &dataobj, 4079 &flags, &dlen, &doff)) 4080 { 4081 return NULL; 4082 } 4083 } 4084 } 4085 4086 CHECK_CURSOR_NOT_CLOSED(self); 4087 4088 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) 4089 return NULL; 4090 if ( (dataobj && !make_dbt(dataobj, &data)) || 4091 (!add_partial_dbt(&data, dlen, doff)) ) { 4092 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4093 return NULL; 4094 } 4095 4096 CLEAR_DBT(pkey); 4097 pkey.flags = DB_DBT_MALLOC; 4098 4099 MYDB_BEGIN_ALLOW_THREADS; 4100 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags); 4101 MYDB_END_ALLOW_THREADS; 4102 4103 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) 4104 && self->mydb->moduleFlags.getReturnsNone) { 4105 Py_INCREF(Py_None); 4106 retval = Py_None; 4107 } 4108 else if (makeDBError(err)) { 4109 retval = NULL; 4110 } 4111 else { 4112 PyObject *pkeyObj; 4113 PyObject *dataObj; 4114 dataObj = Build_PyString(data.data, data.size); 4115 4116 if (self->mydb->primaryDBType == DB_RECNO || 4117 self->mydb->primaryDBType == DB_QUEUE) 4118 pkeyObj = NUMBER_FromLong(*(int *)pkey.data); 4119 else 4120 pkeyObj = Build_PyString(pkey.data, pkey.size); 4121 4122 if (key.data && key.size) /* return key, pkey and data */ 4123 { 4124 PyObject *keyObj; 4125 int type = _DB_get_type(self->mydb); 4126 if (type == DB_RECNO || type == DB_QUEUE) 4127 keyObj = NUMBER_FromLong(*(int *)key.data); 4128 else 4129 keyObj = Build_PyString(key.data, key.size); 4130 #if (PY_VERSION_HEX >= 0x02040000) 4131 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj); 4132 #else 4133 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj); 4134 #endif 4135 Py_DECREF(keyObj); 4136 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4137 } 4138 else /* return just the pkey and data */ 4139 { 4140 #if (PY_VERSION_HEX >= 0x02040000) 4141 retval = PyTuple_Pack(2, pkeyObj, dataObj); 4142 #else 4143 retval = Py_BuildValue("OO", pkeyObj, dataObj); 4144 #endif 4145 } 4146 Py_DECREF(dataObj); 4147 Py_DECREF(pkeyObj); 4148 FREE_DBT(pkey); 4149 } 4150 /* the only time REALLOC should be set is if we used an integer 4151 * key that make_key_dbt malloc'd for us. always free these. */ 4152 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */ 4153 FREE_DBT(key); 4154 } 4155 return retval; 4156 } 4157 4158 4159 static PyObject* 4160 DBC_get_recno(DBCursorObject* self) 4161 { 4162 int err; 4163 db_recno_t recno; 4164 DBT key; 4165 DBT data; 4166 4167 CHECK_CURSOR_NOT_CLOSED(self); 4168 4169 CLEAR_DBT(key); 4170 CLEAR_DBT(data); 4171 4172 MYDB_BEGIN_ALLOW_THREADS; 4173 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO); 4174 MYDB_END_ALLOW_THREADS; 4175 RETURN_IF_ERR(); 4176 4177 recno = *((db_recno_t*)data.data); 4178 return NUMBER_FromLong(recno); 4179 } 4180 4181 4182 static PyObject* 4183 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4184 { 4185 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last"); 4186 } 4187 4188 4189 static PyObject* 4190 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4191 { 4192 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next"); 4193 } 4194 4195 4196 static PyObject* 4197 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4198 { 4199 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev"); 4200 } 4201 4202 4203 static PyObject* 4204 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs) 4205 { 4206 int err, flags = 0; 4207 PyObject* keyobj, *dataobj; 4208 DBT key, data; 4209 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", 4210 NULL }; 4211 int dlen = -1; 4212 int doff = -1; 4213 4214 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames, 4215 &keyobj, &dataobj, &flags, &dlen, &doff)) 4216 return NULL; 4217 4218 CHECK_CURSOR_NOT_CLOSED(self); 4219 4220 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) 4221 return NULL; 4222 if (!make_dbt(dataobj, &data) || 4223 !add_partial_dbt(&data, dlen, doff) ) 4224 { 4225 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4226 return NULL; 4227 } 4228 4229 MYDB_BEGIN_ALLOW_THREADS; 4230 err = _DBC_put(self->dbc, &key, &data, flags); 4231 MYDB_END_ALLOW_THREADS; 4232 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4233 RETURN_IF_ERR(); 4234 RETURN_NONE(); 4235 } 4236 4237 4238 static PyObject* 4239 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4240 { 4241 int err, flags = 0; 4242 DBT key, data; 4243 PyObject* retval, *keyobj; 4244 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; 4245 int dlen = -1; 4246 int doff = -1; 4247 4248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames, 4249 &keyobj, &flags, &dlen, &doff)) 4250 return NULL; 4251 4252 CHECK_CURSOR_NOT_CLOSED(self); 4253 4254 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) 4255 return NULL; 4256 4257 CLEAR_DBT(data); 4258 if (!add_partial_dbt(&data, dlen, doff)) { 4259 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4260 return NULL; 4261 } 4262 4263 MYDB_BEGIN_ALLOW_THREADS; 4264 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET); 4265 MYDB_END_ALLOW_THREADS; 4266 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) 4267 && self->mydb->moduleFlags.cursorSetReturnsNone) { 4268 Py_INCREF(Py_None); 4269 retval = Py_None; 4270 } 4271 else if (makeDBError(err)) { 4272 retval = NULL; 4273 } 4274 else { 4275 switch (_DB_get_type(self->mydb)) { 4276 case -1: 4277