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 retval = NULL; 4278 break; 4279 case DB_BTREE: 4280 case DB_HASH: 4281 default: 4282 retval = BuildValue_SS(key.data, key.size, data.data, data.size); 4283 break; 4284 case DB_RECNO: 4285 case DB_QUEUE: 4286 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); 4287 break; 4288 } 4289 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4290 } 4291 /* the only time REALLOC should be set is if we used an integer 4292 * key that make_key_dbt malloc'd for us. always free these. */ 4293 if (key.flags & DB_DBT_REALLOC) { 4294 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4295 } 4296 4297 return retval; 4298 } 4299 4300 4301 static PyObject* 4302 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs) 4303 { 4304 int err, flags = 0; 4305 DBT key, data; 4306 PyObject* retval, *keyobj; 4307 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; 4308 int dlen = -1; 4309 int doff = -1; 4310 4311 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames, 4312 &keyobj, &flags, &dlen, &doff)) 4313 return NULL; 4314 4315 CHECK_CURSOR_NOT_CLOSED(self); 4316 4317 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) 4318 return NULL; 4319 4320 CLEAR_DBT(data); 4321 if (!add_partial_dbt(&data, dlen, doff)) { 4322 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4323 return NULL; 4324 } 4325 MYDB_BEGIN_ALLOW_THREADS; 4326 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE); 4327 MYDB_END_ALLOW_THREADS; 4328 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) 4329 && self->mydb->moduleFlags.cursorSetReturnsNone) { 4330 Py_INCREF(Py_None); 4331 retval = Py_None; 4332 } 4333 else if (makeDBError(err)) { 4334 retval = NULL; 4335 } 4336 else { 4337 switch (_DB_get_type(self->mydb)) { 4338 case -1: 4339 retval = NULL; 4340 break; 4341 case DB_BTREE: 4342 case DB_HASH: 4343 default: 4344 retval = BuildValue_SS(key.data, key.size, data.data, data.size); 4345 break; 4346 case DB_RECNO: 4347 case DB_QUEUE: 4348 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); 4349 break; 4350 } 4351 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4352 } 4353 /* the only time REALLOC should be set is if we used an integer 4354 * key that make_key_dbt malloc'd for us. always free these. */ 4355 if (key.flags & DB_DBT_REALLOC) { 4356 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4357 } 4358 4359 return retval; 4360 } 4361 4362 static PyObject* 4363 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj, 4364 int flags, unsigned int returnsNone) 4365 { 4366 int err; 4367 DBT key, data; 4368 PyObject* retval; 4369 4370 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */ 4371 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) 4372 return NULL; 4373 if (!make_dbt(dataobj, &data)) { 4374 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4375 return NULL; 4376 } 4377 4378 MYDB_BEGIN_ALLOW_THREADS; 4379 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH); 4380 MYDB_END_ALLOW_THREADS; 4381 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) { 4382 Py_INCREF(Py_None); 4383 retval = Py_None; 4384 } 4385 else if (makeDBError(err)) { 4386 retval = NULL; 4387 } 4388 else { 4389 switch (_DB_get_type(self->mydb)) { 4390 case -1: 4391 retval = NULL; 4392 break; 4393 case DB_BTREE: 4394 case DB_HASH: 4395 default: 4396 retval = BuildValue_SS(key.data, key.size, data.data, data.size); 4397 break; 4398 case DB_RECNO: 4399 case DB_QUEUE: 4400 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size); 4401 break; 4402 } 4403 } 4404 4405 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */ 4406 return retval; 4407 } 4408 4409 static PyObject* 4410 DBC_get_both(DBCursorObject* self, PyObject* args) 4411 { 4412 int flags=0; 4413 PyObject *keyobj, *dataobj; 4414 4415 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags)) 4416 return NULL; 4417 4418 /* if the cursor is closed, self->mydb may be invalid */ 4419 CHECK_CURSOR_NOT_CLOSED(self); 4420 4421 return _DBC_get_set_both(self, keyobj, dataobj, flags, 4422 self->mydb->moduleFlags.getReturnsNone); 4423 } 4424 4425 /* Return size of entry */ 4426 static PyObject* 4427 DBC_get_current_size(DBCursorObject* self) 4428 { 4429 int err, flags=DB_CURRENT; 4430 PyObject* retval = NULL; 4431 DBT key, data; 4432 4433 CHECK_CURSOR_NOT_CLOSED(self); 4434 CLEAR_DBT(key); 4435 CLEAR_DBT(data); 4436 4437 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus 4438 getting the record size. */ 4439 data.flags = DB_DBT_USERMEM; 4440 data.ulen = 0; 4441 MYDB_BEGIN_ALLOW_THREADS; 4442 err = _DBC_get(self->dbc, &key, &data, flags); 4443 MYDB_END_ALLOW_THREADS; 4444 if (err == DB_BUFFER_SMALL || !err) { 4445 /* DB_BUFFER_SMALL means positive size, !err means zero length value */ 4446 retval = NUMBER_FromLong((long)data.size); 4447 err = 0; 4448 } 4449 4450 RETURN_IF_ERR(); 4451 return retval; 4452 } 4453 4454 static PyObject* 4455 DBC_set_both(DBCursorObject* self, PyObject* args) 4456 { 4457 int flags=0; 4458 PyObject *keyobj, *dataobj; 4459 4460 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags)) 4461 return NULL; 4462 4463 /* if the cursor is closed, self->mydb may be invalid */ 4464 CHECK_CURSOR_NOT_CLOSED(self); 4465 4466 return _DBC_get_set_both(self, keyobj, dataobj, flags, 4467 self->mydb->moduleFlags.cursorSetReturnsNone); 4468 } 4469 4470 4471 static PyObject* 4472 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4473 { 4474 int err, irecno, flags=0; 4475 db_recno_t recno; 4476 DBT key, data; 4477 PyObject* retval; 4478 int dlen = -1; 4479 int doff = -1; 4480 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL }; 4481 4482 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames, 4483 &irecno, &flags, &dlen, &doff)) 4484 return NULL; 4485 4486 CHECK_CURSOR_NOT_CLOSED(self); 4487 4488 CLEAR_DBT(key); 4489 recno = (db_recno_t) irecno; 4490 /* use allocated space so DB will be able to realloc room for the real 4491 * key */ 4492 key.data = malloc(sizeof(db_recno_t)); 4493 if (key.data == NULL) { 4494 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); 4495 return NULL; 4496 } 4497 key.size = sizeof(db_recno_t); 4498 key.ulen = key.size; 4499 memcpy(key.data, &recno, sizeof(db_recno_t)); 4500 key.flags = DB_DBT_REALLOC; 4501 4502 CLEAR_DBT(data); 4503 if (!add_partial_dbt(&data, dlen, doff)) { 4504 FREE_DBT(key); 4505 return NULL; 4506 } 4507 4508 MYDB_BEGIN_ALLOW_THREADS; 4509 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO); 4510 MYDB_END_ALLOW_THREADS; 4511 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) 4512 && self->mydb->moduleFlags.cursorSetReturnsNone) { 4513 Py_INCREF(Py_None); 4514 retval = Py_None; 4515 } 4516 else if (makeDBError(err)) { 4517 retval = NULL; 4518 } 4519 else { /* Can only be used for BTrees, so no need to return int key */ 4520 retval = BuildValue_SS(key.data, key.size, data.data, data.size); 4521 } 4522 FREE_DBT(key); 4523 4524 return retval; 4525 } 4526 4527 4528 static PyObject* 4529 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4530 { 4531 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume"); 4532 } 4533 4534 4535 static PyObject* 4536 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4537 { 4538 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup"); 4539 } 4540 4541 4542 static PyObject* 4543 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4544 { 4545 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup"); 4546 } 4547 4548 #if (DBVER >= 46) 4549 static PyObject* 4550 DBC_prev_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4551 { 4552 return _DBCursor_get(self,DB_PREV_DUP,args,kwargs,"|iii:prev_dup"); 4553 } 4554 #endif 4555 4556 static PyObject* 4557 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) 4558 { 4559 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup"); 4560 } 4561 4562 4563 static PyObject* 4564 DBC_join_item(DBCursorObject* self, PyObject* args) 4565 { 4566 int err, flags=0; 4567 DBT key, data; 4568 PyObject* retval; 4569 4570 if (!PyArg_ParseTuple(args, "|i:join_item", &flags)) 4571 return NULL; 4572 4573 CHECK_CURSOR_NOT_CLOSED(self); 4574 4575 CLEAR_DBT(key); 4576 CLEAR_DBT(data); 4577 4578 MYDB_BEGIN_ALLOW_THREADS; 4579 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); 4580 MYDB_END_ALLOW_THREADS; 4581 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) 4582 && self->mydb->moduleFlags.getReturnsNone) { 4583 Py_INCREF(Py_None); 4584 retval = Py_None; 4585 } 4586 else if (makeDBError(err)) { 4587 retval = NULL; 4588 } 4589 else { 4590 retval = BuildValue_S(key.data, key.size); 4591 } 4592 4593 return retval; 4594 } 4595 4596 4597 #if (DBVER >= 46) 4598 static PyObject* 4599 DBC_set_priority(DBCursorObject* self, PyObject* args, PyObject* kwargs) 4600 { 4601 int err, priority; 4602 static char* kwnames[] = { "priority", NULL }; 4603 4604 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_priority", kwnames, 4605 &priority)) 4606 return NULL; 4607 4608 CHECK_CURSOR_NOT_CLOSED(self); 4609 4610 MYDB_BEGIN_ALLOW_THREADS; 4611 err = self->dbc->set_priority(self->dbc, priority); 4612 MYDB_END_ALLOW_THREADS; 4613 RETURN_IF_ERR(); 4614 RETURN_NONE(); 4615 } 4616 4617 4618 static PyObject* 4619 DBC_get_priority(DBCursorObject* self) 4620 { 4621 int err; 4622 DB_CACHE_PRIORITY priority; 4623 4624 CHECK_CURSOR_NOT_CLOSED(self); 4625 4626 MYDB_BEGIN_ALLOW_THREADS; 4627 err = self->dbc->get_priority(self->dbc, &priority); 4628 MYDB_END_ALLOW_THREADS; 4629 RETURN_IF_ERR(); 4630 return NUMBER_FromLong(priority); 4631 } 4632 #endif 4633 4634 4635 4636 /* --------------------------------------------------------------------- */ 4637 /* DBEnv methods */ 4638 4639 4640 static PyObject* 4641 DBEnv_close_internal(DBEnvObject* self, int flags) 4642 { 4643 PyObject *dummy; 4644 int err; 4645 4646 if (!self->closed) { /* Don't close more than once */ 4647 while(self->children_txns) { 4648 dummy = DBTxn_abort_discard_internal(self->children_txns, 0); 4649 Py_XDECREF(dummy); 4650 } 4651 while(self->children_dbs) { 4652 dummy = DB_close_internal(self->children_dbs, 0, 0); 4653 Py_XDECREF(dummy); 4654 } 4655 while(self->children_logcursors) { 4656 dummy = DBLogCursor_close_internal(self->children_logcursors); 4657 Py_XDECREF(dummy); 4658 } 4659 } 4660 4661 self->closed = 1; 4662 if (self->db_env) { 4663 MYDB_BEGIN_ALLOW_THREADS; 4664 err = self->db_env->close(self->db_env, flags); 4665 MYDB_END_ALLOW_THREADS; 4666 /* after calling DBEnv->close, regardless of error, this DBEnv 4667 * may not be accessed again (Berkeley DB docs). */ 4668 self->db_env = NULL; 4669 RETURN_IF_ERR(); 4670 } 4671 RETURN_NONE(); 4672 } 4673 4674 static PyObject* 4675 DBEnv_close(DBEnvObject* self, PyObject* args) 4676 { 4677 int flags = 0; 4678 4679 if (!PyArg_ParseTuple(args, "|i:close", &flags)) 4680 return NULL; 4681 return DBEnv_close_internal(self, flags); 4682 } 4683 4684 4685 static PyObject* 4686 DBEnv_open(DBEnvObject* self, PyObject* args) 4687 { 4688 int err, flags=0, mode=0660; 4689 char *db_home; 4690 4691 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode)) 4692 return NULL; 4693 4694 CHECK_ENV_NOT_CLOSED(self); 4695 4696 MYDB_BEGIN_ALLOW_THREADS; 4697 err = self->db_env->open(self->db_env, db_home, flags, mode); 4698 MYDB_END_ALLOW_THREADS; 4699 RETURN_IF_ERR(); 4700 self->closed = 0; 4701 self->flags = flags; 4702 RETURN_NONE(); 4703 } 4704 4705 4706 static PyObject* 4707 DBEnv_memp_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs) 4708 { 4709 int err; 4710 DB_MPOOL_STAT *gsp; 4711 DB_MPOOL_FSTAT **fsp, **fsp2; 4712 PyObject* d = NULL, *d2, *d3, *r; 4713 u_int32_t flags = 0; 4714 static char* kwnames[] = { "flags", NULL }; 4715 4716 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat", 4717 kwnames, &flags)) 4718 return NULL; 4719 4720 CHECK_ENV_NOT_CLOSED(self); 4721 4722 MYDB_BEGIN_ALLOW_THREADS; 4723 err = self->db_env->memp_stat(self->db_env, &gsp, &fsp, flags); 4724 MYDB_END_ALLOW_THREADS; 4725 RETURN_IF_ERR(); 4726 4727 /* Turn the stat structure into a dictionary */ 4728 d = PyDict_New(); 4729 if (d == NULL) { 4730 if (gsp) 4731 free(gsp); 4732 return NULL; 4733 } 4734 4735 #define MAKE_ENTRY(name) _addIntToDict(d, #name, gsp->st_##name) 4736 4737 MAKE_ENTRY(gbytes); 4738 MAKE_ENTRY(ncache); 4739 #if (DBVER >= 46) 4740 MAKE_ENTRY(max_ncache); 4741 #endif 4742 MAKE_ENTRY(regsize); 4743 #if (DBVER >= 43) 4744 MAKE_ENTRY(mmapsize); 4745 MAKE_ENTRY(maxopenfd); 4746 MAKE_ENTRY(maxwrite); 4747 MAKE_ENTRY(maxwrite_sleep); 4748 #endif 4749 MAKE_ENTRY(map); 4750 MAKE_ENTRY(cache_hit); 4751 MAKE_ENTRY(cache_miss); 4752 MAKE_ENTRY(page_create); 4753 MAKE_ENTRY(page_in); 4754 MAKE_ENTRY(page_out); 4755 MAKE_ENTRY(ro_evict); 4756 MAKE_ENTRY(rw_evict); 4757 MAKE_ENTRY(page_trickle); 4758 MAKE_ENTRY(pages); 4759 MAKE_ENTRY(page_clean); 4760 MAKE_ENTRY(page_dirty); 4761 MAKE_ENTRY(hash_buckets); 4762 MAKE_ENTRY(hash_searches); 4763 MAKE_ENTRY(hash_longest); 4764 MAKE_ENTRY(hash_examined); 4765 MAKE_ENTRY(hash_nowait); 4766 MAKE_ENTRY(hash_wait); 4767 #if (DBVER >= 45) 4768 MAKE_ENTRY(hash_max_nowait); 4769 #endif 4770 MAKE_ENTRY(hash_max_wait); 4771 MAKE_ENTRY(region_wait); 4772 MAKE_ENTRY(region_nowait); 4773 #if (DBVER >= 45) 4774 MAKE_ENTRY(mvcc_frozen); 4775 MAKE_ENTRY(mvcc_thawed); 4776 MAKE_ENTRY(mvcc_freed); 4777 #endif 4778 MAKE_ENTRY(alloc); 4779 MAKE_ENTRY(alloc_buckets); 4780 MAKE_ENTRY(alloc_max_buckets); 4781 MAKE_ENTRY(alloc_pages); 4782 MAKE_ENTRY(alloc_max_pages); 4783 #if (DBVER >= 45) 4784 MAKE_ENTRY(io_wait); 4785 #endif 4786 #if (DBVER >= 48) 4787 MAKE_ENTRY(sync_interrupted); 4788 #endif 4789 4790 #undef MAKE_ENTRY 4791 free(gsp); 4792 4793 d2 = PyDict_New(); 4794 if (d2 == NULL) { 4795 Py_DECREF(d); 4796 if (fsp) 4797 free(fsp); 4798 return NULL; 4799 } 4800 #define MAKE_ENTRY(name) _addIntToDict(d3, #name, (*fsp2)->st_##name) 4801 for(fsp2=fsp;*fsp2; fsp2++) { 4802 d3 = PyDict_New(); 4803 if (d3 == NULL) { 4804 Py_DECREF(d); 4805 Py_DECREF(d2); 4806 if (fsp) 4807 free(fsp); 4808 return NULL; 4809 } 4810 MAKE_ENTRY(pagesize); 4811 MAKE_ENTRY(cache_hit); 4812 MAKE_ENTRY(cache_miss); 4813 MAKE_ENTRY(map); 4814 MAKE_ENTRY(page_create); 4815 MAKE_ENTRY(page_in); 4816 MAKE_ENTRY(page_out); 4817 if(PyDict_SetItemString(d2, (*fsp2)->file_name, d3)) { 4818 Py_DECREF(d); 4819 Py_DECREF(d2); 4820 Py_DECREF(d3); 4821 if (fsp) 4822 free(fsp); 4823 return NULL; 4824 } 4825 Py_DECREF(d3); 4826 } 4827 4828 #undef MAKE_ENTRY 4829 free(fsp); 4830 4831 r = Py_BuildValue("(OO)", d, d2); 4832 Py_DECREF(d); 4833 Py_DECREF(d2); 4834 return r; 4835 } 4836 4837 #if (DBVER >= 43) 4838 static PyObject* 4839 DBEnv_memp_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 4840 { 4841 int err; 4842 int flags=0; 4843 static char* kwnames[] = { "flags", NULL }; 4844 4845 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:memp_stat_print", 4846 kwnames, &flags)) 4847 { 4848 return NULL; 4849 } 4850 CHECK_ENV_NOT_CLOSED(self); 4851 MYDB_BEGIN_ALLOW_THREADS; 4852 err = self->db_env->memp_stat_print(self->db_env, flags); 4853 MYDB_END_ALLOW_THREADS; 4854 RETURN_IF_ERR(); 4855 RETURN_NONE(); 4856 } 4857 #endif 4858 4859 4860 static PyObject* 4861 DBEnv_memp_trickle(DBEnvObject* self, PyObject* args) 4862 { 4863 int err, percent, nwrotep; 4864 4865 if (!PyArg_ParseTuple(args, "i:memp_trickle", &percent)) 4866 return NULL; 4867 CHECK_ENV_NOT_CLOSED(self); 4868 MYDB_BEGIN_ALLOW_THREADS; 4869 err = self->db_env->memp_trickle(self->db_env, percent, &nwrotep); 4870 MYDB_END_ALLOW_THREADS; 4871 RETURN_IF_ERR(); 4872 return NUMBER_FromLong(nwrotep); 4873 } 4874 4875 static PyObject* 4876 DBEnv_memp_sync(DBEnvObject* self, PyObject* args) 4877 { 4878 int err; 4879 DB_LSN lsn = {0, 0}; 4880 DB_LSN *lsn_p = NULL; 4881 4882 if (!PyArg_ParseTuple(args, "|(ii):memp_sync", &lsn.file, &lsn.offset)) 4883 return NULL; 4884 if ((lsn.file!=0) || (lsn.offset!=0)) { 4885 lsn_p = &lsn; 4886 } 4887 CHECK_ENV_NOT_CLOSED(self); 4888 MYDB_BEGIN_ALLOW_THREADS; 4889 err = self->db_env->memp_sync(self->db_env, lsn_p); 4890 MYDB_END_ALLOW_THREADS; 4891 RETURN_IF_ERR(); 4892 RETURN_NONE(); 4893 } 4894 4895 static PyObject* 4896 DBEnv_remove(DBEnvObject* self, PyObject* args) 4897 { 4898 int err, flags=0; 4899 char *db_home; 4900 4901 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags)) 4902 return NULL; 4903 CHECK_ENV_NOT_CLOSED(self); 4904 MYDB_BEGIN_ALLOW_THREADS; 4905 err = self->db_env->remove(self->db_env, db_home, flags); 4906 MYDB_END_ALLOW_THREADS; 4907 RETURN_IF_ERR(); 4908 RETURN_NONE(); 4909 } 4910 4911 static PyObject* 4912 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs) 4913 { 4914 int err; 4915 u_int32_t flags=0; 4916 char *file = NULL; 4917 char *database = NULL; 4918 PyObject *txnobj = NULL; 4919 DB_TXN *txn = NULL; 4920 static char* kwnames[] = { "file", "database", "txn", "flags", 4921 NULL }; 4922 4923 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames, 4924 &file, &database, &txnobj, &flags)) { 4925 return NULL; 4926 } 4927 if (!checkTxnObj(txnobj, &txn)) { 4928 return NULL; 4929 } 4930 CHECK_ENV_NOT_CLOSED(self); 4931 MYDB_BEGIN_ALLOW_THREADS; 4932 err = self->db_env->dbremove(self->db_env, txn, file, database, flags); 4933 MYDB_END_ALLOW_THREADS; 4934 RETURN_IF_ERR(); 4935 RETURN_NONE(); 4936 } 4937 4938 static PyObject* 4939 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs) 4940 { 4941 int err; 4942 u_int32_t flags=0; 4943 char *file = NULL; 4944 char *database = NULL; 4945 char *newname = NULL; 4946 PyObject *txnobj = NULL; 4947 DB_TXN *txn = NULL; 4948 static char* kwnames[] = { "file", "database", "newname", "txn", 4949 "flags", NULL }; 4950 4951 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames, 4952 &file, &database, &newname, &txnobj, &flags)) { 4953 return NULL; 4954 } 4955 if (!checkTxnObj(txnobj, &txn)) { 4956 return NULL; 4957 } 4958 CHECK_ENV_NOT_CLOSED(self); 4959 MYDB_BEGIN_ALLOW_THREADS; 4960 err = self->db_env->dbrename(self->db_env, txn, file, database, newname, 4961 flags); 4962 MYDB_END_ALLOW_THREADS; 4963 RETURN_IF_ERR(); 4964 RETURN_NONE(); 4965 } 4966 4967 4968 4969 static PyObject* 4970 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs) 4971 { 4972 int err; 4973 u_int32_t flags=0; 4974 char *passwd = NULL; 4975 static char* kwnames[] = { "passwd", "flags", NULL }; 4976 4977 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, 4978 &passwd, &flags)) { 4979 return NULL; 4980 } 4981 4982 MYDB_BEGIN_ALLOW_THREADS; 4983 err = self->db_env->set_encrypt(self->db_env, passwd, flags); 4984 MYDB_END_ALLOW_THREADS; 4985 4986 RETURN_IF_ERR(); 4987 RETURN_NONE(); 4988 } 4989 4990 #if (DBVER >= 42) 4991 static PyObject* 4992 DBEnv_get_encrypt_flags(DBEnvObject* self) 4993 { 4994 int err; 4995 u_int32_t flags; 4996 4997 CHECK_ENV_NOT_CLOSED(self); 4998 4999 MYDB_BEGIN_ALLOW_THREADS; 5000 err = self->db_env->get_encrypt_flags(self->db_env, &flags); 5001 MYDB_END_ALLOW_THREADS; 5002 5003 RETURN_IF_ERR(); 5004 5005 return NUMBER_FromLong(flags); 5006 } 5007 5008 static PyObject* 5009 DBEnv_get_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs) 5010 { 5011 int err; 5012 int flag; 5013 u_int32_t timeout; 5014 static char* kwnames[] = {"flag", NULL }; 5015 5016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:get_timeout", kwnames, 5017 &flag)) { 5018 return NULL; 5019 } 5020 CHECK_ENV_NOT_CLOSED(self); 5021 5022 MYDB_BEGIN_ALLOW_THREADS; 5023 err = self->db_env->get_timeout(self->db_env, &timeout, flag); 5024 MYDB_END_ALLOW_THREADS; 5025 RETURN_IF_ERR(); 5026 return NUMBER_FromLong(timeout); 5027 } 5028 #endif 5029 5030 5031 static PyObject* 5032 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs) 5033 { 5034 int err; 5035 u_int32_t flags=0; 5036 u_int32_t timeout = 0; 5037 static char* kwnames[] = { "timeout", "flags", NULL }; 5038 5039 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames, 5040 &timeout, &flags)) { 5041 return NULL; 5042 } 5043 5044 MYDB_BEGIN_ALLOW_THREADS; 5045 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags); 5046 MYDB_END_ALLOW_THREADS; 5047 5048 RETURN_IF_ERR(); 5049 RETURN_NONE(); 5050 } 5051 5052 static PyObject* 5053 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args) 5054 { 5055 int err; 5056 long shm_key = 0; 5057 5058 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key)) 5059 return NULL; 5060 CHECK_ENV_NOT_CLOSED(self); 5061 5062 err = self->db_env->set_shm_key(self->db_env, shm_key); 5063 RETURN_IF_ERR(); 5064 RETURN_NONE(); 5065 } 5066 5067 #if (DBVER >= 42) 5068 static PyObject* 5069 DBEnv_get_shm_key(DBEnvObject* self) 5070 { 5071 int err; 5072 long shm_key; 5073 5074 CHECK_ENV_NOT_CLOSED(self); 5075 5076 MYDB_BEGIN_ALLOW_THREADS; 5077 err = self->db_env->get_shm_key(self->db_env, &shm_key); 5078 MYDB_END_ALLOW_THREADS; 5079 5080 RETURN_IF_ERR(); 5081 5082 return NUMBER_FromLong(shm_key); 5083 } 5084 #endif 5085 5086 #if (DBVER >= 46) 5087 static PyObject* 5088 DBEnv_set_cache_max(DBEnvObject* self, PyObject* args) 5089 { 5090 int err, gbytes, bytes; 5091 5092 if (!PyArg_ParseTuple(args, "ii:set_cache_max", 5093 &gbytes, &bytes)) 5094 return NULL; 5095 CHECK_ENV_NOT_CLOSED(self); 5096 5097 MYDB_BEGIN_ALLOW_THREADS; 5098 err = self->db_env->set_cache_max(self->db_env, gbytes, bytes); 5099 MYDB_END_ALLOW_THREADS; 5100 RETURN_IF_ERR(); 5101 RETURN_NONE(); 5102 } 5103 5104 static PyObject* 5105 DBEnv_get_cache_max(DBEnvObject* self) 5106 { 5107 int err; 5108 u_int32_t gbytes, bytes; 5109 5110 CHECK_ENV_NOT_CLOSED(self); 5111 5112 MYDB_BEGIN_ALLOW_THREADS; 5113 err = self->db_env->get_cache_max(self->db_env, &gbytes, &bytes); 5114 MYDB_END_ALLOW_THREADS; 5115 5116 RETURN_IF_ERR(); 5117 5118 return Py_BuildValue("(ii)", gbytes, bytes); 5119 } 5120 #endif 5121 5122 #if (DBVER >= 46) 5123 static PyObject* 5124 DBEnv_set_thread_count(DBEnvObject* self, PyObject* args) 5125 { 5126 int err; 5127 u_int32_t count; 5128 5129 if (!PyArg_ParseTuple(args, "i:set_thread_count", &count)) 5130 return NULL; 5131 CHECK_ENV_NOT_CLOSED(self); 5132 5133 MYDB_BEGIN_ALLOW_THREADS; 5134 err = self->db_env->set_thread_count(self->db_env, count); 5135 MYDB_END_ALLOW_THREADS; 5136 RETURN_IF_ERR(); 5137 RETURN_NONE(); 5138 } 5139 5140 static PyObject* 5141 DBEnv_get_thread_count(DBEnvObject* self) 5142 { 5143 int err; 5144 u_int32_t count; 5145 5146 CHECK_ENV_NOT_CLOSED(self); 5147 5148 MYDB_BEGIN_ALLOW_THREADS; 5149 err = self->db_env->get_thread_count(self->db_env, &count); 5150 MYDB_END_ALLOW_THREADS; 5151 RETURN_IF_ERR(); 5152 return NUMBER_FromLong(count); 5153 } 5154 #endif 5155 5156 static PyObject* 5157 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args) 5158 { 5159 int err, gbytes=0, bytes=0, ncache=0; 5160 5161 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize", 5162 &gbytes, &bytes, &ncache)) 5163 return NULL; 5164 CHECK_ENV_NOT_CLOSED(self); 5165 5166 MYDB_BEGIN_ALLOW_THREADS; 5167 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache); 5168 MYDB_END_ALLOW_THREADS; 5169 RETURN_IF_ERR(); 5170 RETURN_NONE(); 5171 } 5172 5173 #if (DBVER >= 42) 5174 static PyObject* 5175 DBEnv_get_cachesize(DBEnvObject* self) 5176 { 5177 int err; 5178 u_int32_t gbytes, bytes; 5179 int ncache; 5180 5181 CHECK_ENV_NOT_CLOSED(self); 5182 5183 MYDB_BEGIN_ALLOW_THREADS; 5184 err = self->db_env->get_cachesize(self->db_env, &gbytes, &bytes, &ncache); 5185 MYDB_END_ALLOW_THREADS; 5186 5187 RETURN_IF_ERR(); 5188 5189 return Py_BuildValue("(iii)", gbytes, bytes, ncache); 5190 } 5191 #endif 5192 5193 5194 static PyObject* 5195 DBEnv_set_flags(DBEnvObject* self, PyObject* args) 5196 { 5197 int err, flags=0, onoff=0; 5198 5199 if (!PyArg_ParseTuple(args, "ii:set_flags", 5200 &flags, &onoff)) 5201 return NULL; 5202 CHECK_ENV_NOT_CLOSED(self); 5203 5204 MYDB_BEGIN_ALLOW_THREADS; 5205 err = self->db_env->set_flags(self->db_env, flags, onoff); 5206 MYDB_END_ALLOW_THREADS; 5207 RETURN_IF_ERR(); 5208 RETURN_NONE(); 5209 } 5210 5211 #if (DBVER >= 42) 5212 static PyObject* 5213 DBEnv_get_flags(DBEnvObject* self) 5214 { 5215 int err; 5216 u_int32_t flags; 5217 5218 CHECK_ENV_NOT_CLOSED(self); 5219 5220 MYDB_BEGIN_ALLOW_THREADS; 5221 err = self->db_env->get_flags(self->db_env, &flags); 5222 MYDB_END_ALLOW_THREADS; 5223 RETURN_IF_ERR(); 5224 return NUMBER_FromLong(flags); 5225 } 5226 #endif 5227 5228 #if (DBVER >= 47) 5229 static PyObject* 5230 DBEnv_log_set_config(DBEnvObject* self, PyObject* args) 5231 { 5232 int err, flags, onoff; 5233 5234 if (!PyArg_ParseTuple(args, "ii:log_set_config", 5235 &flags, &onoff)) 5236 return NULL; 5237 CHECK_ENV_NOT_CLOSED(self); 5238 5239 MYDB_BEGIN_ALLOW_THREADS; 5240 err = self->db_env->log_set_config(self->db_env, flags, onoff); 5241 MYDB_END_ALLOW_THREADS; 5242 RETURN_IF_ERR(); 5243 RETURN_NONE(); 5244 } 5245 5246 static PyObject* 5247 DBEnv_log_get_config(DBEnvObject* self, PyObject* args) 5248 { 5249 int err, flag, onoff; 5250 5251 if (!PyArg_ParseTuple(args, "i:log_get_config", &flag)) 5252 return NULL; 5253 CHECK_ENV_NOT_CLOSED(self); 5254 5255 MYDB_BEGIN_ALLOW_THREADS; 5256 err = self->db_env->log_get_config(self->db_env, flag, &onoff); 5257 MYDB_END_ALLOW_THREADS; 5258 RETURN_IF_ERR(); 5259 return PyBool_FromLong(onoff); 5260 } 5261 #endif /* DBVER >= 47 */ 5262 5263 #if (DBVER >= 44) 5264 static PyObject* 5265 DBEnv_mutex_set_max(DBEnvObject* self, PyObject* args) 5266 { 5267 int err; 5268 int value; 5269 5270 if (!PyArg_ParseTuple(args, "i:mutex_set_max", &value)) 5271 return NULL; 5272 5273 CHECK_ENV_NOT_CLOSED(self); 5274 5275 MYDB_BEGIN_ALLOW_THREADS; 5276 err = self->db_env->mutex_set_max(self->db_env, value); 5277 MYDB_END_ALLOW_THREADS; 5278 5279 RETURN_IF_ERR(); 5280 RETURN_NONE(); 5281 } 5282 5283 static PyObject* 5284 DBEnv_mutex_get_max(DBEnvObject* self) 5285 { 5286 int err; 5287 u_int32_t value; 5288 5289 CHECK_ENV_NOT_CLOSED(self); 5290 5291 MYDB_BEGIN_ALLOW_THREADS; 5292 err = self->db_env->mutex_get_max(self->db_env, &value); 5293 MYDB_END_ALLOW_THREADS; 5294 5295 RETURN_IF_ERR(); 5296 5297 return NUMBER_FromLong(value); 5298 } 5299 5300 static PyObject* 5301 DBEnv_mutex_set_align(DBEnvObject* self, PyObject* args) 5302 { 5303 int err; 5304 int align; 5305 5306 if (!PyArg_ParseTuple(args, "i:mutex_set_align", &align)) 5307 return NULL; 5308 5309 CHECK_ENV_NOT_CLOSED(self); 5310 5311 MYDB_BEGIN_ALLOW_THREADS; 5312 err = self->db_env->mutex_set_align(self->db_env, align); 5313 MYDB_END_ALLOW_THREADS; 5314 5315 RETURN_IF_ERR(); 5316 RETURN_NONE(); 5317 } 5318 5319 static PyObject* 5320 DBEnv_mutex_get_align(DBEnvObject* self) 5321 { 5322 int err; 5323 u_int32_t align; 5324 5325 CHECK_ENV_NOT_CLOSED(self); 5326 5327 MYDB_BEGIN_ALLOW_THREADS; 5328 err = self->db_env->mutex_get_align(self->db_env, &align); 5329 MYDB_END_ALLOW_THREADS; 5330 5331 RETURN_IF_ERR(); 5332 5333 return NUMBER_FromLong(align); 5334 } 5335 5336 static PyObject* 5337 DBEnv_mutex_set_increment(DBEnvObject* self, PyObject* args) 5338 { 5339 int err; 5340 int increment; 5341 5342 if (!PyArg_ParseTuple(args, "i:mutex_set_increment", &increment)) 5343 return NULL; 5344 5345 CHECK_ENV_NOT_CLOSED(self); 5346 5347 MYDB_BEGIN_ALLOW_THREADS; 5348 err = self->db_env->mutex_set_increment(self->db_env, increment); 5349 MYDB_END_ALLOW_THREADS; 5350 5351 RETURN_IF_ERR(); 5352 RETURN_NONE(); 5353 } 5354 5355 static PyObject* 5356 DBEnv_mutex_get_increment(DBEnvObject* self) 5357 { 5358 int err; 5359 u_int32_t increment; 5360 5361 CHECK_ENV_NOT_CLOSED(self); 5362 5363 MYDB_BEGIN_ALLOW_THREADS; 5364 err = self->db_env->mutex_get_increment(self->db_env, &increment); 5365 MYDB_END_ALLOW_THREADS; 5366 5367 RETURN_IF_ERR(); 5368 5369 return NUMBER_FromLong(increment); 5370 } 5371 5372 static PyObject* 5373 DBEnv_mutex_set_tas_spins(DBEnvObject* self, PyObject* args) 5374 { 5375 int err; 5376 int tas_spins; 5377 5378 if (!PyArg_ParseTuple(args, "i:mutex_set_tas_spins", &tas_spins)) 5379 return NULL; 5380 5381 CHECK_ENV_NOT_CLOSED(self); 5382 5383 MYDB_BEGIN_ALLOW_THREADS; 5384 err = self->db_env->mutex_set_tas_spins(self->db_env, tas_spins); 5385 MYDB_END_ALLOW_THREADS; 5386 5387 RETURN_IF_ERR(); 5388 RETURN_NONE(); 5389 } 5390 5391 static PyObject* 5392 DBEnv_mutex_get_tas_spins(DBEnvObject* self) 5393 { 5394 int err; 5395 u_int32_t tas_spins; 5396 5397 CHECK_ENV_NOT_CLOSED(self); 5398 5399 MYDB_BEGIN_ALLOW_THREADS; 5400 err = self->db_env->mutex_get_tas_spins(self->db_env, &tas_spins); 5401 MYDB_END_ALLOW_THREADS; 5402 5403 RETURN_IF_ERR(); 5404 5405 return NUMBER_FromLong(tas_spins); 5406 } 5407 #endif 5408 5409 static PyObject* 5410 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args) 5411 { 5412 int err; 5413 char *dir; 5414 5415 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir)) 5416 return NULL; 5417 CHECK_ENV_NOT_CLOSED(self); 5418 5419 MYDB_BEGIN_ALLOW_THREADS; 5420 err = self->db_env->set_data_dir(self->db_env, dir); 5421 MYDB_END_ALLOW_THREADS; 5422 RETURN_IF_ERR(); 5423 RETURN_NONE(); 5424 } 5425 5426 #if (DBVER >= 42) 5427 static PyObject* 5428 DBEnv_get_data_dirs(DBEnvObject* self) 5429 { 5430 int err; 5431 PyObject *tuple; 5432 PyObject *item; 5433 const char **dirpp; 5434 int size, i; 5435 5436 CHECK_ENV_NOT_CLOSED(self); 5437 5438 MYDB_BEGIN_ALLOW_THREADS; 5439 err = self->db_env->get_data_dirs(self->db_env, &dirpp); 5440 MYDB_END_ALLOW_THREADS; 5441 5442 RETURN_IF_ERR(); 5443 5444 /* 5445 ** Calculate size. Python C API 5446 ** actually allows for tuple resizing, 5447 ** but this is simple enough. 5448 */ 5449 for (size=0; *(dirpp+size) ; size++); 5450 5451 tuple = PyTuple_New(size); 5452 if (!tuple) 5453 return NULL; 5454 5455 for (i=0; i<size; i++) { 5456 item = PyBytes_FromString (*(dirpp+i)); 5457 if (item == NULL) { 5458 Py_DECREF(tuple); 5459 tuple = NULL; 5460 break; 5461 } 5462 PyTuple_SET_ITEM(tuple, i, item); 5463 } 5464 return tuple; 5465 } 5466 #endif 5467 5468 #if (DBVER >= 44) 5469 static PyObject* 5470 DBEnv_set_lg_filemode(DBEnvObject* self, PyObject* args) 5471 { 5472 int err, filemode; 5473 5474 if (!PyArg_ParseTuple(args, "i:set_lg_filemode", &filemode)) 5475 return NULL; 5476 CHECK_ENV_NOT_CLOSED(self); 5477 5478 MYDB_BEGIN_ALLOW_THREADS; 5479 err = self->db_env->set_lg_filemode(self->db_env, filemode); 5480 MYDB_END_ALLOW_THREADS; 5481 RETURN_IF_ERR(); 5482 RETURN_NONE(); 5483 } 5484 5485 static PyObject* 5486 DBEnv_get_lg_filemode(DBEnvObject* self) 5487 { 5488 int err, filemode; 5489 5490 CHECK_ENV_NOT_CLOSED(self); 5491 5492 MYDB_BEGIN_ALLOW_THREADS; 5493 err = self->db_env->get_lg_filemode(self->db_env, &filemode); 5494 MYDB_END_ALLOW_THREADS; 5495 RETURN_IF_ERR(); 5496 return NUMBER_FromLong(filemode); 5497 } 5498 #endif 5499 5500 static PyObject* 5501 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args) 5502 { 5503 int err, lg_bsize; 5504 5505 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize)) 5506 return NULL; 5507 CHECK_ENV_NOT_CLOSED(self); 5508 5509 MYDB_BEGIN_ALLOW_THREADS; 5510 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize); 5511 MYDB_END_ALLOW_THREADS; 5512 RETURN_IF_ERR(); 5513 RETURN_NONE(); 5514 } 5515 5516 #if (DBVER >= 42) 5517 static PyObject* 5518 DBEnv_get_lg_bsize(DBEnvObject* self) 5519 { 5520 int err; 5521 u_int32_t lg_bsize; 5522 5523 CHECK_ENV_NOT_CLOSED(self); 5524 5525 MYDB_BEGIN_ALLOW_THREADS; 5526 err = self->db_env->get_lg_bsize(self->db_env, &lg_bsize); 5527 MYDB_END_ALLOW_THREADS; 5528 RETURN_IF_ERR(); 5529 return NUMBER_FromLong(lg_bsize); 5530 } 5531 #endif 5532 5533 static PyObject* 5534 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args) 5535 { 5536 int err; 5537 char *dir; 5538 5539 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir)) 5540 return NULL; 5541 CHECK_ENV_NOT_CLOSED(self); 5542 5543 MYDB_BEGIN_ALLOW_THREADS; 5544 err = self->db_env->set_lg_dir(self->db_env, dir); 5545 MYDB_END_ALLOW_THREADS; 5546 RETURN_IF_ERR(); 5547 RETURN_NONE(); 5548 } 5549 5550 #if (DBVER >= 42) 5551 static PyObject* 5552 DBEnv_get_lg_dir(DBEnvObject* self) 5553 { 5554 int err; 5555 const char *dirp; 5556 5557 CHECK_ENV_NOT_CLOSED(self); 5558 5559 MYDB_BEGIN_ALLOW_THREADS; 5560 err = self->db_env->get_lg_dir(self->db_env, &dirp); 5561 MYDB_END_ALLOW_THREADS; 5562 RETURN_IF_ERR(); 5563 return PyBytes_FromString(dirp); 5564 } 5565 #endif 5566 5567 static PyObject* 5568 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args) 5569 { 5570 int err, lg_max; 5571 5572 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max)) 5573 return NULL; 5574 CHECK_ENV_NOT_CLOSED(self); 5575 5576 MYDB_BEGIN_ALLOW_THREADS; 5577 err = self->db_env->set_lg_max(self->db_env, lg_max); 5578 MYDB_END_ALLOW_THREADS; 5579 RETURN_IF_ERR(); 5580 RETURN_NONE(); 5581 } 5582 5583 #if (DBVER >= 42) 5584 static PyObject* 5585 DBEnv_get_lg_max(DBEnvObject* self) 5586 { 5587 int err; 5588 u_int32_t lg_max; 5589 5590 CHECK_ENV_NOT_CLOSED(self); 5591 5592 MYDB_BEGIN_ALLOW_THREADS; 5593 err = self->db_env->get_lg_max(self->db_env, &lg_max); 5594 MYDB_END_ALLOW_THREADS; 5595 RETURN_IF_ERR(); 5596 return NUMBER_FromLong(lg_max); 5597 } 5598 #endif 5599 5600 5601 static PyObject* 5602 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args) 5603 { 5604 int err, lg_max; 5605 5606 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max)) 5607 return NULL; 5608 CHECK_ENV_NOT_CLOSED(self); 5609 5610 MYDB_BEGIN_ALLOW_THREADS; 5611 err = self->db_env->set_lg_regionmax(self->db_env, lg_max); 5612 MYDB_END_ALLOW_THREADS; 5613 RETURN_IF_ERR(); 5614 RETURN_NONE(); 5615 } 5616 5617 #if (DBVER >= 42) 5618 static PyObject* 5619 DBEnv_get_lg_regionmax(DBEnvObject* self) 5620 { 5621 int err; 5622 u_int32_t lg_regionmax; 5623 5624 CHECK_ENV_NOT_CLOSED(self); 5625 5626 MYDB_BEGIN_ALLOW_THREADS; 5627 err = self->db_env->get_lg_regionmax(self->db_env, &lg_regionmax); 5628 MYDB_END_ALLOW_THREADS; 5629 RETURN_IF_ERR(); 5630 return NUMBER_FromLong(lg_regionmax); 5631 } 5632 #endif 5633 5634 #if (DBVER >= 47) 5635 static PyObject* 5636 DBEnv_set_lk_partitions(DBEnvObject* self, PyObject* args) 5637 { 5638 int err, lk_partitions; 5639 5640 if (!PyArg_ParseTuple(args, "i:set_lk_partitions", &lk_partitions)) 5641 return NULL; 5642 CHECK_ENV_NOT_CLOSED(self); 5643 5644 MYDB_BEGIN_ALLOW_THREADS; 5645 err = self->db_env->set_lk_partitions(self->db_env, lk_partitions); 5646 MYDB_END_ALLOW_THREADS; 5647 RETURN_IF_ERR(); 5648 RETURN_NONE(); 5649 } 5650 5651 static PyObject* 5652 DBEnv_get_lk_partitions(DBEnvObject* self) 5653 { 5654 int err; 5655 u_int32_t lk_partitions; 5656 5657 CHECK_ENV_NOT_CLOSED(self); 5658 5659 MYDB_BEGIN_ALLOW_THREADS; 5660 err = self->db_env->get_lk_partitions(self->db_env, &lk_partitions); 5661 MYDB_END_ALLOW_THREADS; 5662 RETURN_IF_ERR(); 5663 return NUMBER_FromLong(lk_partitions); 5664 } 5665 #endif 5666 5667 static PyObject* 5668 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args) 5669 { 5670 int err, lk_detect; 5671 5672 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect)) 5673 return NULL; 5674 CHECK_ENV_NOT_CLOSED(self); 5675 5676 MYDB_BEGIN_ALLOW_THREADS; 5677 err = self->db_env->set_lk_detect(self->db_env, lk_detect); 5678 MYDB_END_ALLOW_THREADS; 5679 RETURN_IF_ERR(); 5680 RETURN_NONE(); 5681 } 5682 5683 #if (DBVER >= 42) 5684 static PyObject* 5685 DBEnv_get_lk_detect(DBEnvObject* self) 5686 { 5687 int err; 5688 u_int32_t lk_detect; 5689 5690 CHECK_ENV_NOT_CLOSED(self); 5691 5692 MYDB_BEGIN_ALLOW_THREADS; 5693 err = self->db_env->get_lk_detect(self->db_env, &lk_detect); 5694 MYDB_END_ALLOW_THREADS; 5695 RETURN_IF_ERR(); 5696 return NUMBER_FromLong(lk_detect); 5697 } 5698 #endif 5699 5700 5701 #if (DBVER < 45) 5702 static PyObject* 5703 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args) 5704 { 5705 int err, max; 5706 5707 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max)) 5708 return NULL; 5709 CHECK_ENV_NOT_CLOSED(self); 5710 5711 MYDB_BEGIN_ALLOW_THREADS; 5712 err = self->db_env->set_lk_max(self->db_env, max); 5713 MYDB_END_ALLOW_THREADS; 5714 RETURN_IF_ERR(); 5715 RETURN_NONE(); 5716 } 5717 #endif 5718 5719 5720 5721 static PyObject* 5722 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args) 5723 { 5724 int err, max; 5725 5726 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max)) 5727 return NULL; 5728 CHECK_ENV_NOT_CLOSED(self); 5729 5730 MYDB_BEGIN_ALLOW_THREADS; 5731 err = self->db_env->set_lk_max_locks(self->db_env, max); 5732 MYDB_END_ALLOW_THREADS; 5733 RETURN_IF_ERR(); 5734 RETURN_NONE(); 5735 } 5736 5737 #if (DBVER >= 42) 5738 static PyObject* 5739 DBEnv_get_lk_max_locks(DBEnvObject* self) 5740 { 5741 int err; 5742 u_int32_t lk_max; 5743 5744 CHECK_ENV_NOT_CLOSED(self); 5745 5746 MYDB_BEGIN_ALLOW_THREADS; 5747 err = self->db_env->get_lk_max_locks(self->db_env, &lk_max); 5748 MYDB_END_ALLOW_THREADS; 5749 RETURN_IF_ERR(); 5750 return NUMBER_FromLong(lk_max); 5751 } 5752 #endif 5753 5754 static PyObject* 5755 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args) 5756 { 5757 int err, max; 5758 5759 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max)) 5760 return NULL; 5761 CHECK_ENV_NOT_CLOSED(self); 5762 5763 MYDB_BEGIN_ALLOW_THREADS; 5764 err = self->db_env->set_lk_max_lockers(self->db_env, max); 5765 MYDB_END_ALLOW_THREADS; 5766 RETURN_IF_ERR(); 5767 RETURN_NONE(); 5768 } 5769 5770 #if (DBVER >= 42) 5771 static PyObject* 5772 DBEnv_get_lk_max_lockers(DBEnvObject* self) 5773 { 5774 int err; 5775 u_int32_t lk_max; 5776 5777 CHECK_ENV_NOT_CLOSED(self); 5778 5779 MYDB_BEGIN_ALLOW_THREADS; 5780 err = self->db_env->get_lk_max_lockers(self->db_env, &lk_max); 5781 MYDB_END_ALLOW_THREADS; 5782 RETURN_IF_ERR(); 5783 return NUMBER_FromLong(lk_max); 5784 } 5785 #endif 5786 5787 static PyObject* 5788 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args) 5789 { 5790 int err, max; 5791 5792 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max)) 5793 return NULL; 5794 CHECK_ENV_NOT_CLOSED(self); 5795 5796 MYDB_BEGIN_ALLOW_THREADS; 5797 err = self->db_env->set_lk_max_objects(self->db_env, max); 5798 MYDB_END_ALLOW_THREADS; 5799 RETURN_IF_ERR(); 5800 RETURN_NONE(); 5801 } 5802 5803 #if (DBVER >= 42) 5804 static PyObject* 5805 DBEnv_get_lk_max_objects(DBEnvObject* self) 5806 { 5807 int err; 5808 u_int32_t lk_max; 5809 5810 CHECK_ENV_NOT_CLOSED(self); 5811 5812 MYDB_BEGIN_ALLOW_THREADS; 5813 err = self->db_env->get_lk_max_objects(self->db_env, &lk_max); 5814 MYDB_END_ALLOW_THREADS; 5815 RETURN_IF_ERR(); 5816 return NUMBER_FromLong(lk_max); 5817 } 5818 #endif 5819 5820 #if (DBVER >= 42) 5821 static PyObject* 5822 DBEnv_get_mp_mmapsize(DBEnvObject* self) 5823 { 5824 int err; 5825 size_t mmapsize; 5826 5827 CHECK_ENV_NOT_CLOSED(self); 5828 5829 MYDB_BEGIN_ALLOW_THREADS; 5830 err = self->db_env->get_mp_mmapsize(self->db_env, &mmapsize); 5831 MYDB_END_ALLOW_THREADS; 5832 RETURN_IF_ERR(); 5833 return NUMBER_FromLong(mmapsize); 5834 } 5835 #endif 5836 5837 5838 static PyObject* 5839 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args) 5840 { 5841 int err, mp_mmapsize; 5842 5843 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize)) 5844 return NULL; 5845 CHECK_ENV_NOT_CLOSED(self); 5846 5847 MYDB_BEGIN_ALLOW_THREADS; 5848 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize); 5849 MYDB_END_ALLOW_THREADS; 5850 RETURN_IF_ERR(); 5851 RETURN_NONE(); 5852 } 5853 5854 5855 static PyObject* 5856 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args) 5857 { 5858 int err; 5859 char *dir; 5860 5861 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir)) 5862 return NULL; 5863 CHECK_ENV_NOT_CLOSED(self); 5864 5865 MYDB_BEGIN_ALLOW_THREADS; 5866 err = self->db_env->set_tmp_dir(self->db_env, dir); 5867 MYDB_END_ALLOW_THREADS; 5868 RETURN_IF_ERR(); 5869 RETURN_NONE(); 5870 } 5871 5872 5873 #if (DBVER >= 42) 5874 static PyObject* 5875 DBEnv_get_tmp_dir(DBEnvObject* self) 5876 { 5877 int err; 5878 const char *dirpp; 5879 5880 CHECK_ENV_NOT_CLOSED(self); 5881 5882 MYDB_BEGIN_ALLOW_THREADS; 5883 err = self->db_env->get_tmp_dir(self->db_env, &dirpp); 5884 MYDB_END_ALLOW_THREADS; 5885 5886 RETURN_IF_ERR(); 5887 5888 return PyBytes_FromString(dirpp); 5889 } 5890 #endif 5891 5892 5893 static PyObject* 5894 DBEnv_txn_recover(DBEnvObject* self) 5895 { 5896 int flags = DB_FIRST; 5897 int err, i; 5898 PyObject *list, *tuple, *gid; 5899 DBTxnObject *txn; 5900 #define PREPLIST_LEN 16 5901 DB_PREPLIST preplist[PREPLIST_LEN]; 5902 #if (DBVER < 48) 5903 long retp; 5904 #else 5905 u_int32_t retp; 5906 #endif 5907 5908 CHECK_ENV_NOT_CLOSED(self); 5909 5910 list=PyList_New(0); 5911 if (!list) 5912 return NULL; 5913 while (!0) { 5914 MYDB_BEGIN_ALLOW_THREADS 5915 err=self->db_env->txn_recover(self->db_env, 5916 preplist, PREPLIST_LEN, &retp, flags); 5917 #undef PREPLIST_LEN 5918 MYDB_END_ALLOW_THREADS 5919 if (err) { 5920 Py_DECREF(list); 5921 RETURN_IF_ERR(); 5922 } 5923 if (!retp) break; 5924 flags=DB_NEXT; /* Prepare for next loop pass */ 5925 for (i=0; i<retp; i++) { 5926 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid), 5927 DB_GID_SIZE); 5928 if (!gid) { 5929 Py_DECREF(list); 5930 return NULL; 5931 } 5932 txn=newDBTxnObject(self, NULL, preplist[i].txn, 0); 5933 if (!txn) { 5934 Py_DECREF(list); 5935 Py_DECREF(gid); 5936 return NULL; 5937 } 5938 txn->flag_prepare=1; /* Recover state */ 5939 tuple=PyTuple_New(2); 5940 if (!tuple) { 5941 Py_DECREF(list); 5942 Py_DECREF(gid); 5943 Py_DECREF(txn); 5944 return NULL; 5945 } 5946 if (PyTuple_SetItem(tuple, 0, gid)) { 5947 Py_DECREF(list); 5948 Py_DECREF(gid); 5949 Py_DECREF(txn); 5950 Py_DECREF(tuple); 5951 return NULL; 5952 } 5953 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) { 5954 Py_DECREF(list); 5955 Py_DECREF(txn); 5956 Py_DECREF(tuple); /* This delete the "gid" also */ 5957 return NULL; 5958 } 5959 if (PyList_Append(list, tuple)) { 5960 Py_DECREF(list); 5961 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */ 5962 return NULL; 5963 } 5964 Py_DECREF(tuple); 5965 } 5966 } 5967 return list; 5968 } 5969 5970 static PyObject* 5971 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs) 5972 { 5973 int flags = 0; 5974 PyObject* txnobj = NULL; 5975 DB_TXN *txn = NULL; 5976 static char* kwnames[] = { "parent", "flags", NULL }; 5977 5978 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames, 5979 &txnobj, &flags)) 5980 return NULL; 5981 5982 if (!checkTxnObj(txnobj, &txn)) 5983 return NULL; 5984 CHECK_ENV_NOT_CLOSED(self); 5985 5986 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags); 5987 } 5988 5989 5990 static PyObject* 5991 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args) 5992 { 5993 int err, kbyte=0, min=0, flags=0; 5994 5995 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags)) 5996 return NULL; 5997 CHECK_ENV_NOT_CLOSED(self); 5998 5999 MYDB_BEGIN_ALLOW_THREADS; 6000 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags); 6001 MYDB_END_ALLOW_THREADS; 6002 RETURN_IF_ERR(); 6003 RETURN_NONE(); 6004 } 6005 6006 6007 #if (DBVER >= 42) 6008 static PyObject* 6009 DBEnv_get_tx_max(DBEnvObject* self) 6010 { 6011 int err; 6012 u_int32_t max; 6013 6014 CHECK_ENV_NOT_CLOSED(self); 6015 6016 MYDB_BEGIN_ALLOW_THREADS; 6017 err = self->db_env->get_tx_max(self->db_env, &max); 6018 MYDB_END_ALLOW_THREADS; 6019 RETURN_IF_ERR(); 6020 return PyLong_FromUnsignedLong(max); 6021 } 6022 #endif 6023 6024 6025 static PyObject* 6026 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args) 6027 { 6028 int err, max; 6029 6030 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max)) 6031 return NULL; 6032 CHECK_ENV_NOT_CLOSED(self); 6033 6034 MYDB_BEGIN_ALLOW_THREADS; 6035 err = self->db_env->set_tx_max(self->db_env, max); 6036 MYDB_END_ALLOW_THREADS; 6037 RETURN_IF_ERR(); 6038 RETURN_NONE(); 6039 } 6040 6041 6042 #if (DBVER >= 42) 6043 static PyObject* 6044 DBEnv_get_tx_timestamp(DBEnvObject* self) 6045 { 6046 int err; 6047 time_t timestamp; 6048 6049 CHECK_ENV_NOT_CLOSED(self); 6050 6051 MYDB_BEGIN_ALLOW_THREADS; 6052 err = self->db_env->get_tx_timestamp(self->db_env, &timestamp); 6053 MYDB_END_ALLOW_THREADS; 6054 RETURN_IF_ERR(); 6055 return NUMBER_FromLong(timestamp); 6056 } 6057 #endif 6058 6059 static PyObject* 6060 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args) 6061 { 6062 int err; 6063 long stamp; 6064 time_t timestamp; 6065 6066 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp)) 6067 return NULL; 6068 CHECK_ENV_NOT_CLOSED(self); 6069 timestamp = (time_t)stamp; 6070 MYDB_BEGIN_ALLOW_THREADS; 6071 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp); 6072 MYDB_END_ALLOW_THREADS; 6073 RETURN_IF_ERR(); 6074 RETURN_NONE(); 6075 } 6076 6077 6078 static PyObject* 6079 DBEnv_lock_detect(DBEnvObject* self, PyObject* args) 6080 { 6081 int err, atype, flags=0; 6082 int aborted = 0; 6083 6084 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags)) 6085 return NULL; 6086 CHECK_ENV_NOT_CLOSED(self); 6087 6088 MYDB_BEGIN_ALLOW_THREADS; 6089 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted); 6090 MYDB_END_ALLOW_THREADS; 6091 RETURN_IF_ERR(); 6092 return NUMBER_FromLong(aborted); 6093 } 6094 6095 6096 static PyObject* 6097 DBEnv_lock_get(DBEnvObject* self, PyObject* args) 6098 { 6099 int flags=0; 6100 int locker, lock_mode; 6101 DBT obj; 6102 PyObject* objobj; 6103 6104 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags)) 6105 return NULL; 6106 6107 6108 if (!make_dbt(objobj, &obj)) 6109 return NULL; 6110 6111 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags); 6112 } 6113 6114 6115 static PyObject* 6116 DBEnv_lock_id(DBEnvObject* self) 6117 { 6118 int err; 6119 u_int32_t theID; 6120 6121 CHECK_ENV_NOT_CLOSED(self); 6122 MYDB_BEGIN_ALLOW_THREADS; 6123 err = self->db_env->lock_id(self->db_env, &theID); 6124 MYDB_END_ALLOW_THREADS; 6125 RETURN_IF_ERR(); 6126 6127 return NUMBER_FromLong((long)theID); 6128 } 6129 6130 static PyObject* 6131 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args) 6132 { 6133 int err; 6134 u_int32_t theID; 6135 6136 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID)) 6137 return NULL; 6138 6139 CHECK_ENV_NOT_CLOSED(self); 6140 MYDB_BEGIN_ALLOW_THREADS; 6141 err = self->db_env->lock_id_free(self->db_env, theID); 6142 MYDB_END_ALLOW_THREADS; 6143 RETURN_IF_ERR(); 6144 RETURN_NONE(); 6145 } 6146 6147 static PyObject* 6148 DBEnv_lock_put(DBEnvObject* self, PyObject* args) 6149 { 6150 int err; 6151 DBLockObject* dblockobj; 6152 6153 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj)) 6154 return NULL; 6155 6156 CHECK_ENV_NOT_CLOSED(self); 6157 MYDB_BEGIN_ALLOW_THREADS; 6158 err = self->db_env->lock_put(self->db_env, &dblockobj->lock); 6159 MYDB_END_ALLOW_THREADS; 6160 RETURN_IF_ERR(); 6161 RETURN_NONE(); 6162 } 6163 6164 #if (DBVER >= 44) 6165 static PyObject* 6166 DBEnv_fileid_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs) 6167 { 6168 int err; 6169 char *file; 6170 u_int32_t flags = 0; 6171 static char* kwnames[] = { "file", "flags", NULL}; 6172 6173 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:fileid_reset", kwnames, 6174 &file, &flags)) 6175 return NULL; 6176 CHECK_ENV_NOT_CLOSED(self); 6177 6178 MYDB_BEGIN_ALLOW_THREADS; 6179 err = self->db_env->fileid_reset(self->db_env, file, flags); 6180 MYDB_END_ALLOW_THREADS; 6181 RETURN_IF_ERR(); 6182 RETURN_NONE(); 6183 } 6184 6185 static PyObject* 6186 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs) 6187 { 6188 int err; 6189 char *file; 6190 u_int32_t flags = 0; 6191 static char* kwnames[] = { "file", "flags", NULL}; 6192 6193 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames, 6194 &file, &flags)) 6195 return NULL; 6196 CHECK_ENV_NOT_CLOSED(self); 6197 6198 MYDB_BEGIN_ALLOW_THREADS; 6199 err = self->db_env->lsn_reset(self->db_env, file, flags); 6200 MYDB_END_ALLOW_THREADS; 6201 RETURN_IF_ERR(); 6202 RETURN_NONE(); 6203 } 6204 #endif /* DBVER >= 4.4 */ 6205 6206 6207 #if (DBVER >= 43) 6208 static PyObject* 6209 DBEnv_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 6210 { 6211 int err; 6212 int flags=0; 6213 static char* kwnames[] = { "flags", NULL }; 6214 6215 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print", 6216 kwnames, &flags)) 6217 { 6218 return NULL; 6219 } 6220 CHECK_ENV_NOT_CLOSED(self); 6221 MYDB_BEGIN_ALLOW_THREADS; 6222 err = self->db_env->stat_print(self->db_env, flags); 6223 MYDB_END_ALLOW_THREADS; 6224 RETURN_IF_ERR(); 6225 RETURN_NONE(); 6226 } 6227 #endif 6228 6229 6230 static PyObject* 6231 DBEnv_log_stat(DBEnvObject* self, PyObject* args) 6232 { 6233 int err; 6234 DB_LOG_STAT* statp = NULL; 6235 PyObject* d = NULL; 6236 u_int32_t flags = 0; 6237 6238 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags)) 6239 return NULL; 6240 CHECK_ENV_NOT_CLOSED(self); 6241 6242 MYDB_BEGIN_ALLOW_THREADS; 6243 err = self->db_env->log_stat(self->db_env, &statp, flags); 6244 MYDB_END_ALLOW_THREADS; 6245 RETURN_IF_ERR(); 6246 6247 /* Turn the stat structure into a dictionary */ 6248 d = PyDict_New(); 6249 if (d == NULL) { 6250 if (statp) 6251 free(statp); 6252 return NULL; 6253 } 6254 6255 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name) 6256 6257 MAKE_ENTRY(magic); 6258 MAKE_ENTRY(version); 6259 MAKE_ENTRY(mode); 6260 MAKE_ENTRY(lg_bsize); 6261 #if (DBVER >= 44) 6262 MAKE_ENTRY(lg_size); 6263 MAKE_ENTRY(record); 6264 #endif 6265 MAKE_ENTRY(w_mbytes); 6266 MAKE_ENTRY(w_bytes); 6267 MAKE_ENTRY(wc_mbytes); 6268 MAKE_ENTRY(wc_bytes); 6269 MAKE_ENTRY(wcount); 6270 MAKE_ENTRY(wcount_fill); 6271 #if (DBVER >= 44) 6272 MAKE_ENTRY(rcount); 6273 #endif 6274 MAKE_ENTRY(scount); 6275 MAKE_ENTRY(cur_file); 6276 MAKE_ENTRY(cur_offset); 6277 MAKE_ENTRY(disk_file); 6278 MAKE_ENTRY(disk_offset); 6279 MAKE_ENTRY(maxcommitperflush); 6280 MAKE_ENTRY(mincommitperflush); 6281 MAKE_ENTRY(regsize); 6282 MAKE_ENTRY(region_wait); 6283 MAKE_ENTRY(region_nowait); 6284 6285 #undef MAKE_ENTRY 6286 free(statp); 6287 return d; 6288 } /* DBEnv_log_stat */ 6289 6290 6291 #if (DBVER >= 43) 6292 static PyObject* 6293 DBEnv_log_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 6294 { 6295 int err; 6296 int flags=0; 6297 static char* kwnames[] = { "flags", NULL }; 6298 6299 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:log_stat_print", 6300 kwnames, &flags)) 6301 { 6302 return NULL; 6303 } 6304 CHECK_ENV_NOT_CLOSED(self); 6305 MYDB_BEGIN_ALLOW_THREADS; 6306 err = self->db_env->log_stat_print(self->db_env, flags); 6307 MYDB_END_ALLOW_THREADS; 6308 RETURN_IF_ERR(); 6309 RETURN_NONE(); 6310 } 6311 #endif 6312 6313 6314 static PyObject* 6315 DBEnv_lock_stat(DBEnvObject* self, PyObject* args) 6316 { 6317 int err; 6318 DB_LOCK_STAT* sp; 6319 PyObject* d = NULL; 6320 u_int32_t flags = 0; 6321 6322 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags)) 6323 return NULL; 6324 CHECK_ENV_NOT_CLOSED(self); 6325 6326 MYDB_BEGIN_ALLOW_THREADS; 6327 err = self->db_env->lock_stat(self->db_env, &sp, flags); 6328 MYDB_END_ALLOW_THREADS; 6329 RETURN_IF_ERR(); 6330 6331 /* Turn the stat structure into a dictionary */ 6332 d = PyDict_New(); 6333 if (d == NULL) { 6334 free(sp); 6335 return NULL; 6336 } 6337 6338 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) 6339 6340 MAKE_ENTRY(id); 6341 MAKE_ENTRY(cur_maxid); 6342 MAKE_ENTRY(nmodes); 6343 MAKE_ENTRY(maxlocks); 6344 MAKE_ENTRY(maxlockers); 6345 MAKE_ENTRY(maxobjects); 6346 MAKE_ENTRY(nlocks); 6347 MAKE_ENTRY(maxnlocks); 6348 MAKE_ENTRY(nlockers); 6349 MAKE_ENTRY(maxnlockers); 6350 MAKE_ENTRY(nobjects); 6351 MAKE_ENTRY(maxnobjects); 6352 MAKE_ENTRY(nrequests); 6353 MAKE_ENTRY(nreleases); 6354 #if (DBVER >= 44) 6355 MAKE_ENTRY(nupgrade); 6356 MAKE_ENTRY(ndowngrade); 6357 #endif 6358 #if (DBVER < 44) 6359 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */ 6360 MAKE_ENTRY(nconflicts); 6361 #else 6362 MAKE_ENTRY(lock_nowait); 6363 MAKE_ENTRY(lock_wait); 6364 #endif 6365 MAKE_ENTRY(ndeadlocks); 6366 MAKE_ENTRY(locktimeout); 6367 MAKE_ENTRY(txntimeout); 6368 MAKE_ENTRY(nlocktimeouts); 6369 MAKE_ENTRY(ntxntimeouts); 6370 #if (DBVER >= 46) 6371 MAKE_ENTRY(objs_wait); 6372 MAKE_ENTRY(objs_nowait); 6373 MAKE_ENTRY(lockers_wait); 6374 MAKE_ENTRY(lockers_nowait); 6375 #if (DBVER >= 47) 6376 MAKE_ENTRY(lock_wait); 6377 MAKE_ENTRY(lock_nowait); 6378 #else 6379 MAKE_ENTRY(locks_wait); 6380 MAKE_ENTRY(locks_nowait); 6381 #endif 6382 MAKE_ENTRY(hash_len); 6383 #endif 6384 MAKE_ENTRY(regsize); 6385 MAKE_ENTRY(region_wait); 6386 MAKE_ENTRY(region_nowait); 6387 6388 #undef MAKE_ENTRY 6389 free(sp); 6390 return d; 6391 } 6392 6393 #if (DBVER >= 43) 6394 static PyObject* 6395 DBEnv_lock_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 6396 { 6397 int err; 6398 int flags=0; 6399 static char* kwnames[] = { "flags", NULL }; 6400 6401 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:lock_stat_print", 6402 kwnames, &flags)) 6403 { 6404 return NULL; 6405 } 6406 CHECK_ENV_NOT_CLOSED(self); 6407 MYDB_BEGIN_ALLOW_THREADS; 6408 err = self->db_env->lock_stat_print(self->db_env, flags); 6409 MYDB_END_ALLOW_THREADS; 6410 RETURN_IF_ERR(); 6411 RETURN_NONE(); 6412 } 6413 #endif 6414 6415 6416 static PyObject* 6417 DBEnv_log_cursor(DBEnvObject* self) 6418 { 6419 int err; 6420 DB_LOGC* dblogc; 6421 6422 CHECK_ENV_NOT_CLOSED(self); 6423 6424 MYDB_BEGIN_ALLOW_THREADS; 6425 err = self->db_env->log_cursor(self->db_env, &dblogc, 0); 6426 MYDB_END_ALLOW_THREADS; 6427 RETURN_IF_ERR(); 6428 return (PyObject*) newDBLogCursorObject(dblogc, self); 6429 } 6430 6431 6432 static PyObject* 6433 DBEnv_log_flush(DBEnvObject* self) 6434 { 6435 int err; 6436 6437 CHECK_ENV_NOT_CLOSED(self); 6438 6439 MYDB_BEGIN_ALLOW_THREADS 6440 err = self->db_env->log_flush(self->db_env, NULL); 6441 MYDB_END_ALLOW_THREADS 6442 6443 RETURN_IF_ERR(); 6444 RETURN_NONE(); 6445 } 6446 6447 static PyObject* 6448 DBEnv_log_file(DBEnvObject* self, PyObject* args) 6449 { 6450 int err; 6451 DB_LSN lsn = {0, 0}; 6452 int size = 20; 6453 char *name = NULL; 6454 PyObject *retval; 6455 6456 if (!PyArg_ParseTuple(args, "(ii):log_file", &lsn.file, &lsn.offset)) 6457 return NULL; 6458 6459 CHECK_ENV_NOT_CLOSED(self); 6460 6461 do { 6462 name = malloc(size); 6463 if (!name) { 6464 PyErr_NoMemory(); 6465 return NULL; 6466 } 6467 MYDB_BEGIN_ALLOW_THREADS; 6468 err = self->db_env->log_file(self->db_env, &lsn, name, size); 6469 MYDB_END_ALLOW_THREADS; 6470 if (err == EINVAL) { 6471 free(name); 6472 size *= 2; 6473 } else if (err) { 6474 free(name); 6475 RETURN_IF_ERR(); 6476 assert(0); /* Unreachable... supposely */ 6477 return NULL; 6478 } 6479 /* 6480 ** If the final buffer we try is too small, we will 6481 ** get this exception: 6482 ** DBInvalidArgError: 6483 ** (22, 'Invalid argument -- DB_ENV->log_file: name buffer is too short') 6484 */ 6485 } while ((err == EINVAL) && (size<(1<<17))); 6486 6487 RETURN_IF_ERR(); /* Maybe the size is not the problem */ 6488 6489 retval = Py_BuildValue("s", name); 6490 free(name); 6491 return retval; 6492 } 6493 6494 6495 #if (DBVER >= 44) 6496 static PyObject* 6497 DBEnv_log_printf(DBEnvObject* self, PyObject* args, PyObject *kwargs) 6498 { 6499 int err; 6500 char *string; 6501 PyObject *txnobj = NULL; 6502 DB_TXN *txn = NULL; 6503 static char* kwnames[] = {"string", "txn", NULL }; 6504 6505 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|O:log_printf", kwnames, 6506 &string, &txnobj)) 6507 return NULL; 6508 6509 CHECK_ENV_NOT_CLOSED(self); 6510 6511 if (!checkTxnObj(txnobj, &txn)) 6512 return NULL; 6513 6514 /* 6515 ** Do not use the format string directly, to avoid attacks. 6516 */ 6517 MYDB_BEGIN_ALLOW_THREADS; 6518 err = self->db_env->log_printf(self->db_env, txn, "%s", string); 6519 MYDB_END_ALLOW_THREADS; 6520 6521 RETURN_IF_ERR(); 6522 RETURN_NONE(); 6523 } 6524 #endif 6525 6526 6527 static PyObject* 6528 DBEnv_log_archive(DBEnvObject* self, PyObject* args) 6529 { 6530 int flags=0; 6531 int err; 6532 char **log_list = NULL; 6533 PyObject* list; 6534 PyObject* item = NULL; 6535 6536 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags)) 6537 return NULL; 6538 6539 CHECK_ENV_NOT_CLOSED(self); 6540 MYDB_BEGIN_ALLOW_THREADS; 6541 err = self->db_env->log_archive(self->db_env, &log_list, flags); 6542 MYDB_END_ALLOW_THREADS; 6543 RETURN_IF_ERR(); 6544 6545 list = PyList_New(0); 6546 if (list == NULL) { 6547 if (log_list) 6548 free(log_list); 6549 return NULL; 6550 } 6551 6552 if (log_list) { 6553 char **log_list_start; 6554 for (log_list_start = log_list; *log_list != NULL; ++log_list) { 6555 item = PyBytes_FromString (*log_list); 6556 if (item == NULL) { 6557 Py_DECREF(list); 6558 list = NULL; 6559 break; 6560 } 6561 if (PyList_Append(list, item)) { 6562 Py_DECREF(list); 6563 list = NULL; 6564 Py_DECREF(item); 6565 break; 6566 } 6567 Py_DECREF(item); 6568 } 6569 free(log_list_start); 6570 } 6571 return list; 6572 } 6573 6574 6575 #if (DBVER >= 44) 6576 static PyObject* 6577 DBEnv_mutex_stat(DBEnvObject* self, PyObject* args) 6578 { 6579 int err; 6580 DB_MUTEX_STAT* statp = NULL; 6581 PyObject* d = NULL; 6582 u_int32_t flags = 0; 6583 6584 if (!PyArg_ParseTuple(args, "|i:mutex_stat", &flags)) 6585 return NULL; 6586 CHECK_ENV_NOT_CLOSED(self); 6587 6588 MYDB_BEGIN_ALLOW_THREADS; 6589 err = self->db_env->mutex_stat(self->db_env, &statp, flags); 6590 MYDB_END_ALLOW_THREADS; 6591 RETURN_IF_ERR(); 6592 6593 /* Turn the stat structure into a dictionary */ 6594 d = PyDict_New(); 6595 if (d == NULL) { 6596 if (statp) 6597 free(statp); 6598 return NULL; 6599 } 6600 6601 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name) 6602 6603 MAKE_ENTRY(mutex_align); 6604 MAKE_ENTRY(mutex_tas_spins); 6605 MAKE_ENTRY(mutex_cnt); 6606 MAKE_ENTRY(mutex_free); 6607 MAKE_ENTRY(mutex_inuse); 6608 MAKE_ENTRY(mutex_inuse_max); 6609 MAKE_ENTRY(regsize); 6610 MAKE_ENTRY(region_wait); 6611 MAKE_ENTRY(region_nowait); 6612 6613 #undef MAKE_ENTRY 6614 free(statp); 6615 return d; 6616 } 6617 #endif 6618 6619 6620 #if (DBVER >= 44) 6621 static PyObject* 6622 DBEnv_mutex_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 6623 { 6624 int err; 6625 int flags=0; 6626 static char* kwnames[] = { "flags", NULL }; 6627 6628 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:mutex_stat_print", 6629 kwnames, &flags)) 6630 { 6631 return NULL; 6632 } 6633 CHECK_ENV_NOT_CLOSED(self); 6634 MYDB_BEGIN_ALLOW_THREADS; 6635 err = self->db_env->mutex_stat_print(self->db_env, flags); 6636 MYDB_END_ALLOW_THREADS; 6637 RETURN_IF_ERR(); 6638 RETURN_NONE(); 6639 } 6640 #endif 6641 6642 6643 #if (DBVER >= 43) 6644 static PyObject* 6645 DBEnv_txn_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 6646 { 6647 int err; 6648 int flags=0; 6649 static char* kwnames[] = { "flags", NULL }; 6650 6651 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print", 6652 kwnames, &flags)) 6653 { 6654 return NULL; 6655 } 6656 6657 CHECK_ENV_NOT_CLOSED(self); 6658 6659 MYDB_BEGIN_ALLOW_THREADS; 6660 err = self->db_env->txn_stat_print(self->db_env, flags); 6661 MYDB_END_ALLOW_THREADS; 6662 RETURN_IF_ERR(); 6663 RETURN_NONE(); 6664 } 6665 #endif 6666 6667 6668 static PyObject* 6669 DBEnv_txn_stat(DBEnvObject* self, PyObject* args) 6670 { 6671 int err; 6672 DB_TXN_STAT* sp; 6673 PyObject* d = NULL; 6674 u_int32_t flags=0; 6675 6676 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags)) 6677 return NULL; 6678 CHECK_ENV_NOT_CLOSED(self); 6679 6680 MYDB_BEGIN_ALLOW_THREADS; 6681 err = self->db_env->txn_stat(self->db_env, &sp, flags); 6682 MYDB_END_ALLOW_THREADS; 6683 RETURN_IF_ERR(); 6684 6685 /* Turn the stat structure into a dictionary */ 6686 d = PyDict_New(); 6687 if (d == NULL) { 6688 free(sp); 6689 return NULL; 6690 } 6691 6692 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) 6693 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name) 6694 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name) 6695 6696 MAKE_DB_LSN_ENTRY(last_ckp); 6697 MAKE_TIME_T_ENTRY(time_ckp); 6698 MAKE_ENTRY(last_txnid); 6699 MAKE_ENTRY(maxtxns); 6700 MAKE_ENTRY(nactive); 6701 MAKE_ENTRY(maxnactive); 6702 #if (DBVER >= 45) 6703 MAKE_ENTRY(nsnapshot); 6704 MAKE_ENTRY(maxnsnapshot); 6705 #endif 6706 MAKE_ENTRY(nbegins); 6707 MAKE_ENTRY(naborts); 6708 MAKE_ENTRY(ncommits); 6709 MAKE_ENTRY(nrestores); 6710 MAKE_ENTRY(regsize); 6711 MAKE_ENTRY(region_wait); 6712 MAKE_ENTRY(region_nowait); 6713 6714 #undef MAKE_DB_LSN_ENTRY 6715 #undef MAKE_ENTRY 6716 #undef MAKE_TIME_T_ENTRY 6717 free(sp); 6718 return d; 6719 } 6720 6721 6722 static PyObject* 6723 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args) 6724 { 6725 int flags=0; 6726 int oldValue=0; 6727 6728 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags)) 6729 return NULL; 6730 CHECK_ENV_NOT_CLOSED(self); 6731 6732 if (self->moduleFlags.getReturnsNone) 6733 ++oldValue; 6734 if (self->moduleFlags.cursorSetReturnsNone) 6735 ++oldValue; 6736 self->moduleFlags.getReturnsNone = (flags >= 1); 6737 self->moduleFlags.cursorSetReturnsNone = (flags >= 2); 6738 return NUMBER_FromLong(oldValue); 6739 } 6740 6741 static PyObject* 6742 DBEnv_get_private(DBEnvObject* self) 6743 { 6744 /* We can give out the private field even if dbenv is closed */ 6745 Py_INCREF(self->private_obj); 6746 return self->private_obj; 6747 } 6748 6749 static PyObject* 6750 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj) 6751 { 6752 /* We can set the private field even if dbenv is closed */ 6753 Py_DECREF(self->private_obj); 6754 Py_INCREF(private_obj); 6755 self->private_obj = private_obj; 6756 RETURN_NONE(); 6757 } 6758 6759 6760 #if (DBVER < 48) 6761 static PyObject* 6762 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs) 6763 { 6764 int err; 6765 char *host; 6766 long cl_timeout=0, sv_timeout=0; 6767 6768 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL}; 6769 6770 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames, 6771 &host, &cl_timeout, &sv_timeout)) 6772 return NULL; 6773 CHECK_ENV_NOT_CLOSED(self); 6774 6775 MYDB_BEGIN_ALLOW_THREADS; 6776 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout, 6777 sv_timeout, 0); 6778 MYDB_END_ALLOW_THREADS; 6779 RETURN_IF_ERR(); 6780 RETURN_NONE(); 6781 } 6782 #endif 6783 6784 #if (DBVER >= 43) 6785 static PyObject* 6786 DBEnv_set_mp_max_openfd(DBEnvObject* self, PyObject* args) 6787 { 6788 int err; 6789 int maxopenfd; 6790 6791 if (!PyArg_ParseTuple(args, "i:set_mp_max_openfd", &maxopenfd)) { 6792 return NULL; 6793 } 6794 CHECK_ENV_NOT_CLOSED(self); 6795 MYDB_BEGIN_ALLOW_THREADS; 6796 err = self->db_env->set_mp_max_openfd(self->db_env, maxopenfd); 6797 MYDB_END_ALLOW_THREADS; 6798 RETURN_IF_ERR(); 6799 RETURN_NONE(); 6800 } 6801 6802 static PyObject* 6803 DBEnv_get_mp_max_openfd(DBEnvObject* self) 6804 { 6805 int err; 6806 int maxopenfd; 6807 6808 CHECK_ENV_NOT_CLOSED(self); 6809 6810 MYDB_BEGIN_ALLOW_THREADS; 6811 err = self->db_env->get_mp_max_openfd(self->db_env, &maxopenfd); 6812 MYDB_END_ALLOW_THREADS; 6813 RETURN_IF_ERR(); 6814 return NUMBER_FromLong(maxopenfd); 6815 } 6816 6817 6818 static PyObject* 6819 DBEnv_set_mp_max_write(DBEnvObject* self, PyObject* args) 6820 { 6821 int err; 6822 int maxwrite, maxwrite_sleep; 6823 6824 if (!PyArg_ParseTuple(args, "ii:set_mp_max_write", &maxwrite, 6825 &maxwrite_sleep)) { 6826 return NULL; 6827 } 6828 CHECK_ENV_NOT_CLOSED(self); 6829 MYDB_BEGIN_ALLOW_THREADS; 6830 err = self->db_env->set_mp_max_write(self->db_env, maxwrite, 6831 maxwrite_sleep); 6832 MYDB_END_ALLOW_THREADS; 6833 RETURN_IF_ERR(); 6834 RETURN_NONE(); 6835 } 6836 6837 static PyObject* 6838 DBEnv_get_mp_max_write(DBEnvObject* self) 6839 { 6840 int err; 6841 int maxwrite; 6842 #if (DBVER >= 46) 6843 db_timeout_t maxwrite_sleep; 6844 #else 6845 int maxwrite_sleep; 6846 #endif 6847 6848 CHECK_ENV_NOT_CLOSED(self); 6849 6850 MYDB_BEGIN_ALLOW_THREADS; 6851 err = self->db_env->get_mp_max_write(self->db_env, &maxwrite, 6852 &maxwrite_sleep); 6853 MYDB_END_ALLOW_THREADS; 6854 RETURN_IF_ERR(); 6855 6856 return Py_BuildValue("(ii)", maxwrite, (int)maxwrite_sleep); 6857 } 6858 #endif 6859 6860 6861 static PyObject* 6862 DBEnv_set_verbose(DBEnvObject* self, PyObject* args) 6863 { 6864 int err; 6865 int which, onoff; 6866 6867 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) { 6868 return NULL; 6869 } 6870 CHECK_ENV_NOT_CLOSED(self); 6871 MYDB_BEGIN_ALLOW_THREADS; 6872 err = self->db_env->set_verbose(self->db_env, which, onoff); 6873 MYDB_END_ALLOW_THREADS; 6874 RETURN_IF_ERR(); 6875 RETURN_NONE(); 6876 } 6877 6878 #if (DBVER >= 42) 6879 static PyObject* 6880 DBEnv_get_verbose(DBEnvObject* self, PyObject* args) 6881 { 6882 int err; 6883 int which; 6884 int verbose; 6885 6886 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) { 6887 return NULL; 6888 } 6889 CHECK_ENV_NOT_CLOSED(self); 6890 MYDB_BEGIN_ALLOW_THREADS; 6891 err = self->db_env->get_verbose(self->db_env, which, &verbose); 6892 MYDB_END_ALLOW_THREADS; 6893 RETURN_IF_ERR(); 6894 return PyBool_FromLong(verbose); 6895 } 6896 #endif 6897 6898 #if (DBVER >= 45) 6899 static void 6900 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info) 6901 { 6902 DBEnvObject *dbenv; 6903 PyObject* callback; 6904 PyObject* args; 6905 PyObject* result = NULL; 6906 6907 MYDB_BEGIN_BLOCK_THREADS; 6908 dbenv = (DBEnvObject *)db_env->app_private; 6909 callback = dbenv->event_notifyCallback; 6910 if (callback) { 6911 if (event == DB_EVENT_REP_NEWMASTER) { 6912 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info)); 6913 } else { 6914 args = Py_BuildValue("(OiO)", dbenv, event, Py_None); 6915 } 6916 if (args) { 6917 result = PyEval_CallObject(callback, args); 6918 } 6919 if ((!args) || (!result)) { 6920 PyErr_Print(); 6921 } 6922 Py_XDECREF(args); 6923 Py_XDECREF(result); 6924 } 6925 MYDB_END_BLOCK_THREADS; 6926 } 6927 #endif 6928 6929 #if (DBVER >= 45) 6930 static PyObject* 6931 DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc) 6932 { 6933 int err; 6934 6935 CHECK_ENV_NOT_CLOSED(self); 6936 6937 if (!PyCallable_Check(notifyFunc)) { 6938 makeTypeError("Callable", notifyFunc); 6939 return NULL; 6940 } 6941 6942 Py_XDECREF(self->event_notifyCallback); 6943 Py_INCREF(notifyFunc); 6944 self->event_notifyCallback = notifyFunc; 6945 6946 /* This is to workaround a problem with un-initialized threads (see 6947 comment in DB_associate) */ 6948 #ifdef WITH_THREAD 6949 PyEval_InitThreads(); 6950 #endif 6951 6952 MYDB_BEGIN_ALLOW_THREADS; 6953 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback); 6954 MYDB_END_ALLOW_THREADS; 6955 6956 if (err) { 6957 Py_DECREF(notifyFunc); 6958 self->event_notifyCallback = NULL; 6959 } 6960 6961 RETURN_IF_ERR(); 6962 RETURN_NONE(); 6963 } 6964 #endif 6965 6966 6967 /* --------------------------------------------------------------------- */ 6968 /* REPLICATION METHODS: Base Replication */ 6969 6970 6971 static PyObject* 6972 DBEnv_rep_process_message(DBEnvObject* self, PyObject* args) 6973 { 6974 int err; 6975 PyObject *control_py, *rec_py; 6976 DBT control, rec; 6977 int envid; 6978 #if (DBVER >= 42) 6979 DB_LSN lsn; 6980 #endif 6981 6982 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py, 6983 &rec_py, &envid)) 6984 return NULL; 6985 CHECK_ENV_NOT_CLOSED(self); 6986 6987 if (!make_dbt(control_py, &control)) 6988 return NULL; 6989 if (!make_dbt(rec_py, &rec)) 6990 return NULL; 6991 6992 MYDB_BEGIN_ALLOW_THREADS; 6993 #if (DBVER >= 46) 6994 err = self->db_env->rep_process_message(self->db_env, &control, &rec, 6995 envid, &lsn); 6996 #else 6997 #if (DBVER >= 42) 6998 err = self->db_env->rep_process_message(self->db_env, &control, &rec, 6999 &envid, &lsn); 7000 #else 7001 err = self->db_env->rep_process_message(self->db_env, &control, &rec, 7002 &envid); 7003 #endif 7004 #endif 7005 MYDB_END_ALLOW_THREADS; 7006 switch (err) { 7007 case DB_REP_NEWMASTER : 7008 return Py_BuildValue("(iO)", envid, Py_None); 7009 break; 7010 7011 case DB_REP_DUPMASTER : 7012 case DB_REP_HOLDELECTION : 7013 #if (DBVER >= 44) 7014 case DB_REP_IGNORE : 7015 case DB_REP_JOIN_FAILURE : 7016 #endif 7017 return Py_BuildValue("(iO)", err, Py_None); 7018 break; 7019 case DB_REP_NEWSITE : 7020 { 7021 PyObject *tmp, *r; 7022 7023 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) { 7024 return NULL; 7025 } 7026 7027 r = Py_BuildValue("(iO)", err, tmp); 7028 Py_DECREF(tmp); 7029 return r; 7030 break; 7031 } 7032 #if (DBVER >= 42) 7033 case DB_REP_NOTPERM : 7034 case DB_REP_ISPERM : 7035 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset); 7036 break; 7037 #endif 7038 } 7039 RETURN_IF_ERR(); 7040 return Py_BuildValue("(OO)", Py_None, Py_None); 7041 } 7042 7043 static int 7044 _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec, 7045 const DB_LSN *lsn, int envid, u_int32_t flags) 7046 { 7047 DBEnvObject *dbenv; 7048 PyObject* rep_transport; 7049 PyObject* args; 7050 PyObject *a, *b; 7051 PyObject* result = NULL; 7052 int ret=0; 7053 7054 MYDB_BEGIN_BLOCK_THREADS; 7055 dbenv = (DBEnvObject *)db_env->app_private; 7056 rep_transport = dbenv->rep_transport; 7057 7058 /* 7059 ** The errors in 'a' or 'b' are detected in "Py_BuildValue". 7060 */ 7061 a = PyBytes_FromStringAndSize(control->data, control->size); 7062 b = PyBytes_FromStringAndSize(rec->data, rec->size); 7063 7064 args = Py_BuildValue( 7065 #if (PY_VERSION_HEX >= 0x02040000) 7066 "(OOO(ll)iI)", 7067 #else 7068 "(OOO(ll)ii)", 7069 #endif 7070 dbenv, 7071 a, b, 7072 lsn->file, lsn->offset, envid, flags); 7073 if (args) { 7074 result = PyEval_CallObject(rep_transport, args); 7075 } 7076 7077 if ((!args) || (!result)) { 7078 PyErr_Print(); 7079 ret = -1; 7080 } 7081 Py_XDECREF(a); 7082 Py_XDECREF(b); 7083 Py_XDECREF(args); 7084 Py_XDECREF(result); 7085 MYDB_END_BLOCK_THREADS; 7086 return ret; 7087 } 7088 7089 #if (DBVER <= 41) 7090 static int 7091 _DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec, 7092 int envid, u_int32_t flags) 7093 { 7094 DB_LSN lsn; 7095 7096 lsn.file = -1; /* Dummy values */ 7097 lsn.offset = -1; 7098 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid, 7099 flags); 7100 } 7101 #endif 7102 7103 static PyObject* 7104 DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args) 7105 { 7106 int err; 7107 int envid; 7108 PyObject *rep_transport; 7109 7110 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport)) 7111 return NULL; 7112 CHECK_ENV_NOT_CLOSED(self); 7113 if (!PyCallable_Check(rep_transport)) { 7114 makeTypeError("Callable", rep_transport); 7115 return NULL; 7116 } 7117 7118 MYDB_BEGIN_ALLOW_THREADS; 7119 #if (DBVER >=45) 7120 err = self->db_env->rep_set_transport(self->db_env, envid, 7121 &_DBEnv_rep_transportCallback); 7122 #else 7123 #if (DBVER >= 42) 7124 err = self->db_env->set_rep_transport(self->db_env, envid, 7125 &_DBEnv_rep_transportCallback); 7126 #else 7127 err = self->db_env->set_rep_transport(self->db_env, envid, 7128 &_DBEnv_rep_transportCallbackOLD); 7129 #endif 7130 #endif 7131 MYDB_END_ALLOW_THREADS; 7132 RETURN_IF_ERR(); 7133 7134 Py_DECREF(self->rep_transport); 7135 Py_INCREF(rep_transport); 7136 self->rep_transport = rep_transport; 7137 RETURN_NONE(); 7138 } 7139 7140 #if (DBVER >= 47) 7141 static PyObject* 7142 DBEnv_rep_set_request(DBEnvObject* self, PyObject* args) 7143 { 7144 int err; 7145 unsigned int minimum, maximum; 7146 7147 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum)) 7148 return NULL; 7149 CHECK_ENV_NOT_CLOSED(self); 7150 7151 MYDB_BEGIN_ALLOW_THREADS; 7152 err = self->db_env->rep_set_request(self->db_env, minimum, maximum); 7153 MYDB_END_ALLOW_THREADS; 7154 RETURN_IF_ERR(); 7155 RETURN_NONE(); 7156 } 7157 7158 static PyObject* 7159 DBEnv_rep_get_request(DBEnvObject* self) 7160 { 7161 int err; 7162 u_int32_t minimum, maximum; 7163 7164 CHECK_ENV_NOT_CLOSED(self); 7165 MYDB_BEGIN_ALLOW_THREADS; 7166 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum); 7167 MYDB_END_ALLOW_THREADS; 7168 RETURN_IF_ERR(); 7169 #if (PY_VERSION_HEX >= 0x02040000) 7170 return Py_BuildValue("II", minimum, maximum); 7171 #else 7172 return Py_BuildValue("ii", minimum, maximum); 7173 #endif 7174 } 7175 #endif 7176 7177 #if (DBVER >= 45) 7178 static PyObject* 7179 DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args) 7180 { 7181 int err; 7182 int limit; 7183 7184 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit)) 7185 return NULL; 7186 CHECK_ENV_NOT_CLOSED(self); 7187 7188 MYDB_BEGIN_ALLOW_THREADS; 7189 err = self->db_env->rep_set_limit(self->db_env, 0, limit); 7190 MYDB_END_ALLOW_THREADS; 7191 RETURN_IF_ERR(); 7192 RETURN_NONE(); 7193 } 7194 7195 static PyObject* 7196 DBEnv_rep_get_limit(DBEnvObject* self) 7197 { 7198 int err; 7199 u_int32_t gbytes, bytes; 7200 7201 CHECK_ENV_NOT_CLOSED(self); 7202 MYDB_BEGIN_ALLOW_THREADS; 7203 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes); 7204 MYDB_END_ALLOW_THREADS; 7205 RETURN_IF_ERR(); 7206 return NUMBER_FromLong(bytes); 7207 } 7208 #endif 7209 7210 #if (DBVER >= 44) 7211 static PyObject* 7212 DBEnv_rep_set_config(DBEnvObject* self, PyObject* args) 7213 { 7214 int err; 7215 int which; 7216 int onoff; 7217 7218 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff)) 7219 return NULL; 7220 CHECK_ENV_NOT_CLOSED(self); 7221 7222 MYDB_BEGIN_ALLOW_THREADS; 7223 err = self->db_env->rep_set_config(self->db_env, which, onoff); 7224 MYDB_END_ALLOW_THREADS; 7225 RETURN_IF_ERR(); 7226 RETURN_NONE(); 7227 } 7228 7229 static PyObject* 7230 DBEnv_rep_get_config(DBEnvObject* self, PyObject* args) 7231 { 7232 int err; 7233 int which; 7234 int onoff; 7235 7236 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) { 7237 return NULL; 7238 } 7239 CHECK_ENV_NOT_CLOSED(self); 7240 MYDB_BEGIN_ALLOW_THREADS; 7241 err = self->db_env->rep_get_config(self->db_env, which, &onoff); 7242 MYDB_END_ALLOW_THREADS; 7243 RETURN_IF_ERR(); 7244 return PyBool_FromLong(onoff); 7245 } 7246 #endif 7247 7248 #if (DBVER >= 46) 7249 static PyObject* 7250 DBEnv_rep_elect(DBEnvObject* self, PyObject* args) 7251 { 7252 int err; 7253 u_int32_t nsites, nvotes; 7254 7255 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) { 7256 return NULL; 7257 } 7258 CHECK_ENV_NOT_CLOSED(self); 7259 MYDB_BEGIN_ALLOW_THREADS; 7260 err = self->db_env->rep_elect(self->db_env, nsites, nvotes, 0); 7261 MYDB_END_ALLOW_THREADS; 7262 RETURN_IF_ERR(); 7263 RETURN_NONE(); 7264 } 7265 #endif 7266 7267 static PyObject* 7268 DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs) 7269 { 7270 int err; 7271 PyObject *cdata_py = Py_None; 7272 DBT cdata; 7273 int flags; 7274 static char* kwnames[] = {"flags","cdata", NULL}; 7275 7276 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 7277 "i|O:rep_start", kwnames, &flags, &cdata_py)) 7278 { 7279 return NULL; 7280 } 7281 CHECK_ENV_NOT_CLOSED(self); 7282 7283 if (!make_dbt(cdata_py, &cdata)) 7284 return NULL; 7285 7286 MYDB_BEGIN_ALLOW_THREADS; 7287 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL, 7288 flags); 7289 MYDB_END_ALLOW_THREADS; 7290 RETURN_IF_ERR(); 7291 RETURN_NONE(); 7292 } 7293 7294 #if (DBVER >= 44) 7295 static PyObject* 7296 DBEnv_rep_sync(DBEnvObject* self) 7297 { 7298 int err; 7299 7300 CHECK_ENV_NOT_CLOSED(self); 7301 MYDB_BEGIN_ALLOW_THREADS; 7302 err = self->db_env->rep_sync(self->db_env, 0); 7303 MYDB_END_ALLOW_THREADS; 7304 RETURN_IF_ERR(); 7305 RETURN_NONE(); 7306 } 7307 #endif 7308 7309 7310 #if (DBVER >= 45) 7311 static PyObject* 7312 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args) 7313 { 7314 int err; 7315 int nsites; 7316 7317 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) { 7318 return NULL; 7319 } 7320 CHECK_ENV_NOT_CLOSED(self); 7321 MYDB_BEGIN_ALLOW_THREADS; 7322 err = self->db_env->rep_set_nsites(self->db_env, nsites); 7323 MYDB_END_ALLOW_THREADS; 7324 RETURN_IF_ERR(); 7325 RETURN_NONE(); 7326 } 7327 7328 static PyObject* 7329 DBEnv_rep_get_nsites(DBEnvObject* self) 7330 { 7331 int err; 7332 #if (DBVER >= 47) 7333 u_int32_t nsites; 7334 #else 7335 int nsites; 7336 #endif 7337 7338 CHECK_ENV_NOT_CLOSED(self); 7339 MYDB_BEGIN_ALLOW_THREADS; 7340 err = self->db_env->rep_get_nsites(self->db_env, &nsites); 7341 MYDB_END_ALLOW_THREADS; 7342 RETURN_IF_ERR(); 7343 return NUMBER_FromLong(nsites); 7344 } 7345 7346 static PyObject* 7347 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args) 7348 { 7349 int err; 7350 int priority; 7351 7352 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) { 7353 return NULL; 7354 } 7355 CHECK_ENV_NOT_CLOSED(self); 7356 MYDB_BEGIN_ALLOW_THREADS; 7357 err = self->db_env->rep_set_priority(self->db_env, priority); 7358 MYDB_END_ALLOW_THREADS; 7359 RETURN_IF_ERR(); 7360 RETURN_NONE(); 7361 } 7362 7363 static PyObject* 7364 DBEnv_rep_get_priority(DBEnvObject* self) 7365 { 7366 int err; 7367 #if (DBVER >= 47) 7368 u_int32_t priority; 7369 #else 7370 int priority; 7371 #endif 7372 7373 CHECK_ENV_NOT_CLOSED(self); 7374 MYDB_BEGIN_ALLOW_THREADS; 7375 err = self->db_env->rep_get_priority(self->db_env, &priority); 7376 MYDB_END_ALLOW_THREADS; 7377 RETURN_IF_ERR(); 7378 return NUMBER_FromLong(priority); 7379 } 7380 7381 static PyObject* 7382 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args) 7383 { 7384 int err; 7385 int which, timeout; 7386 7387 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) { 7388 return NULL; 7389 } 7390 CHECK_ENV_NOT_CLOSED(self); 7391 MYDB_BEGIN_ALLOW_THREADS; 7392 err = self->db_env->rep_set_timeout(self->db_env, which, timeout); 7393 MYDB_END_ALLOW_THREADS; 7394 RETURN_IF_ERR(); 7395 RETURN_NONE(); 7396 } 7397 7398 static PyObject* 7399 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args) 7400 { 7401 int err; 7402 int which; 7403 u_int32_t timeout; 7404 7405 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) { 7406 return NULL; 7407 } 7408 CHECK_ENV_NOT_CLOSED(self); 7409 MYDB_BEGIN_ALLOW_THREADS; 7410 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout); 7411 MYDB_END_ALLOW_THREADS; 7412 RETURN_IF_ERR(); 7413 return NUMBER_FromLong(timeout); 7414 } 7415 #endif 7416 7417 7418 #if (DBVER >= 47) 7419 static PyObject* 7420 DBEnv_rep_set_clockskew(DBEnvObject* self, PyObject* args) 7421 { 7422 int err; 7423 unsigned int fast, slow; 7424 7425 #if (PY_VERSION_HEX >= 0x02040000) 7426 if (!PyArg_ParseTuple(args,"II:rep_set_clockskew", &fast, &slow)) 7427 return NULL; 7428 #else 7429 if (!PyArg_ParseTuple(args,"ii:rep_set_clockskew", &fast, &slow)) 7430 return NULL; 7431 #endif 7432 7433 CHECK_ENV_NOT_CLOSED(self); 7434 7435 MYDB_BEGIN_ALLOW_THREADS; 7436 err = self->db_env->rep_set_clockskew(self->db_env, fast, slow); 7437 MYDB_END_ALLOW_THREADS; 7438 RETURN_IF_ERR(); 7439 RETURN_NONE(); 7440 } 7441 7442 static PyObject* 7443 DBEnv_rep_get_clockskew(DBEnvObject* self) 7444 { 7445 int err; 7446 unsigned int fast, slow; 7447 7448 CHECK_ENV_NOT_CLOSED(self); 7449 MYDB_BEGIN_ALLOW_THREADS; 7450 err = self->db_env->rep_get_clockskew(self->db_env, &fast, &slow); 7451 MYDB_END_ALLOW_THREADS; 7452 RETURN_IF_ERR(); 7453 #if (PY_VERSION_HEX >= 0x02040000) 7454 return Py_BuildValue("(II)", fast, slow); 7455 #else 7456 return Py_BuildValue("(ii)", fast, slow); 7457 #endif 7458 } 7459 #endif 7460 7461 #if (DBVER >= 43) 7462 static PyObject* 7463 DBEnv_rep_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 7464 { 7465 int err; 7466 int flags=0; 7467 static char* kwnames[] = { "flags", NULL }; 7468 7469 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat_print", 7470 kwnames, &flags)) 7471 { 7472 return NULL; 7473 } 7474 CHECK_ENV_NOT_CLOSED(self); 7475 MYDB_BEGIN_ALLOW_THREADS; 7476 err = self->db_env->rep_stat_print(self->db_env, flags); 7477 MYDB_END_ALLOW_THREADS; 7478 RETURN_IF_ERR(); 7479 RETURN_NONE(); 7480 } 7481 #endif 7482 7483 static PyObject* 7484 DBEnv_rep_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs) 7485 { 7486 int err; 7487 int flags=0; 7488 DB_REP_STAT *statp; 7489 PyObject *stats; 7490 static char* kwnames[] = { "flags", NULL }; 7491 7492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:rep_stat", 7493 kwnames, &flags)) 7494 { 7495 return NULL; 7496 } 7497 CHECK_ENV_NOT_CLOSED(self); 7498 MYDB_BEGIN_ALLOW_THREADS; 7499 err = self->db_env->rep_stat(self->db_env, &statp, flags); 7500 MYDB_END_ALLOW_THREADS; 7501 RETURN_IF_ERR(); 7502 7503 stats=PyDict_New(); 7504 if (stats == NULL) { 7505 free(statp); 7506 return NULL; 7507 } 7508 7509 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name) 7510 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(stats , #name, statp->st_##name) 7511 7512 #if (DBVER >= 44) 7513 MAKE_ENTRY(bulk_fills); 7514 MAKE_ENTRY(bulk_overflows); 7515 MAKE_ENTRY(bulk_records); 7516 MAKE_ENTRY(bulk_transfers); 7517 MAKE_ENTRY(client_rerequests); 7518 MAKE_ENTRY(client_svc_miss); 7519 MAKE_ENTRY(client_svc_req); 7520 #endif 7521 MAKE_ENTRY(dupmasters); 7522 #if (DBVER >= 43) 7523 MAKE_ENTRY(egen); 7524 MAKE_ENTRY(election_nvotes); 7525 MAKE_ENTRY(startup_complete); 7526 MAKE_ENTRY(pg_duplicated); 7527 MAKE_ENTRY(pg_records); 7528 MAKE_ENTRY(pg_requested); 7529 MAKE_ENTRY(next_pg); 7530 MAKE_ENTRY(waiting_pg); 7531 #endif 7532 MAKE_ENTRY(election_cur_winner); 7533 MAKE_ENTRY(election_gen); 7534 MAKE_DB_LSN_ENTRY(election_lsn); 7535 MAKE_ENTRY(election_nsites); 7536 MAKE_ENTRY(election_priority); 7537 #if (DBVER >= 44) 7538 MAKE_ENTRY(election_sec); 7539 MAKE_ENTRY(election_usec); 7540 #endif 7541 MAKE_ENTRY(election_status); 7542 MAKE_ENTRY(election_tiebreaker); 7543 MAKE_ENTRY(election_votes); 7544 MAKE_ENTRY(elections); 7545 MAKE_ENTRY(elections_won); 7546 MAKE_ENTRY(env_id); 7547 MAKE_ENTRY(env_priority); 7548 MAKE_ENTRY(gen); 7549 MAKE_ENTRY(log_duplicated); 7550 MAKE_ENTRY(log_queued); 7551 MAKE_ENTRY(log_queued_max); 7552 MAKE_ENTRY(log_queued_total); 7553 MAKE_ENTRY(log_records); 7554 MAKE_ENTRY(log_requested); 7555 MAKE_ENTRY(master); 7556 MAKE_ENTRY(master_changes); 7557 #if (DBVER >= 47) 7558 MAKE_ENTRY(max_lease_sec); 7559 MAKE_ENTRY(max_lease_usec); 7560 MAKE_DB_LSN_ENTRY(max_perm_lsn); 7561 #endif 7562 MAKE_ENTRY(msgs_badgen); 7563 MAKE_ENTRY(msgs_processed); 7564 MAKE_ENTRY(msgs_recover); 7565 MAKE_ENTRY(msgs_send_failures); 7566 MAKE_ENTRY(msgs_sent); 7567 MAKE_ENTRY(newsites); 7568 MAKE_DB_LSN_ENTRY(next_lsn); 7569 MAKE_ENTRY(nsites); 7570 MAKE_ENTRY(nthrottles); 7571 MAKE_ENTRY(outdated); 7572 #if (DBVER >= 46) 7573 MAKE_ENTRY(startsync_delayed); 7574 #endif 7575 MAKE_ENTRY(status); 7576 MAKE_ENTRY(txns_applied); 7577 MAKE_DB_LSN_ENTRY(waiting_lsn); 7578 7579 #undef MAKE_DB_LSN_ENTRY 7580 #undef MAKE_ENTRY 7581 7582 free(statp); 7583 return stats; 7584 } 7585 7586 /* --------------------------------------------------------------------- */ 7587 /* REPLICATION METHODS: Replication Manager */ 7588 7589 #if (DBVER >= 45) 7590 static PyObject* 7591 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject* 7592 kwargs) 7593 { 7594 int err; 7595 int nthreads, flags; 7596 static char* kwnames[] = {"nthreads","flags", NULL}; 7597 7598 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 7599 "ii:repmgr_start", kwnames, &nthreads, &flags)) 7600 { 7601 return NULL; 7602 } 7603 CHECK_ENV_NOT_CLOSED(self); 7604 MYDB_BEGIN_ALLOW_THREADS; 7605 err = self->db_env->repmgr_start(self->db_env, nthreads, flags); 7606 MYDB_END_ALLOW_THREADS; 7607 RETURN_IF_ERR(); 7608 RETURN_NONE(); 7609 } 7610 7611 static PyObject* 7612 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject* 7613 kwargs) 7614 { 7615 int err; 7616 char *host; 7617 int port; 7618 int flags = 0; 7619 static char* kwnames[] = {"host", "port", "flags", NULL}; 7620 7621 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 7622 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags)) 7623 { 7624 return NULL; 7625 } 7626 CHECK_ENV_NOT_CLOSED(self); 7627 MYDB_BEGIN_ALLOW_THREADS; 7628 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags); 7629 MYDB_END_ALLOW_THREADS; 7630 RETURN_IF_ERR(); 7631 RETURN_NONE(); 7632 } 7633 7634 static PyObject* 7635 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject* 7636 kwargs) 7637 { 7638 int err; 7639 char *host; 7640 int port; 7641 int flags = 0; 7642 int eidp; 7643 static char* kwnames[] = {"host", "port", "flags", NULL}; 7644 7645 if (!PyArg_ParseTupleAndKeywords(args, kwargs, 7646 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags)) 7647 { 7648 return NULL; 7649 } 7650 CHECK_ENV_NOT_CLOSED(self); 7651 MYDB_BEGIN_ALLOW_THREADS; 7652 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags); 7653 MYDB_END_ALLOW_THREADS; 7654 RETURN_IF_ERR(); 7655 return NUMBER_FromLong(eidp); 7656 } 7657 7658 static PyObject* 7659 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args) 7660 { 7661 int err; 7662 int ack_policy; 7663 7664 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy)) 7665 { 7666 return NULL; 7667 } 7668 CHECK_ENV_NOT_CLOSED(self); 7669 MYDB_BEGIN_ALLOW_THREADS; 7670 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy); 7671 MYDB_END_ALLOW_THREADS; 7672 RETURN_IF_ERR(); 7673 RETURN_NONE(); 7674 } 7675 7676 static PyObject* 7677 DBEnv_repmgr_get_ack_policy(DBEnvObject* self) 7678 { 7679 int err; 7680 int ack_policy; 7681 7682 CHECK_ENV_NOT_CLOSED(self); 7683 MYDB_BEGIN_ALLOW_THREADS; 7684 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy); 7685 MYDB_END_ALLOW_THREADS; 7686 RETURN_IF_ERR(); 7687 return NUMBER_FromLong(ack_policy); 7688 } 7689 7690 static PyObject* 7691 DBEnv_repmgr_site_list(DBEnvObject* self) 7692 { 7693 int err; 7694 unsigned int countp; 7695 DB_REPMGR_SITE *listp; 7696 PyObject *stats, *key, *tuple; 7697 7698 CHECK_ENV_NOT_CLOSED(self); 7699 MYDB_BEGIN_ALLOW_THREADS; 7700 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp); 7701 MYDB_END_ALLOW_THREADS; 7702 RETURN_IF_ERR(); 7703 7704 stats=PyDict_New(); 7705 if (stats == NULL) { 7706 free(listp); 7707 return NULL; 7708 } 7709 7710 for(;countp--;) { 7711 key=NUMBER_FromLong(listp[countp].eid); 7712 if(!key) { 7713 Py_DECREF(stats); 7714 free(listp); 7715 return NULL; 7716 } 7717 #if (PY_VERSION_HEX >= 0x02040000) 7718 tuple=Py_BuildValue("(sII)", listp[countp].host, 7719 listp[countp].port, listp[countp].status); 7720 #else 7721 tuple=Py_BuildValue("(sii)", listp[countp].host, 7722 listp[countp].port, listp[countp].status); 7723 #endif 7724 if(!tuple) { 7725 Py_DECREF(key); 7726 Py_DECREF(stats); 7727 free(listp); 7728 return NULL; 7729 } 7730 if(PyDict_SetItem(stats, key, tuple)) { 7731 Py_DECREF(key); 7732 Py_DECREF(tuple); 7733 Py_DECREF(stats); 7734 free(listp); 7735 return NULL; 7736 } 7737 Py_DECREF(key); 7738 Py_DECREF(tuple); 7739 } 7740 free(listp); 7741 return stats; 7742 } 7743 #endif 7744 7745 #if (DBVER >= 46) 7746 static PyObject* 7747 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs) 7748 { 7749 int err; 7750 int flags=0; 7751 static char* kwnames[] = { "flags", NULL }; 7752 7753 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print", 7754 kwnames, &flags)) 7755 { 7756 return NULL; 7757 } 7758 CHECK_ENV_NOT_CLOSED(self); 7759 MYDB_BEGIN_ALLOW_THREADS; 7760 err = self->db_env->repmgr_stat_print(self->db_env, flags); 7761 MYDB_END_ALLOW_THREADS; 7762 RETURN_IF_ERR(); 7763 RETURN_NONE(); 7764 } 7765 7766 static PyObject* 7767 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs) 7768 { 7769 int err; 7770 int flags=0; 7771 DB_REPMGR_STAT *statp; 7772 PyObject *stats; 7773 static char* kwnames[] = { "flags", NULL }; 7774 7775 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat", 7776 kwnames, &flags)) 7777 { 7778 return NULL; 7779 } 7780 CHECK_ENV_NOT_CLOSED(self); 7781 MYDB_BEGIN_ALLOW_THREADS; 7782 err = self->db_env->repmgr_stat(self->db_env, &statp, flags); 7783 MYDB_END_ALLOW_THREADS; 7784 RETURN_IF_ERR(); 7785 7786 stats=PyDict_New(); 7787 if (stats == NULL) { 7788 free(statp); 7789 return NULL; 7790 } 7791 7792 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name) 7793 7794 MAKE_ENTRY(perm_failed); 7795 MAKE_ENTRY(msgs_queued); 7796 MAKE_ENTRY(msgs_dropped); 7797 MAKE_ENTRY(connection_drop); 7798 MAKE_ENTRY(connect_fail); 7799 7800 #undef MAKE_ENTRY 7801 7802 free(statp); 7803 return stats; 7804 } 7805 #endif 7806 7807 7808 /* --------------------------------------------------------------------- */ 7809 /* DBTxn methods */ 7810 7811 7812 static void _close_transaction_cursors(DBTxnObject* txn) 7813 { 7814 PyObject *dummy; 7815 7816 while(txn->children_cursors) { 7817 PyErr_Warn(PyExc_RuntimeWarning, 7818 "Must close cursors before resolving a transaction."); 7819 dummy=DBC_close_internal(txn->children_cursors); 7820 Py_XDECREF(dummy); 7821 } 7822 } 7823 7824 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn) 7825 { 7826 DBObject *db; 7827 #if (DBVER >= 43) 7828 DBSequenceObject *dbs; 7829 #endif 7830 7831 while (txn->children_dbs) { 7832 db=txn->children_dbs; 7833 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db); 7834 if (txn->parent_txn) { 7835 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db); 7836 db->txn=txn->parent_txn; 7837 } else { 7838 /* The db is already linked to its environment, 7839 ** so nothing to do. 7840 */ 7841 db->txn=NULL; 7842 } 7843 } 7844 7845 #if (DBVER >= 43) 7846 while (txn->children_sequences) { 7847 dbs=txn->children_sequences; 7848 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs); 7849 if (txn->parent_txn) { 7850 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs); 7851 dbs->txn=txn->parent_txn; 7852 } else { 7853 /* The sequence is already linked to its 7854 ** parent db. Nothing to do. 7855 */ 7856 dbs->txn=NULL; 7857 } 7858 } 7859 #endif 7860 } 7861 7862 7863 static PyObject* 7864 DBTxn_commit(DBTxnObject* self, PyObject* args) 7865 { 7866 int flags=0, err; 7867 DB_TXN *txn; 7868 7869 if (!PyArg_ParseTuple(args, "|i:commit", &flags)) 7870 return NULL; 7871 7872 _close_transaction_cursors(self); 7873 7874 if (!self->txn) { 7875 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " 7876 "after txn_commit, txn_abort " 7877 "or txn_discard"); 7878 if (t) { 7879 PyErr_SetObject(DBError, t); 7880 Py_DECREF(t); 7881 } 7882 return NULL; 7883 } 7884 self->flag_prepare=0; 7885 txn = self->txn; 7886 self->txn = NULL; /* this DB_TXN is no longer valid after this call */ 7887 7888 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); 7889 7890 MYDB_BEGIN_ALLOW_THREADS; 7891 err = txn->commit(txn, flags); 7892 MYDB_END_ALLOW_THREADS; 7893 7894 _promote_transaction_dbs_and_sequences(self); 7895 7896 RETURN_IF_ERR(); 7897 RETURN_NONE(); 7898 } 7899 7900 static PyObject* 7901 DBTxn_prepare(DBTxnObject* self, PyObject* args) 7902 { 7903 int err; 7904 char* gid=NULL; 7905 int gid_size=0; 7906 7907 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size)) 7908 return NULL; 7909 7910 if (gid_size != DB_GID_SIZE) { 7911 PyErr_SetString(PyExc_TypeError, 7912 "gid must be DB_GID_SIZE bytes long"); 7913 return NULL; 7914 } 7915 7916 if (!self->txn) { 7917 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used " 7918 "after txn_commit, txn_abort " 7919 "or txn_discard"); 7920 if (t) { 7921 PyErr_SetObject(DBError, t); 7922 Py_DECREF(t); 7923 } 7924 return NULL; 7925 } 7926 self->flag_prepare=1; /* Prepare state */ 7927 MYDB_BEGIN_ALLOW_THREADS; 7928 err = self->txn->prepare(self->txn, (u_int8_t*)gid); 7929 MYDB_END_ALLOW_THREADS; 7930 RETURN_IF_ERR(); 7931 RETURN_NONE(); 7932 } 7933 7934 7935 static PyObject* 7936 DBTxn_abort_discard_internal(DBTxnObject* self, int discard) 7937 { 7938 PyObject *dummy; 7939 int err=0; 7940 DB_TXN *txn; 7941 7942 if (!self->txn) { 7943 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " 7944 "after txn_commit, txn_abort " 7945 "or txn_discard"); 7946 if (t) { 7947 PyErr_SetObject(DBError, t); 7948 Py_DECREF(t); 7949 } 7950 return NULL; 7951 } 7952 txn = self->txn; 7953 self->txn = NULL; /* this DB_TXN is no longer valid after this call */ 7954 7955 _close_transaction_cursors(self); 7956 #if (DBVER >= 43) 7957 while (self->children_sequences) { 7958 dummy=DBSequence_close_internal(self->children_sequences,0,0); 7959 Py_XDECREF(dummy); 7960 } 7961 #endif 7962 while (self->children_dbs) { 7963 dummy=DB_close_internal(self->children_dbs, 0, 0); 7964 Py_XDECREF(dummy); 7965 } 7966 7967 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); 7968 7969 MYDB_BEGIN_ALLOW_THREADS; 7970 if (discard) { 7971 assert(!self->flag_prepare); 7972 err = txn->discard(txn,0); 7973 } else { 7974 /* 7975 ** If the transaction is in the "prepare" or "recover" state, 7976 ** we better do not implicitly abort it. 7977 */ 7978 if (!self->flag_prepare) { 7979 err = txn->abort(txn); 7980 } 7981 } 7982 MYDB_END_ALLOW_THREADS; 7983 RETURN_IF_ERR(); 7984 RETURN_NONE(); 7985 } 7986 7987 static PyObject* 7988 DBTxn_abort(DBTxnObject* self) 7989 { 7990 self->flag_prepare=0; 7991 _close_transaction_cursors(self); 7992 7993 return DBTxn_abort_discard_internal(self,0); 7994 } 7995 7996 static PyObject* 7997 DBTxn_discard(DBTxnObject* self) 7998 { 7999 self->flag_prepare=0; 8000 _close_transaction_cursors(self); 8001 8002 return DBTxn_abort_discard_internal(self,1); 8003 } 8004 8005 8006 static PyObject* 8007 DBTxn_id(DBTxnObject* self) 8008 { 8009 int id; 8010 8011 if (!self->txn) { 8012 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used " 8013 "after txn_commit, txn_abort " 8014 "or txn_discard"); 8015 if (t) { 8016 PyErr_SetObject(DBError, t); 8017 Py_DECREF(t); 8018 } 8019 return NULL; 8020 } 8021 MYDB_BEGIN_ALLOW_THREADS; 8022 id = self->txn->id(self->txn); 8023 MYDB_END_ALLOW_THREADS; 8024 return NUMBER_FromLong(id); 8025 } 8026 8027 8028 static PyObject* 8029 DBTxn_set_timeout(DBTxnObject* self, PyObject* args, PyObject* kwargs) 8030 { 8031 int err; 8032 u_int32_t flags=0; 8033 u_int32_t timeout = 0; 8034 static char* kwnames[] = { "timeout", "flags", NULL }; 8035 8036 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames, 8037 &timeout, &flags)) { 8038 return NULL; 8039 } 8040 8041 MYDB_BEGIN_ALLOW_THREADS; 8042 err = self->txn->set_timeout(self->txn, (db_timeout_t)timeout, flags); 8043 MYDB_END_ALLOW_THREADS; 8044 8045 RETURN_IF_ERR(); 8046 RETURN_NONE(); 8047 } 8048 8049 8050 #if (DBVER >= 44) 8051 static PyObject* 8052 DBTxn_set_name(DBTxnObject* self, PyObject* args) 8053 { 8054 int err; 8055 const char *name; 8056 8057 if (!PyArg_ParseTuple(args, "s:set_name", &name)) 8058 return NULL; 8059 8060 MYDB_BEGIN_ALLOW_THREADS; 8061 err = self->txn->set_name(self->txn, name); 8062 MYDB_END_ALLOW_THREADS; 8063 8064 RETURN_IF_ERR(); 8065 RETURN_NONE(); 8066 } 8067 #endif 8068 8069 8070 #if (DBVER >= 44) 8071 static PyObject* 8072 DBTxn_get_name(DBTxnObject* self) 8073 { 8074 int err; 8075 const char *name; 8076 8077 MYDB_BEGIN_ALLOW_THREADS; 8078 err = self->txn->get_name(self->txn, &name); 8079 MYDB_END_ALLOW_THREADS; 8080 8081 RETURN_IF_ERR(); 8082 #if (PY_VERSION_HEX < 0x03000000) 8083 if (!name) { 8084 return PyString_FromString(""); 8085 } 8086 return PyString_FromString(name); 8087 #else 8088 if (!name) { 8089 return PyUnicode_FromString(""); 8090 } 8091 return PyUnicode_FromString(name); 8092 #endif 8093 } 8094 #endif 8095 8096 8097 #if (DBVER >= 43) 8098 /* --------------------------------------------------------------------- */ 8099 /* DBSequence methods */ 8100 8101 8102 static PyObject* 8103 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close) 8104 { 8105 int err=0; 8106 8107 if (self->sequence!=NULL) { 8108 EXTRACT_FROM_DOUBLE_LINKED_LIST(self); 8109 if (self->txn) { 8110 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self); 8111 self->txn=NULL; 8112 } 8113 8114 /* 8115 ** "do_not_close" is used to dispose all related objects in the 8116 ** tree, without actually releasing the "root" object. 8117 ** This is done, for example, because function calls like 8118 ** "DBSequence.remove()" implicitly close the underlying handle. So 8119 ** the handle doesn't need to be closed, but related objects 8120 ** must be cleaned up. 8121 */ 8122 if (!do_not_close) { 8123 MYDB_BEGIN_ALLOW_THREADS 8124 err = self->sequence->close(self->sequence, flags); 8125 MYDB_END_ALLOW_THREADS 8126 } 8127 self->sequence = NULL; 8128 8129 RETURN_IF_ERR(); 8130 } 8131 8132 RETURN_NONE(); 8133 } 8134 8135 static PyObject* 8136 DBSequence_close(DBSequenceObject* self, PyObject* args) 8137 { 8138 int flags=0; 8139 if (!PyArg_ParseTuple(args,"|i:close", &flags)) 8140 return NULL; 8141 8142 return DBSequence_close_internal(self,flags,0); 8143 } 8144 8145 static PyObject* 8146 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs) 8147 { 8148 int err, flags = 0; 8149 int delta = 1; 8150 db_seq_t value; 8151 PyObject *txnobj = NULL; 8152 DB_TXN *txn = NULL; 8153 static char* kwnames[] = {"delta", "txn", "flags", NULL }; 8154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags)) 8155 return NULL; 8156 CHECK_SEQUENCE_NOT_CLOSED(self) 8157 8158 if (!checkTxnObj(txnobj, &txn)) 8159 return NULL; 8160 8161 MYDB_BEGIN_ALLOW_THREADS 8162 err = self->sequence->get(self->sequence, txn, delta, &value, flags); 8163 MYDB_END_ALLOW_THREADS 8164 8165 RETURN_IF_ERR(); 8166 return PyLong_FromLongLong(value); 8167 } 8168 8169 static PyObject* 8170 DBSequence_get_dbp(DBSequenceObject* self) 8171 { 8172 CHECK_SEQUENCE_NOT_CLOSED(self) 8173 Py_INCREF(self->mydb); 8174 return (PyObject* )self->mydb; 8175 } 8176 8177 static PyObject* 8178 DBSequence_get_key(DBSequenceObject* self) 8179 { 8180 int err; 8181 DBT key; 8182 PyObject *retval = NULL; 8183 8184 key.flags = DB_DBT_MALLOC; 8185 CHECK_SEQUENCE_NOT_CLOSED(self) 8186 MYDB_BEGIN_ALLOW_THREADS 8187 err = self->sequence->get_key(self->sequence, &key); 8188 MYDB_END_ALLOW_THREADS 8189 8190 if (!err) 8191 retval = Build_PyString(key.data, key.size); 8192 8193 FREE_DBT(key); 8194 RETURN_IF_ERR(); 8195 8196 return retval; 8197 } 8198 8199 static PyObject* 8200 DBSequence_initial_value(DBSequenceObject* self, PyObject* args) 8201 { 8202 int err; 8203 PY_LONG_LONG value; 8204 db_seq_t value2; 8205 if (!PyArg_ParseTuple(args,"L:initial_value", &value)) 8206 return NULL; 8207 CHECK_SEQUENCE_NOT_CLOSED(self) 8208 8209 value2=value; /* If truncation, compiler should show a warning */ 8210 MYDB_BEGIN_ALLOW_THREADS 8211 err = self->sequence->initial_value(self->sequence, value2); 8212 MYDB_END_ALLOW_THREADS 8213 8214 RETURN_IF_ERR(); 8215 8216 RETURN_NONE(); 8217 } 8218 8219 static PyObject* 8220 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs) 8221 { 8222 int err, flags = 0; 8223 PyObject* keyobj; 8224 PyObject *txnobj = NULL; 8225 DB_TXN *txn = NULL; 8226 DBT key; 8227 8228 static char* kwnames[] = {"key", "txn", "flags", NULL }; 8229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags)) 8230 return NULL; 8231 8232 if (!checkTxnObj(txnobj, &txn)) 8233 return NULL; 8234 8235 if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) 8236 return NULL; 8237 8238 MYDB_BEGIN_ALLOW_THREADS 8239 err = self->sequence->open(self->sequence, txn, &key, flags); 8240 MYDB_END_ALLOW_THREADS 8241 8242 FREE_DBT(key); 8243 RETURN_IF_ERR(); 8244 8245 if (txn) { 8246 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self); 8247 self->txn=(DBTxnObject *)txnobj; 8248 } 8249 8250 RETURN_NONE(); 8251 } 8252 8253 static PyObject* 8254 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs) 8255 { 8256 PyObject *dummy; 8257 int err, flags = 0; 8258 PyObject *txnobj = NULL; 8259 DB_TXN *txn = NULL; 8260 8261 static char* kwnames[] = {"txn", "flags", NULL }; 8262 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags)) 8263 return NULL; 8264 8265 if (!checkTxnObj(txnobj, &txn)) 8266 return NULL; 8267 8268 CHECK_SEQUENCE_NOT_CLOSED(self) 8269 8270 MYDB_BEGIN_ALLOW_THREADS 8271 err = self->sequence->remove(self->sequence, txn, flags); 8272 MYDB_END_ALLOW_THREADS 8273 8274 dummy=DBSequence_close_internal(self,flags,1); 8275 Py_XDECREF(dummy); 8276 8277 RETURN_IF_ERR(); 8278 RETURN_NONE(); 8279 } 8280 8281 static PyObject* 8282 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args) 8283 { 8284 int err, size; 8285 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size)) 8286 return NULL; 8287 CHECK_SEQUENCE_NOT_CLOSED(self) 8288 8289 MYDB_BEGIN_ALLOW_THREADS 8290 err = self->sequence->set_cachesize(self->sequence, size); 8291 MYDB_END_ALLOW_THREADS 8292 8293 RETURN_IF_ERR(); 8294 RETURN_NONE(); 8295 } 8296 8297 static PyObject* 8298 DBSequence_get_cachesize(DBSequenceObject* self) 8299 { 8300 int err, size; 8301 8302 CHECK_SEQUENCE_NOT_CLOSED(self) 8303 8304 MYDB_BEGIN_ALLOW_THREADS 8305 err = self->sequence->get_cachesize(self->sequence, &size); 8306 MYDB_END_ALLOW_THREADS 8307 8308 RETURN_IF_ERR(); 8309 return NUMBER_FromLong(size); 8310 } 8311 8312 static PyObject* 8313 DBSequence_set_flags(DBSequenceObject* self, PyObject* args) 8314 { 8315 int err, flags = 0; 8316 if (!PyArg_ParseTuple(args,"i:set_flags", &flags)) 8317 return NULL; 8318 CHECK_SEQUENCE_NOT_CLOSED(self) 8319 8320 MYDB_BEGIN_ALLOW_THREADS 8321 err = self->sequence->set_flags(self->sequence, flags); 8322 MYDB_END_ALLOW_THREADS 8323 8324 RETURN_IF_ERR(); 8325 RETURN_NONE(); 8326 } 8327 8328 static PyObject* 8329 DBSequence_get_flags(DBSequenceObject* self) 8330 { 8331 unsigned int flags; 8332 int err; 8333 8334 CHECK_SEQUENCE_NOT_CLOSED(self) 8335 8336 MYDB_BEGIN_ALLOW_THREADS 8337 err = self->sequence->get_flags(self->sequence, &flags); 8338 MYDB_END_ALLOW_THREADS 8339 8340 RETURN_IF_ERR(); 8341 return NUMBER_FromLong((int)flags); 8342 } 8343 8344 static PyObject* 8345 DBSequence_set_range(DBSequenceObject* self, PyObject* args) 8346 { 8347 int err; 8348 PY_LONG_LONG min, max; 8349 db_seq_t min2, max2; 8350 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max)) 8351 return NULL; 8352 CHECK_SEQUENCE_NOT_CLOSED(self) 8353 8354 min2=min; /* If truncation, compiler should show a warning */ 8355 max2=max; 8356 MYDB_BEGIN_ALLOW_THREADS 8357 err = self->sequence->set_range(self->sequence, min2, max2); 8358 MYDB_END_ALLOW_THREADS 8359 8360 RETURN_IF_ERR(); 8361 RETURN_NONE(); 8362 } 8363 8364 static PyObject* 8365 DBSequence_get_range(DBSequenceObject* self) 8366 { 8367 int err; 8368 PY_LONG_LONG min, max; 8369 db_seq_t min2, max2; 8370 8371 CHECK_SEQUENCE_NOT_CLOSED(self) 8372 8373 MYDB_BEGIN_ALLOW_THREADS 8374 err = self->sequence->get_range(self->sequence, &min2, &max2); 8375 MYDB_END_ALLOW_THREADS 8376 8377 RETURN_IF_ERR(); 8378 min=min2; /* If truncation, compiler should show a warning */ 8379 max=max2; 8380 return Py_BuildValue("(LL)", min, max); 8381 } 8382 8383 8384 static PyObject* 8385 DBSequence_stat_print(DBSequenceObject* self, PyObject* args, PyObject *kwargs) 8386 { 8387 int err; 8388 int flags=0; 8389 static char* kwnames[] = { "flags", NULL }; 8390 8391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat_print", 8392 kwnames, &flags)) 8393 { 8394 return NULL; 8395 } 8396 8397 CHECK_SEQUENCE_NOT_CLOSED(self); 8398 8399 MYDB_BEGIN_ALLOW_THREADS; 8400 err = self->sequence->stat_print(self->sequence, flags); 8401 MYDB_END_ALLOW_THREADS; 8402 RETURN_IF_ERR(); 8403 RETURN_NONE(); 8404 } 8405 8406 static PyObject* 8407 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs) 8408 { 8409 int err, flags = 0; 8410 DB_SEQUENCE_STAT* sp = NULL; 8411 PyObject* dict_stat; 8412 static char* kwnames[] = {"flags", NULL }; 8413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags)) 8414 return NULL; 8415 CHECK_SEQUENCE_NOT_CLOSED(self); 8416 8417 MYDB_BEGIN_ALLOW_THREADS; 8418 err = self->sequence->stat(self->sequence, &sp, flags); 8419 MYDB_END_ALLOW_THREADS; 8420 RETURN_IF_ERR(); 8421 8422 if ((dict_stat = PyDict_New()) == NULL) { 8423 free(sp); 8424 return NULL; 8425 } 8426 8427 8428 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name) 8429 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name) 8430 8431 MAKE_INT_ENTRY(wait); 8432 MAKE_INT_ENTRY(nowait); 8433 MAKE_LONG_LONG_ENTRY(current); 8434 MAKE_LONG_LONG_ENTRY(value); 8435 MAKE_LONG_LONG_ENTRY(last_value); 8436 MAKE_LONG_LONG_ENTRY(min); 8437 MAKE_LONG_LONG_ENTRY(max); 8438 MAKE_INT_ENTRY(cache_size); 8439 MAKE_INT_ENTRY(flags); 8440 8441 #undef MAKE_INT_ENTRY 8442 #undef MAKE_LONG_LONG_ENTRY 8443 8444 free(sp); 8445 return dict_stat; 8446 } 8447 #endif 8448 8449 8450 /* --------------------------------------------------------------------- */ 8451 /* Method definition tables and type objects */ 8452 8453 static PyMethodDef DB_methods[] = { 8454 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS}, 8455 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS}, 8456 {"close", (PyCFunction)DB_close, METH_VARARGS}, 8457 #if (DBVER >= 47) 8458 {"compact", (PyCFunction)DB_compact, METH_VARARGS|METH_KEYWORDS}, 8459 #endif 8460 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS}, 8461 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS}, 8462 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS}, 8463 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS}, 8464 {"fd", (PyCFunction)DB_fd, METH_NOARGS}, 8465 #if (DBVER >= 46) 8466 {"exists", (PyCFunction)DB_exists, 8467 METH_VARARGS|METH_KEYWORDS}, 8468 #endif 8469 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS}, 8470 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS}, 8471 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS}, 8472 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS}, 8473 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS}, 8474 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS}, 8475 {"join", (PyCFunction)DB_join, METH_VARARGS}, 8476 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS}, 8477 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS}, 8478 {"items", (PyCFunction)DB_items, METH_VARARGS}, 8479 {"keys", (PyCFunction)DB_keys, METH_VARARGS}, 8480 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS}, 8481 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS}, 8482 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS}, 8483 {"rename", (PyCFunction)DB_rename, METH_VARARGS}, 8484 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS}, 8485 #if (DBVER >= 42) 8486 {"get_bt_minkey", (PyCFunction)DB_get_bt_minkey, METH_NOARGS}, 8487 #endif 8488 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O}, 8489 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS}, 8490 #if (DBVER >= 42) 8491 {"get_cachesize", (PyCFunction)DB_get_cachesize, METH_NOARGS}, 8492 #endif 8493 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS}, 8494 #if (DBVER >= 42) 8495 {"get_encrypt_flags", (PyCFunction)DB_get_encrypt_flags, METH_NOARGS}, 8496 #endif 8497 8498 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS}, 8499 #if (DBVER >= 42) 8500 {"get_flags", (PyCFunction)DB_get_flags, METH_NOARGS}, 8501 #endif 8502 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS}, 8503 #if (DBVER >= 42) 8504 {"get_h_ffactor", (PyCFunction)DB_get_h_ffactor, METH_NOARGS}, 8505 #endif 8506 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS}, 8507 #if (DBVER >= 42) 8508 {"get_h_nelem", (PyCFunction)DB_get_h_nelem, METH_NOARGS}, 8509 #endif 8510 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS}, 8511 #if (DBVER >= 42) 8512 {"get_lorder", (PyCFunction)DB_get_lorder, METH_NOARGS}, 8513 #endif 8514 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS}, 8515 #if (DBVER >= 42) 8516 {"get_pagesize", (PyCFunction)DB_get_pagesize, METH_NOARGS}, 8517 #endif 8518 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS}, 8519 #if (DBVER >= 42) 8520 {"get_re_delim", (PyCFunction)DB_get_re_delim, METH_NOARGS}, 8521 #endif 8522 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS}, 8523 #if (DBVER >= 42) 8524 {"get_re_len", (PyCFunction)DB_get_re_len, METH_NOARGS}, 8525 #endif 8526 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS}, 8527 #if (DBVER >= 42) 8528 {"get_re_pad", (PyCFunction)DB_get_re_pad, METH_NOARGS}, 8529 #endif 8530 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS}, 8531 #if (DBVER >= 42) 8532 {"get_re_source", (PyCFunction)DB_get_re_source, METH_NOARGS}, 8533 #endif 8534 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS}, 8535 #if (DBVER >= 42) 8536 {"get_q_extentsize",(PyCFunction)DB_get_q_extentsize, METH_NOARGS}, 8537 #endif 8538 {"set_private", (PyCFunction)DB_set_private, METH_O}, 8539 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS}, 8540 #if (DBVER >= 46) 8541 {"set_priority", (PyCFunction)DB_set_priority, METH_VARARGS}, 8542 {"get_priority", (PyCFunction)DB_get_priority, METH_NOARGS}, 8543 #endif 8544 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS}, 8545 #if (DBVER >= 43) 8546 {"stat_print", (PyCFunction)DB_stat_print, 8547 METH_VARARGS|METH_KEYWORDS}, 8548 #endif 8549 {"sync", (PyCFunction)DB_sync, METH_VARARGS}, 8550 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS}, 8551 {"type", (PyCFunction)DB_get_type, METH_NOARGS}, 8552 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS}, 8553 {"values", (PyCFunction)DB_values, METH_VARARGS}, 8554 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS}, 8555 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS}, 8556 {NULL, NULL} /* sentinel */ 8557 }; 8558 8559 8560 /* We need this to support __contains__() */ 8561 static PySequenceMethods DB_sequence = { 8562 0, /* sq_length, mapping wins here */ 8563 0, /* sq_concat */ 8564 0, /* sq_repeat */ 8565 0, /* sq_item */ 8566 0, /* sq_slice */ 8567 0, /* sq_ass_item */ 8568 0, /* sq_ass_slice */ 8569 (objobjproc)DB_contains, /* sq_contains */ 8570 0, /* sq_inplace_concat */ 8571 0, /* sq_inplace_repeat */ 8572 }; 8573 8574 static PyMappingMethods DB_mapping = { 8575 DB_length, /*mp_length*/ 8576 (binaryfunc)DB_subscript, /*mp_subscript*/ 8577 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/ 8578 }; 8579 8580 8581 static PyMethodDef DBCursor_methods[] = { 8582 {"close", (PyCFunction)DBC_close, METH_NOARGS}, 8583 {"count", (PyCFunction)DBC_count, METH_VARARGS}, 8584 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS}, 8585 {"delete", (PyCFunction)DBC_delete, METH_VARARGS}, 8586 {"dup", (PyCFunction)DBC_dup, METH_VARARGS}, 8587 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS}, 8588 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS}, 8589 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS}, 8590 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS}, 8591 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS}, 8592 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS}, 8593 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS}, 8594 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS}, 8595 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS}, 8596 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS}, 8597 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS}, 8598 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS}, 8599 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS}, 8600 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS}, 8601 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS}, 8602 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS}, 8603 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS}, 8604 #if (DBVER >= 46) 8605 {"prev_dup", (PyCFunction)DBC_prev_dup, 8606 METH_VARARGS|METH_KEYWORDS}, 8607 #endif 8608 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS}, 8609 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS}, 8610 #if (DBVER >= 46) 8611 {"set_priority", (PyCFunction)DBC_set_priority, 8612 METH_VARARGS|METH_KEYWORDS}, 8613 {"get_priority", (PyCFunction)DBC_get_priority, METH_NOARGS}, 8614 #endif 8615 {NULL, NULL} /* sentinel */ 8616 }; 8617 8618 8619 static PyMethodDef DBLogCursor_methods[] = { 8620 {"close", (PyCFunction)DBLogCursor_close, METH_NOARGS}, 8621 {"current", (PyCFunction)DBLogCursor_current, METH_NOARGS}, 8622 {"first", (PyCFunction)DBLogCursor_first, METH_NOARGS}, 8623 {"last", (PyCFunction)DBLogCursor_last, METH_NOARGS}, 8624 {"next", (PyCFunction)DBLogCursor_next, METH_NOARGS}, 8625 {"prev", (PyCFunction)DBLogCursor_prev, METH_NOARGS}, 8626 {"set", (PyCFunction)DBLogCursor_set, METH_VARARGS}, 8627 {NULL, NULL} /* sentinel */ 8628 }; 8629 8630 8631 static PyMethodDef DBEnv_methods[] = { 8632 {"close", (PyCFunction)DBEnv_close, METH_VARARGS}, 8633 {"open", (PyCFunction)DBEnv_open, METH_VARARGS}, 8634 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS}, 8635 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS}, 8636 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS}, 8637 #if (DBVER >= 46) 8638 {"set_thread_count", (PyCFunction)DBEnv_set_thread_count, METH_VARARGS}, 8639 {"get_thread_count", (PyCFunction)DBEnv_get_thread_count, METH_NOARGS}, 8640 #endif 8641 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS}, 8642 #if (DBVER >= 42) 8643 {"get_encrypt_flags", (PyCFunction)DBEnv_get_encrypt_flags, METH_NOARGS}, 8644 {"get_timeout", (PyCFunction)DBEnv_get_timeout, 8645 METH_VARARGS|METH_KEYWORDS}, 8646 #endif 8647 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS}, 8648 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS}, 8649 #if (DBVER >= 42) 8650 {"get_shm_key", (PyCFunction)DBEnv_get_shm_key, METH_NOARGS}, 8651 #endif 8652 #if (DBVER >= 46) 8653 {"set_cache_max", (PyCFunction)DBEnv_set_cache_max, METH_VARARGS}, 8654 {"get_cache_max", (PyCFunction)DBEnv_get_cache_max, METH_NOARGS}, 8655 #endif 8656 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS}, 8657 #if (DBVER >= 42) 8658 {"get_cachesize", (PyCFunction)DBEnv_get_cachesize, METH_NOARGS}, 8659 #endif 8660 {"memp_trickle", (PyCFunction)DBEnv_memp_trickle, METH_VARARGS}, 8661 {"memp_sync", (PyCFunction)DBEnv_memp_sync, METH_VARARGS}, 8662 {"memp_stat", (PyCFunction)DBEnv_memp_stat, 8663 METH_VARARGS|METH_KEYWORDS}, 8664 #if (DBVER >= 43) 8665 {"memp_stat_print", (PyCFunction)DBEnv_memp_stat_print, 8666 METH_VARARGS|METH_KEYWORDS}, 8667 #endif 8668 #if (DBVER >= 44) 8669 {"mutex_set_max", (PyCFunction)DBEnv_mutex_set_max, METH_VARARGS}, 8670 {"mutex_get_max", (PyCFunction)DBEnv_mutex_get_max, METH_NOARGS}, 8671 {"mutex_set_align", (PyCFunction)DBEnv_mutex_set_align, METH_VARARGS}, 8672 {"mutex_get_align", (PyCFunction)DBEnv_mutex_get_align, METH_NOARGS}, 8673 {"mutex_set_increment", (PyCFunction)DBEnv_mutex_set_increment, 8674 METH_VARARGS}, 8675 {"mutex_get_increment", (PyCFunction)DBEnv_mutex_get_increment, 8676 METH_NOARGS}, 8677 {"mutex_set_tas_spins", (PyCFunction)DBEnv_mutex_set_tas_spins, 8678 METH_VARARGS}, 8679 {"mutex_get_tas_spins", (PyCFunction)DBEnv_mutex_get_tas_spins, 8680 METH_NOARGS}, 8681 {"mutex_stat", (PyCFunction)DBEnv_mutex_stat, METH_VARARGS}, 8682 #if (DBVER >= 44) 8683 {"mutex_stat_print", (PyCFunction)DBEnv_mutex_stat_print, 8684 METH_VARARGS|METH_KEYWORDS}, 8685 #endif 8686 #endif 8687 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS}, 8688 #if (DBVER >= 42) 8689 {"get_data_dirs", (PyCFunction)DBEnv_get_data_dirs, METH_NOARGS}, 8690 #endif 8691 #if (DBVER >= 42) 8692 {"get_flags", (PyCFunction)DBEnv_get_flags, METH_NOARGS}, 8693 #endif 8694 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS}, 8695 #if (DBVER >= 47) 8696 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS}, 8697 {"log_get_config", (PyCFunction)DBEnv_log_get_config, METH_VARARGS}, 8698 #endif 8699 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS}, 8700 #if (DBVER >= 42) 8701 {"get_lg_bsize", (PyCFunction)DBEnv_get_lg_bsize, METH_NOARGS}, 8702 #endif 8703 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS}, 8704 #if (DBVER >= 42) 8705 {"get_lg_dir", (PyCFunction)DBEnv_get_lg_dir, METH_NOARGS}, 8706 #endif 8707 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS}, 8708 #if (DBVER >= 42) 8709 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS}, 8710 #endif 8711 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS}, 8712 #if (DBVER >= 42) 8713 {"get_lg_regionmax",(PyCFunction)DBEnv_get_lg_regionmax, METH_NOARGS}, 8714 #endif 8715 #if (DBVER >= 44) 8716 {"set_lg_filemode", (PyCFunction)DBEnv_set_lg_filemode, METH_VARARGS}, 8717 {"get_lg_filemode", (PyCFunction)DBEnv_get_lg_filemode, METH_NOARGS}, 8718 #endif 8719 #if (DBVER >= 47) 8720 {"set_lk_partitions", (PyCFunction)DBEnv_set_lk_partitions, METH_VARARGS}, 8721 {"get_lk_partitions", (PyCFunction)DBEnv_get_lk_partitions, METH_NOARGS}, 8722 #endif 8723 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS}, 8724 #if (DBVER >= 42) 8725 {"get_lk_detect", (PyCFunction)DBEnv_get_lk_detect, METH_NOARGS}, 8726 #endif 8727 #if (DBVER < 45) 8728 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS}, 8729 #endif 8730 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS}, 8731 #if (DBVER >= 42) 8732 {"get_lk_max_locks", (PyCFunction)DBEnv_get_lk_max_locks, METH_NOARGS}, 8733 #endif 8734 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS}, 8735 #if (DBVER >= 42) 8736 {"get_lk_max_lockers", (PyCFunction)DBEnv_get_lk_max_lockers, METH_NOARGS}, 8737 #endif 8738 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS}, 8739 #if (DBVER >= 42) 8740 {"get_lk_max_objects", (PyCFunction)DBEnv_get_lk_max_objects, METH_NOARGS}, 8741 #endif 8742 #if (DBVER >= 43) 8743 {"stat_print", (PyCFunction)DBEnv_stat_print, 8744 METH_VARARGS|METH_KEYWORDS}, 8745 #endif 8746 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS}, 8747 #if (DBVER >= 42) 8748 {"get_mp_mmapsize", (PyCFunction)DBEnv_get_mp_mmapsize, METH_NOARGS}, 8749 #endif 8750 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS}, 8751 #if (DBVER >= 42) 8752 {"get_tmp_dir", (PyCFunction)DBEnv_get_tmp_dir, METH_NOARGS}, 8753 #endif 8754 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS}, 8755 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS}, 8756 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS}, 8757 #if (DBVER >= 43) 8758 {"txn_stat_print", (PyCFunction)DBEnv_txn_stat_print, 8759 METH_VARARGS|METH_KEYWORDS}, 8760 #endif 8761 #if (DBVER >= 42) 8762 {"get_tx_max", (PyCFunction)DBEnv_get_tx_max, METH_NOARGS}, 8763 {"get_tx_timestamp", (PyCFunction)DBEnv_get_tx_timestamp, METH_NOARGS}, 8764 #endif 8765 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS}, 8766 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS}, 8767 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS}, 8768 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS}, 8769 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS}, 8770 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS}, 8771 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS}, 8772 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS}, 8773 #if (DBVER >= 43) 8774 {"lock_stat_print", (PyCFunction)DBEnv_lock_stat_print, 8775 METH_VARARGS|METH_KEYWORDS}, 8776 #endif 8777 {"log_cursor", (PyCFunction)DBEnv_log_cursor, METH_NOARGS}, 8778 {"log_file", (PyCFunction)DBEnv_log_file, METH_VARARGS}, 8779 #if (DBVER >= 44) 8780 {"log_printf", (PyCFunction)DBEnv_log_printf, 8781 METH_VARARGS|METH_KEYWORDS}, 8782 #endif 8783 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS}, 8784 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS}, 8785 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS}, 8786 #if (DBVER >= 43) 8787 {"log_stat_print", (PyCFunction)DBEnv_log_stat_print, 8788 METH_VARARGS|METH_KEYWORDS}, 8789 #endif 8790 #if (DBVER >= 44) 8791 {"fileid_reset", (PyCFunction)DBEnv_fileid_reset, METH_VARARGS|METH_KEYWORDS}, 8792 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS}, 8793 #endif 8794 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS}, 8795 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS}, 8796 #if (DBVER < 48) 8797 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server, 8798 METH_VARARGS|METH_KEYWORDS}, 8799 #endif 8800 #if (DBVER >= 43) 8801 {"set_mp_max_openfd", (PyCFunction)DBEnv_set_mp_max_openfd, METH_VARARGS}, 8802 {"get_mp_max_openfd", (PyCFunction)DBEnv_get_mp_max_openfd, METH_NOARGS}, 8803 {"set_mp_max_write", (PyCFunction)DBEnv_set_mp_max_write, METH_VARARGS}, 8804 {"get_mp_max_write", (PyCFunction)DBEnv_get_mp_max_write, METH_NOARGS}, 8805 #endif 8806 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS}, 8807 #if (DBVER >= 42) 8808 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS}, 8809 #endif 8810 {"set_private", (PyCFunction)DBEnv_set_private, METH_O}, 8811 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS}, 8812 {"rep_start", (PyCFunction)DBEnv_rep_start, 8813 METH_VARARGS|METH_KEYWORDS}, 8814 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS}, 8815 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message, 8816 METH_VARARGS}, 8817 #if (DBVER >= 46) 8818 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS}, 8819 #endif 8820 #if (DBVER >= 44) 8821 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS}, 8822 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS}, 8823 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS}, 8824 #endif 8825 #if (DBVER >= 45) 8826 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS}, 8827 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS}, 8828 #endif 8829 #if (DBVER >= 47) 8830 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS}, 8831 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS}, 8832 #endif 8833 #if (DBVER >= 45) 8834 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O}, 8835 #endif 8836 #if (DBVER >= 45) 8837 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS}, 8838 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS}, 8839 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS}, 8840 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS}, 8841 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS}, 8842 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS}, 8843 #endif 8844 #if (DBVER >= 47) 8845 {"rep_set_clockskew", (PyCFunction)DBEnv_rep_set_clockskew, METH_VARARGS}, 8846 {"rep_get_clockskew", (PyCFunction)DBEnv_rep_get_clockskew, METH_VARARGS}, 8847 #endif 8848 {"rep_stat", (PyCFunction)DBEnv_rep_stat, 8849 METH_VARARGS|METH_KEYWORDS}, 8850 #if (DBVER >= 43) 8851 {"rep_stat_print", (PyCFunction)DBEnv_rep_stat_print, 8852 METH_VARARGS|METH_KEYWORDS}, 8853 #endif 8854 8855 #if (DBVER >= 45) 8856 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start, 8857 METH_VARARGS|METH_KEYWORDS}, 8858 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site, 8859 METH_VARARGS|METH_KEYWORDS}, 8860 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site, 8861 METH_VARARGS|METH_KEYWORDS}, 8862 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy, 8863 METH_VARARGS}, 8864 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy, 8865 METH_NOARGS}, 8866 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list, 8867 METH_NOARGS}, 8868 #endif 8869 #if (DBVER >= 46) 8870 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat, 8871 METH_VARARGS|METH_KEYWORDS}, 8872 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print, 8873 METH_VARARGS|METH_KEYWORDS}, 8874 #endif 8875 {NULL, NULL} /* sentinel */ 8876 }; 8877 8878 8879 static PyMethodDef DBTxn_methods[] = { 8880 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS}, 8881 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS}, 8882 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS}, 8883 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS}, 8884 {"id", (PyCFunction)DBTxn_id, METH_NOARGS}, 8885 {"set_timeout", (PyCFunction)DBTxn_set_timeout, 8886 METH_VARARGS|METH_KEYWORDS}, 8887 #if (DBVER >= 44) 8888 {"set_name", (PyCFunction)DBTxn_set_name, METH_VARARGS}, 8889 {"get_name", (PyCFunction)DBTxn_get_name, METH_NOARGS}, 8890 #endif 8891 {NULL, NULL} /* sentinel */ 8892 }; 8893 8894 8895 #if (DBVER >= 43) 8896 static PyMethodDef DBSequence_methods[] = { 8897 {"close", (PyCFunction)DBSequence_close, METH_VARARGS}, 8898 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS}, 8899 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS}, 8900 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS}, 8901 {"initial_value", (PyCFunction)DBSequence_initial_value, METH_VARARGS}, 8902 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS}, 8903 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS}, 8904 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS}, 8905 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS}, 8906 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS}, 8907 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS}, 8908 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS}, 8909 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS}, 8910 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS}, 8911 {"stat_print", (PyCFunction)DBSequence_stat_print, 8912 METH_VARARGS|METH_KEYWORDS}, 8913 {NULL, NULL} /* sentinel */ 8914 }; 8915 #endif 8916 8917 8918 static PyObject* 8919 DBEnv_db_home_get(DBEnvObject* self) 8920 { 8921 const char *home = NULL; 8922 8923 CHECK_ENV_NOT_CLOSED(self); 8924 8925 #if (DBVER >= 42) 8926 MYDB_BEGIN_ALLOW_THREADS; 8927 self->db_env->get_home(self->db_env, &home); 8928 MYDB_END_ALLOW_THREADS; 8929 #else 8930 home=self->db_env->db_home; 8931 #endif 8932 8933 if (home == NULL) { 8934 RETURN_NONE(); 8935 } 8936 return PyBytes_FromString(home); 8937 } 8938 8939 static PyGetSetDef DBEnv_getsets[] = { 8940 {"db_home", (getter)DBEnv_db_home_get, NULL,}, 8941 {NULL} 8942 }; 8943 8944 8945 statichere PyTypeObject DB_Type = { 8946 #if (PY_VERSION_HEX < 0x03000000) 8947 PyObject_HEAD_INIT(NULL) 8948 0, /*ob_size*/ 8949 #else 8950 PyVarObject_HEAD_INIT(NULL, 0) 8951 #endif 8952 "DB", /*tp_name*/ 8953 sizeof(DBObject), /*tp_basicsize*/ 8954 0, /*tp_itemsize*/ 8955 /* methods */ 8956 (destructor)DB_dealloc, /*tp_dealloc*/ 8957 0, /*tp_print*/ 8958 0, /*tp_getattr*/ 8959 0, /*tp_setattr*/ 8960 0, /*tp_compare*/ 8961 0, /*tp_repr*/ 8962 0, /*tp_as_number*/ 8963 &DB_sequence,/*tp_as_sequence*/ 8964 &DB_mapping,/*tp_as_mapping*/ 8965 0, /*tp_hash*/ 8966 0, /* tp_call */ 8967 0, /* tp_str */ 8968 0, /* tp_getattro */ 8969 0, /* tp_setattro */ 8970 0, /* tp_as_buffer */ 8971 #if (PY_VERSION_HEX < 0x03000000) 8972 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 8973 #else 8974 Py_TPFLAGS_DEFAULT, /* tp_flags */ 8975 #endif 8976 0, /* tp_doc */ 8977 0, /* tp_traverse */ 8978 0, /* tp_clear */ 8979 0, /* tp_richcompare */ 8980 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */ 8981 0, /*tp_iter*/ 8982 0, /*tp_iternext*/ 8983 DB_methods, /*tp_methods*/ 8984 0, /*tp_members*/ 8985 }; 8986 8987 8988 statichere PyTypeObject DBCursor_Type = { 8989 #if (PY_VERSION_HEX < 0x03000000) 8990 PyObject_HEAD_INIT(NULL) 8991 0, /*ob_size*/ 8992 #else 8993 PyVarObject_HEAD_INIT(NULL, 0) 8994 #endif 8995 "DBCursor", /*tp_name*/ 8996 sizeof(DBCursorObject), /*tp_basicsize*/ 8997 0, /*tp_itemsize*/ 8998 /* methods */ 8999 (destructor)DBCursor_dealloc,/*tp_dealloc*/ 9000 0, /*tp_print*/ 9001 0, /*tp_getattr*/ 9002 0, /*tp_setattr*/ 9003 0, /*tp_compare*/ 9004 0, /*tp_repr*/ 9005 0, /*tp_as_number*/ 9006 0, /*tp_as_sequence*/ 9007 0, /*tp_as_mapping*/ 9008 0, /*tp_hash*/ 9009 0, /*tp_call*/ 9010 0, /*tp_str*/ 9011 0, /*tp_getattro*/ 9012 0, /*tp_setattro*/ 9013 0, /*tp_as_buffer*/ 9014 #if (PY_VERSION_HEX < 0x03000000) 9015 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 9016 #else 9017 Py_TPFLAGS_DEFAULT, /* tp_flags */ 9018 #endif 9019 0, /* tp_doc */ 9020 0, /* tp_traverse */ 9021 0, /* tp_clear */ 9022 0, /* tp_richcompare */ 9023 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */ 9024 0, /*tp_iter*/ 9025 0, /*tp_iternext*/ 9026 DBCursor_methods, /*tp_methods*/ 9027 0, /*tp_members*/ 9028 }; 9029 9030 9031 statichere PyTypeObject DBLogCursor_Type = { 9032 #if (PY_VERSION_HEX < 0x03000000) 9033 PyObject_HEAD_INIT(NULL) 9034 0, /*ob_size*/ 9035 #else 9036 PyVarObject_HEAD_INIT(NULL, 0) 9037 #endif 9038 "DBLogCursor", /*tp_name*/ 9039 sizeof(DBLogCursorObject), /*tp_basicsize*/ 9040 0, /*tp_itemsize*/ 9041 /* methods */ 9042 (destructor)DBLogCursor_dealloc,/*tp_dealloc*/ 9043 0, /*tp_print*/ 9044 0, /*tp_getattr*/ 9045 0, /*tp_setattr*/ 9046 0, /*tp_compare*/ 9047 0, /*tp_repr*/ 9048 0, /*tp_as_number*/ 9049 0, /*tp_as_sequence*/ 9050 0, /*tp_as_mapping*/ 9051 0, /*tp_hash*/ 9052 0, /*tp_call*/ 9053 0, /*tp_str*/ 9054 0, /*tp_getattro*/ 9055 0, /*tp_setattro*/ 9056 0, /*tp_as_buffer*/ 9057 #if (PY_VERSION_HEX < 0x03000000) 9058 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 9059 #else 9060 Py_TPFLAGS_DEFAULT, /* tp_flags */ 9061 #endif 9062 0, /* tp_doc */ 9063 0, /* tp_traverse */ 9064 0, /* tp_clear */ 9065 0, /* tp_richcompare */ 9066 offsetof(DBLogCursorObject, in_weakreflist), /* tp_weaklistoffset */ 9067 0, /*tp_iter*/ 9068 0, /*tp_iternext*/ 9069 DBLogCursor_methods, /*tp_methods*/ 9070 0, /*tp_members*/ 9071 }; 9072 9073 9074 statichere PyTypeObject DBEnv_Type = { 9075 #if (PY_VERSION_HEX < 0x03000000) 9076 PyObject_HEAD_INIT(NULL) 9077 0, /*ob_size*/ 9078 #else 9079 PyVarObject_HEAD_INIT(NULL, 0) 9080 #endif 9081 "DBEnv", /*tp_name*/ 9082 sizeof(DBEnvObject), /*tp_basicsize*/ 9083 0, /*tp_itemsize*/ 9084 /* methods */ 9085 (destructor)DBEnv_dealloc, /*tp_dealloc*/ 9086 0, /*tp_print*/ 9087 0, /*tp_getattr*/ 9088 0, /*tp_setattr*/ 9089 0, /*tp_compare*/ 9090 0, /*tp_repr*/ 9091 0, /*tp_as_number*/ 9092 0, /*tp_as_sequence*/ 9093 0, /*tp_as_mapping*/ 9094 0, /*tp_hash*/ 9095 0, /* tp_call */ 9096 0, /* tp_str */ 9097 0, /* tp_getattro */ 9098 0, /* tp_setattro */ 9099 0, /* tp_as_buffer */ 9100 #if (PY_VERSION_HEX < 0x03000000) 9101 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 9102 #else 9103 Py_TPFLAGS_DEFAULT, /* tp_flags */ 9104 #endif 9105 0, /* tp_doc */ 9106 0, /* tp_traverse */ 9107 0, /* tp_clear */ 9108 0, /* tp_richcompare */ 9109 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */ 9110 0, /* tp_iter */ 9111 0, /* tp_iternext */ 9112 DBEnv_methods, /* tp_methods */ 9113 0, /* tp_members */ 9114 DBEnv_getsets, /* tp_getsets */ 9115 }; 9116 9117 statichere PyTypeObject DBTxn_Type = { 9118 #if (PY_VERSION_HEX < 0x03000000) 9119 PyObject_HEAD_INIT(NULL) 9120 0, /*ob_size*/ 9121 #else 9122 PyVarObject_HEAD_INIT(NULL, 0) 9123 #endif 9124 "DBTxn", /*tp_name*/ 9125 sizeof(DBTxnObject), /*tp_basicsize*/ 9126 0, /*tp_itemsize*/ 9127 /* methods */ 9128 (destructor)DBTxn_dealloc, /*tp_dealloc*/ 9129 0, /*tp_print*/ 9130 0, /*tp_getattr*/ 9131 0, /*tp_setattr*/ 9132 0, /*tp_compare*/ 9133 0, /*tp_repr*/ 9134 0, /*tp_as_number*/ 9135 0, /*tp_as_sequence*/ 9136 0, /*tp_as_mapping*/ 9137 0, /*tp_hash*/ 9138 0, /* tp_call */ 9139 0, /* tp_str */ 9140 0, /* tp_getattro */ 9141 0, /* tp_setattro */ 9142 0, /* tp_as_buffer */ 9143 #if (PY_VERSION_HEX < 0x03000000) 9144 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 9145 #else 9146 Py_TPFLAGS_DEFAULT, /* tp_flags */ 9147 #endif 9148 0, /* tp_doc */ 9149 0, /* tp_traverse */ 9150 0, /* tp_clear */ 9151 0, /* tp_richcompare */ 9152 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */ 9153 0, /*tp_iter*/ 9154 0, /*tp_iternext*/ 9155 DBTxn_methods, /*tp_methods*/ 9156 0, /*tp_members*/ 9157 }; 9158 9159 9160 statichere PyTypeObject DBLock_Type = { 9161 #if (PY_VERSION_HEX < 0x03000000) 9162 PyObject_HEAD_INIT(NULL) 9163 0, /*ob_size*/ 9164 #else 9165 PyVarObject_HEAD_INIT(NULL, 0) 9166 #endif 9167 "DBLock", /*tp_name*/ 9168 sizeof(DBLockObject), /*tp_basicsize*/ 9169 0, /*tp_itemsize*/ 9170 /* methods */ 9171 (destructor)DBLock_dealloc, /*tp_dealloc*/ 9172 0, /*tp_print*/ 9173 0, /*tp_getattr*/ 9174 0, /*tp_setattr*/ 9175 0, /*tp_compare*/ 9176 0, /*tp_repr*/ 9177 0, /*tp_as_number*/ 9178 0, /*tp_as_sequence*/ 9179 0, /*tp_as_mapping*/ 9180 0, /*tp_hash*/ 9181 0, /* tp_call */ 9182 0, /* tp_str */ 9183 0, /* tp_getattro */ 9184 0, /* tp_setattro */ 9185 0, /* tp_as_buffer */ 9186 #if (PY_VERSION_HEX < 0x03000000) 9187 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 9188 #else 9189 Py_TPFLAGS_DEFAULT, /* tp_flags */ 9190 #endif 9191 0, /* tp_doc */ 9192 0, /* tp_traverse */ 9193 0, /* tp_clear */ 9194 0, /* tp_richcompare */ 9195 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */ 9196 }; 9197 9198 #if (DBVER >= 43) 9199 statichere PyTypeObject DBSequence_Type = { 9200 #if (PY_VERSION_HEX < 0x03000000) 9201 PyObject_HEAD_INIT(NULL) 9202 0, /*ob_size*/ 9203 #else 9204 PyVarObject_HEAD_INIT(NULL, 0) 9205 #endif 9206 "DBSequence", /*tp_name*/ 9207 sizeof(DBSequenceObject), /*tp_basicsize*/ 9208 0, /*tp_itemsize*/ 9209 /* methods */ 9210 (destructor)DBSequence_dealloc, /*tp_dealloc*/ 9211 0, /*tp_print*/ 9212 0, /*tp_getattr*/ 9213 0, /*tp_setattr*/ 9214 0, /*tp_compare*/ 9215 0, /*tp_repr*/ 9216 0, /*tp_as_number*/ 9217 0, /*tp_as_sequence*/ 9218 0, /*tp_as_mapping*/ 9219 0, /*tp_hash*/ 9220 0, /* tp_call */ 9221 0, /* tp_str */ 9222 0, /* tp_getattro */ 9223 0, /* tp_setattro */ 9224 0, /* tp_as_buffer */ 9225 #if (PY_VERSION_HEX < 0x03000000) 9226 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ 9227 #else 9228 Py_TPFLAGS_DEFAULT, /* tp_flags */ 9229 #endif 9230 0, /* tp_doc */ 9231 0, /* tp_traverse */ 9232 0, /* tp_clear */ 9233 0, /* tp_richcompare */ 9234 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */ 9235 0, /*tp_iter*/ 9236 0, /*tp_iternext*/ 9237 DBSequence_methods, /*tp_methods*/ 9238 0, /*tp_members*/ 9239 }; 9240 #endif 9241 9242 /* --------------------------------------------------------------------- */ 9243 /* Module-level functions */ 9244 9245 static PyObject* 9246 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs) 9247 { 9248 PyObject* dbenvobj = NULL; 9249 int flags = 0; 9250 static char* kwnames[] = { "dbEnv", "flags", NULL}; 9251 9252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames, 9253 &dbenvobj, &flags)) 9254 return NULL; 9255 if (dbenvobj == Py_None) 9256 dbenvobj = NULL; 9257 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) { 9258 makeTypeError("DBEnv", dbenvobj); 9259 return NULL; 9260 } 9261 9262 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags); 9263 } 9264 9265 9266 static PyObject* 9267 DBEnv_construct(PyObject* self, PyObject* args) 9268 { 9269 int flags = 0; 9270 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL; 9271 return (PyObject* )newDBEnvObject(flags); 9272 } 9273 9274 #if (DBVER >= 43) 9275 static PyObject* 9276 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs) 9277 { 9278 PyObject* dbobj; 9279 int flags = 0; 9280 static char* kwnames[] = { "db", "flags", NULL}; 9281 9282 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags)) 9283 return NULL; 9284 if (!DBObject_Check(dbobj)) { 9285 makeTypeError("DB", dbobj); 9286 return NULL; 9287 } 9288 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags); 9289 } 9290 #endif 9291 9292 static char bsddb_version_doc[] = 9293 "Returns a tuple of major, minor, and patch release numbers of the\n\ 9294 underlying DB library."; 9295 9296 static PyObject* 9297 bsddb_version(PyObject* self) 9298 { 9299 int major, minor, patch; 9300 9301 db_version(&major, &minor, &patch); 9302 return Py_BuildValue("(iii)", major, minor, patch); 9303 } 9304 9305 9306 /* List of functions defined in the module */ 9307 static PyMethodDef bsddb_methods[] = { 9308 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS }, 9309 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS}, 9310 #if (DBVER >= 43) 9311 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS }, 9312 #endif 9313 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc}, 9314 {NULL, NULL} /* sentinel */ 9315 }; 9316 9317 9318 /* API structure */ 9319 static BSDDB_api bsddb_api; 9320 9321 9322 /* --------------------------------------------------------------------- */ 9323 /* Module initialization */ 9324 9325 9326 /* Convenience routine to export an integer value. 9327 * Errors are silently ignored, for better or for worse... 9328 */ 9329 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME) 9330 9331 #define MODULE_NAME_MAX_LEN 11 9332 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb"; 9333 9334 #if (PY_VERSION_HEX >= 0x03000000) 9335 static struct PyModuleDef bsddbmodule = { 9336 PyModuleDef_HEAD_INIT, 9337 _bsddbModuleName, /* Name of module */ 9338 NULL, /* module documentation, may be NULL */ 9339 -1, /* size of per-interpreter state of the module, 9340 or -1 if the module keeps state in global variables. */ 9341 bsddb_methods, 9342 NULL, /* Reload */ 9343 NULL, /* Traverse */ 9344 NULL, /* Clear */ 9345 NULL /* Free */ 9346 }; 9347 #endif 9348 9349 9350 #if (PY_VERSION_HEX < 0x03000000) 9351 DL_EXPORT(void) init_bsddb(void) 9352 #else 9353 PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */ 9354 #endif 9355 { 9356 PyObject* m; 9357 PyObject* d; 9358 PyObject* py_api; 9359 PyObject* pybsddb_version_s; 9360 PyObject* db_version_s; 9361 PyObject* cvsid_s; 9362 9363 #if (PY_VERSION_HEX < 0x03000000) 9364 pybsddb_version_s = PyString_FromString(PY_BSDDB_VERSION); 9365 db_version_s = PyString_FromString(DB_VERSION_STRING); 9366 cvsid_s = PyString_FromString(rcs_id); 9367 #else 9368 /* This data should be ascii, so UTF-8 conversion is fine */ 9369 pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION); 9370 db_version_s = PyUnicode_FromString(DB_VERSION_STRING); 9371 cvsid_s = PyUnicode_FromString(rcs_id); 9372 #endif 9373 9374 /* Initialize object types */ 9375 if ((PyType_Ready(&DB_Type) < 0) 9376 || (PyType_Ready(&DBCursor_Type) < 0) 9377 || (PyType_Ready(&DBLogCursor_Type) < 0) 9378 || (PyType_Ready(&DBEnv_Type) < 0) 9379 || (PyType_Ready(&DBTxn_Type) < 0) 9380 || (PyType_Ready(&DBLock_Type) < 0) 9381 #if (DBVER >= 43) 9382 || (PyType_Ready(&DBSequence_Type) < 0) 9383 #endif 9384 ) { 9385 #if (PY_VERSION_HEX < 0x03000000) 9386 return; 9387 #else 9388 return NULL; 9389 #endif 9390 } 9391 9392 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE) 9393 /* Save the current interpreter, so callbacks can do the right thing. */ 9394 _db_interpreterState = PyThreadState_GET()->interp; 9395 #endif 9396 9397 /* Create the module and add the functions */ 9398 #if (PY_VERSION_HEX < 0x03000000) 9399 m = Py_InitModule(_bsddbModuleName, bsddb_methods); 9400 #else 9401 m=PyModule_Create(&bsddbmodule); 9402 #endif 9403 if (m == NULL) { 9404 #if (PY_VERSION_HEX < 0x03000000) 9405 return; 9406 #else 9407 return NULL; 9408 #endif 9409 } 9410 9411 /* Add some symbolic constants to the module */ 9412 d = PyModule_GetDict(m); 9413 PyDict_SetItemString(d, "__version__", pybsddb_version_s); 9414 PyDict_SetItemString(d, "cvsid", cvsid_s); 9415 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s); 9416 Py_DECREF(pybsddb_version_s); 9417 pybsddb_version_s = NULL; 9418 Py_DECREF(cvsid_s); 9419 cvsid_s = NULL; 9420 Py_DECREF(db_version_s); 9421 db_version_s = NULL; 9422 9423 ADD_INT(d, DB_VERSION_MAJOR); 9424 ADD_INT(d, DB_VERSION_MINOR); 9425 ADD_INT(d, DB_VERSION_PATCH); 9426 9427 ADD_INT(d, DB_MAX_PAGES); 9428 ADD_INT(d, DB_MAX_RECORDS); 9429 9430 #if (DBVER < 48) 9431 #if (DBVER >= 42) 9432 ADD_INT(d, DB_RPCCLIENT); 9433 #else 9434 ADD_INT(d, DB_CLIENT); 9435 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */ 9436 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT); 9437 #endif 9438 #endif 9439 9440 #if (DBVER < 48) 9441 ADD_INT(d, DB_XA_CREATE); 9442 #endif 9443 9444 ADD_INT(d, DB_CREATE); 9445 ADD_INT(d, DB_NOMMAP); 9446 ADD_INT(d, DB_THREAD); 9447 #if (DBVER >= 45) 9448 ADD_INT(d, DB_MULTIVERSION); 9449 #endif 9450 9451 ADD_INT(d, DB_FORCE); 9452 ADD_INT(d, DB_INIT_CDB); 9453 ADD_INT(d, DB_INIT_LOCK); 9454 ADD_INT(d, DB_INIT_LOG); 9455 ADD_INT(d, DB_INIT_MPOOL); 9456 ADD_INT(d, DB_INIT_TXN); 9457 ADD_INT(d, DB_JOINENV); 9458 9459 #if (DBVER >= 48) 9460 ADD_INT(d, DB_GID_SIZE); 9461 #else 9462 ADD_INT(d, DB_XIDDATASIZE); 9463 /* Allow new code to work in old BDB releases */ 9464 _addIntToDict(d, "DB_GID_SIZE", DB_XIDDATASIZE); 9465 #endif 9466 9467 ADD_INT(d, DB_RECOVER); 9468 ADD_INT(d, DB_RECOVER_FATAL); 9469 ADD_INT(d, DB_TXN_NOSYNC); 9470 ADD_INT(d, DB_USE_ENVIRON); 9471 ADD_INT(d, DB_USE_ENVIRON_ROOT); 9472 9473 ADD_INT(d, DB_LOCKDOWN); 9474 ADD_INT(d, DB_PRIVATE); 9475 ADD_INT(d, DB_SYSTEM_MEM); 9476 9477 ADD_INT(d, DB_TXN_SYNC); 9478 ADD_INT(d, DB_TXN_NOWAIT); 9479 9480 #if (DBVER >= 46) 9481 ADD_INT(d, DB_TXN_WAIT); 9482 #endif 9483 9484 ADD_INT(d, DB_EXCL); 9485 ADD_INT(d, DB_FCNTL_LOCKING); 9486 ADD_INT(d, DB_ODDFILESIZE); 9487 ADD_INT(d, DB_RDWRMASTER); 9488 ADD_INT(d, DB_RDONLY); 9489 ADD_INT(d, DB_TRUNCATE); 9490 ADD_INT(d, DB_EXTENT); 9491 ADD_INT(d, DB_CDB_ALLDB); 9492 ADD_INT(d, DB_VERIFY); 9493 ADD_INT(d, DB_UPGRADE); 9494 9495 ADD_INT(d, DB_PRINTABLE); 9496 ADD_INT(d, DB_AGGRESSIVE); 9497 ADD_INT(d, DB_NOORDERCHK); 9498 ADD_INT(d, DB_ORDERCHKONLY); 9499 ADD_INT(d, DB_PR_PAGE); 9500 9501 ADD_INT(d, DB_PR_RECOVERYTEST); 9502 ADD_INT(d, DB_SALVAGE); 9503 9504 ADD_INT(d, DB_LOCK_NORUN); 9505 ADD_INT(d, DB_LOCK_DEFAULT); 9506 ADD_INT(d, DB_LOCK_OLDEST); 9507 ADD_INT(d, DB_LOCK_RANDOM); 9508 ADD_INT(d, DB_LOCK_YOUNGEST); 9509 ADD_INT(d, DB_LOCK_MAXLOCKS); 9510 ADD_INT(d, DB_LOCK_MINLOCKS); 9511 ADD_INT(d, DB_LOCK_MINWRITE); 9512 9513 ADD_INT(d, DB_LOCK_EXPIRE); 9514 #if (DBVER >= 43) 9515 ADD_INT(d, DB_LOCK_MAXWRITE); 9516 #endif 9517 9518 _addIntToDict(d, "DB_LOCK_CONFLICT", 0); 9519 9520 ADD_INT(d, DB_LOCK_DUMP); 9521 ADD_INT(d, DB_LOCK_GET); 9522 ADD_INT(d, DB_LOCK_INHERIT); 9523 ADD_INT(d, DB_LOCK_PUT); 9524 ADD_INT(d, DB_LOCK_PUT_ALL); 9525 ADD_INT(d, DB_LOCK_PUT_OBJ); 9526 9527 ADD_INT(d, DB_LOCK_NG); 9528 ADD_INT(d, DB_LOCK_READ); 9529 ADD_INT(d, DB_LOCK_WRITE); 9530 ADD_INT(d, DB_LOCK_NOWAIT); 9531 ADD_INT(d, DB_LOCK_WAIT); 9532 ADD_INT(d, DB_LOCK_IWRITE); 9533 ADD_INT(d, DB_LOCK_IREAD); 9534 ADD_INT(d, DB_LOCK_IWR); 9535 #if (DBVER < 44) 9536 ADD_INT(d, DB_LOCK_DIRTY); 9537 #else 9538 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */ 9539 #endif 9540 ADD_INT(d, DB_LOCK_WWRITE); 9541 9542 ADD_INT(d, DB_LOCK_RECORD); 9543 ADD_INT(d, DB_LOCK_UPGRADE); 9544 ADD_INT(d, DB_LOCK_SWITCH); 9545 ADD_INT(d, DB_LOCK_UPGRADE_WRITE); 9546 9547 ADD_INT(d, DB_LOCK_NOWAIT); 9548 ADD_INT(d, DB_LOCK_RECORD); 9549 ADD_INT(d, DB_LOCK_UPGRADE); 9550 9551 ADD_INT(d, DB_LSTAT_ABORTED); 9552 #if (DBVER < 43) 9553 ADD_INT(d, DB_LSTAT_ERR); 9554 #endif 9555 ADD_INT(d, DB_LSTAT_FREE); 9556 ADD_INT(d, DB_LSTAT_HELD); 9557 9558 ADD_INT(d, DB_LSTAT_PENDING); 9559 ADD_INT(d, DB_LSTAT_WAITING); 9560 9561 ADD_INT(d, DB_ARCH_ABS); 9562 ADD_INT(d, DB_ARCH_DATA); 9563 ADD_INT(d, DB_ARCH_LOG); 9564 #if (DBVER >= 42) 9565 ADD_INT(d, DB_ARCH_REMOVE); 9566 #endif 9567 9568 ADD_INT(d, DB_BTREE); 9569 ADD_INT(d, DB_HASH); 9570 ADD_INT(d, DB_RECNO); 9571 ADD_INT(d, DB_QUEUE); 9572 ADD_INT(d, DB_UNKNOWN); 9573 9574 ADD_INT(d, DB_DUP); 9575 ADD_INT(d, DB_DUPSORT); 9576 ADD_INT(d, DB_RECNUM); 9577 ADD_INT(d, DB_RENUMBER); 9578 ADD_INT(d, DB_REVSPLITOFF); 9579 ADD_INT(d, DB_SNAPSHOT); 9580 9581 #if (DBVER >= 43) 9582 ADD_INT(d, DB_INORDER); 9583 #endif 9584 9585 ADD_INT(d, DB_JOIN_NOSORT); 9586 9587 ADD_INT(d, DB_AFTER); 9588 ADD_INT(d, DB_APPEND); 9589 ADD_INT(d, DB_BEFORE); 9590 #if (DBVER < 45) 9591 ADD_INT(d, DB_CACHED_COUNTS); 9592 #endif 9593 9594 #if (DBVER <= 41) 9595 ADD_INT(d, DB_COMMIT); 9596 #endif 9597 ADD_INT(d, DB_CONSUME); 9598 ADD_INT(d, DB_CONSUME_WAIT); 9599 ADD_INT(d, DB_CURRENT); 9600 ADD_INT(d, DB_FAST_STAT); 9601 ADD_INT(d, DB_FIRST); 9602 ADD_INT(d, DB_FLUSH); 9603 ADD_INT(d, DB_GET_BOTH); 9604 ADD_INT(d, DB_GET_BOTH_RANGE); 9605 ADD_INT(d, DB_GET_RECNO); 9606 ADD_INT(d, DB_JOIN_ITEM); 9607 ADD_INT(d, DB_KEYFIRST); 9608 ADD_INT(d, DB_KEYLAST); 9609 ADD_INT(d, DB_LAST); 9610 ADD_INT(d, DB_NEXT); 9611 ADD_INT(d, DB_NEXT_DUP); 9612 ADD_INT(d, DB_NEXT_NODUP); 9613 ADD_INT(d, DB_NODUPDATA); 9614 ADD_INT(d, DB_NOOVERWRITE); 9615 ADD_INT(d, DB_NOSYNC); 9616 ADD_INT(d, DB_POSITION); 9617 ADD_INT(d, DB_PREV); 9618 ADD_INT(d, DB_PREV_NODUP); 9619 #if (DBVER >= 46) 9620 ADD_INT(d, DB_PREV_DUP); 9621 #endif 9622 #if (DBVER < 45) 9623 ADD_INT(d, DB_RECORDCOUNT); 9624 #endif 9625 ADD_INT(d, DB_SET); 9626 ADD_INT(d, DB_SET_RANGE); 9627 ADD_INT(d, DB_SET_RECNO); 9628 ADD_INT(d, DB_WRITECURSOR); 9629 9630 ADD_INT(d, DB_OPFLAGS_MASK); 9631 ADD_INT(d, DB_RMW); 9632 ADD_INT(d, DB_DIRTY_READ); 9633 ADD_INT(d, DB_MULTIPLE); 9634 ADD_INT(d, DB_MULTIPLE_KEY); 9635 9636 #if (DBVER >= 44) 9637 ADD_INT(d, DB_IMMUTABLE_KEY); 9638 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */ 9639 ADD_INT(d, DB_READ_COMMITTED); 9640 #endif 9641 9642 #if (DBVER >= 44) 9643 ADD_INT(d, DB_FREELIST_ONLY); 9644 ADD_INT(d, DB_FREE_SPACE); 9645 #endif 9646 9647 ADD_INT(d, DB_DONOTINDEX); 9648 9649 ADD_INT(d, DB_KEYEMPTY); 9650 ADD_INT(d, DB_KEYEXIST); 9651 ADD_INT(d, DB_LOCK_DEADLOCK); 9652 ADD_INT(d, DB_LOCK_NOTGRANTED); 9653 ADD_INT(d, DB_NOSERVER); 9654 ADD_INT(d, DB_NOSERVER_HOME); 9655 ADD_INT(d, DB_NOSERVER_ID); 9656 ADD_INT(d, DB_NOTFOUND); 9657 ADD_INT(d, DB_OLD_VERSION); 9658 ADD_INT(d, DB_RUNRECOVERY); 9659 ADD_INT(d, DB_VERIFY_BAD); 9660 ADD_INT(d, DB_PAGE_NOTFOUND); 9661 ADD_INT(d, DB_SECONDARY_BAD); 9662 ADD_INT(d, DB_STAT_CLEAR); 9663 ADD_INT(d, DB_REGION_INIT); 9664 ADD_INT(d, DB_NOLOCKING); 9665 ADD_INT(d, DB_YIELDCPU); 9666 ADD_INT(d, DB_PANIC_ENVIRONMENT); 9667 ADD_INT(d, DB_NOPANIC); 9668 9669 ADD_INT(d, DB_OVERWRITE); 9670 9671 #if (DBVER >= 43) 9672 ADD_INT(d, DB_STAT_SUBSYSTEM); 9673 ADD_INT(d, DB_STAT_MEMP_HASH); 9674 #endif 9675 9676 #if (DBVER >= 48) 9677 ADD_INT(d, DB_OVERWRITE_DUP); 9678 #endif 9679 9680 #if (DBVER >= 47) 9681 ADD_INT(d, DB_FOREIGN_ABORT); 9682 ADD_INT(d, DB_FOREIGN_CASCADE); 9683 ADD_INT(d, DB_FOREIGN_NULLIFY); 9684 #endif 9685 9686 #if (DBVER >= 44) 9687 ADD_INT(d, DB_REGISTER); 9688 #endif 9689 9690 ADD_INT(d, DB_EID_INVALID); 9691 ADD_INT(d, DB_EID_BROADCAST); 9692 9693 #if (DBVER >= 42) 9694 ADD_INT(d, DB_TIME_NOTGRANTED); 9695 ADD_INT(d, DB_TXN_NOT_DURABLE); 9696 ADD_INT(d, DB_TXN_WRITE_NOSYNC); 9697 ADD_INT(d, DB_DIRECT_DB); 9698 ADD_INT(d, DB_INIT_REP); 9699 ADD_INT(d, DB_ENCRYPT); 9700 ADD_INT(d, DB_CHKSUM); 9701 #endif 9702 9703 #if (DBVER >= 42) && (DBVER < 47) 9704 ADD_INT(d, DB_LOG_AUTOREMOVE); 9705 ADD_INT(d, DB_DIRECT_LOG); 9706 #endif 9707 9708 #if (DBVER >= 47) 9709 ADD_INT(d, DB_LOG_DIRECT); 9710 ADD_INT(d, DB_LOG_DSYNC); 9711 ADD_INT(d, DB_LOG_IN_MEMORY); 9712 ADD_INT(d, DB_LOG_AUTO_REMOVE); 9713 ADD_INT(d, DB_LOG_ZERO); 9714 #endif 9715 9716 #if (DBVER >= 44) 9717 ADD_INT(d, DB_DSYNC_DB); 9718 #endif 9719 9720 #if (DBVER >= 45) 9721 ADD_INT(d, DB_TXN_SNAPSHOT); 9722 #endif 9723 9724 ADD_INT(d, DB_VERB_DEADLOCK); 9725 #if (DBVER >= 46) 9726 ADD_INT(d, DB_VERB_FILEOPS); 9727 ADD_INT(d, DB_VERB_FILEOPS_ALL); 9728 #endif 9729 ADD_INT(d, DB_VERB_RECOVERY); 9730 #if (DBVER >= 44) 9731 ADD_INT(d, DB_VERB_REGISTER); 9732 #endif 9733 ADD_INT(d, DB_VERB_REPLICATION); 9734 ADD_INT(d, DB_VERB_WAITSFOR); 9735 9736 #if (DBVER >= 45) 9737 ADD_INT(d, DB_EVENT_PANIC); 9738 ADD_INT(d, DB_EVENT_REP_CLIENT); 9739 #if (DBVER >= 46) 9740 ADD_INT(d, DB_EVENT_REP_ELECTED); 9741 #endif 9742 ADD_INT(d, DB_EVENT_REP_MASTER); 9743 ADD_INT(d, DB_EVENT_REP_NEWMASTER); 9744 #if (DBVER >= 46) 9745 ADD_INT(d, DB_EVENT_REP_PERM_FAILED); 9746 #endif 9747 ADD_INT(d, DB_EVENT_REP_STARTUPDONE); 9748 ADD_INT(d, DB_EVENT_WRITE_FAILED); 9749 #endif 9750 9751 ADD_INT(d, DB_REP_DUPMASTER); 9752 ADD_INT(d, DB_REP_HOLDELECTION); 9753 #if (DBVER >= 44) 9754 ADD_INT(d, DB_REP_IGNORE); 9755 ADD_INT(d, DB_REP_JOIN_FAILURE); 9756 #endif 9757 #if (DBVER >= 42) 9758 ADD_INT(d, DB_REP_ISPERM); 9759 ADD_INT(d, DB_REP_NOTPERM); 9760 #endif 9761 ADD_INT(d, DB_REP_NEWSITE); 9762 9763 ADD_INT(d, DB_REP_MASTER); 9764 ADD_INT(d, DB_REP_CLIENT); 9765 9766 ADD_INT(d, DB_REP_PERMANENT); 9767 9768 #if (DBVER >= 44) 9769 ADD_INT(d, DB_REP_CONF_NOAUTOINIT); 9770 ADD_INT(d, DB_REP_CONF_DELAYCLIENT); 9771 ADD_INT(d, DB_REP_CONF_BULK); 9772 ADD_INT(d, DB_REP_CONF_NOWAIT); 9773 ADD_INT(d, DB_REP_ANYWHERE); 9774 ADD_INT(d, DB_REP_REREQUEST); 9775 #endif 9776 9777 #if (DBVER >= 42) 9778 ADD_INT(d, DB_REP_NOBUFFER); 9779 #endif 9780 9781 #if (DBVER >= 46) 9782 ADD_INT(d, DB_REP_LEASE_EXPIRED); 9783 ADD_INT(d, DB_IGNORE_LEASE); 9784 #endif 9785 9786 #if (DBVER >= 47) 9787 ADD_INT(d, DB_REP_CONF_LEASE); 9788 ADD_INT(d, DB_REPMGR_CONF_2SITE_STRICT); 9789 #endif 9790 9791 #if (DBVER >= 45) 9792 ADD_INT(d, DB_REP_ELECTION); 9793 9794 ADD_INT(d, DB_REP_ACK_TIMEOUT); 9795 ADD_INT(d, DB_REP_CONNECTION_RETRY); 9796 ADD_INT(d, DB_REP_ELECTION_TIMEOUT); 9797 ADD_INT(d, DB_REP_ELECTION_RETRY); 9798 #endif 9799 #if (DBVER >= 46) 9800 ADD_INT(d, DB_REP_CHECKPOINT_DELAY); 9801 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT); 9802 ADD_INT(d, DB_REP_LEASE_TIMEOUT); 9803 #endif 9804 #if (DBVER >= 47) 9805 ADD_INT(d, DB_REP_HEARTBEAT_MONITOR); 9806 ADD_INT(d, DB_REP_HEARTBEAT_SEND); 9807 #endif 9808 9809 #if (DBVER >= 45) 9810 ADD_INT(d, DB_REPMGR_PEER); 9811 ADD_INT(d, DB_REPMGR_ACKS_ALL); 9812 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS); 9813 ADD_INT(d, DB_REPMGR_ACKS_NONE); 9814 ADD_INT(d, DB_REPMGR_ACKS_ONE); 9815 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER); 9816 ADD_INT(d, DB_REPMGR_ACKS_QUORUM); 9817 ADD_INT(d, DB_REPMGR_CONNECTED); 9818 ADD_INT(d, DB_REPMGR_DISCONNECTED); 9819 ADD_INT(d, DB_STAT_ALL); 9820 #endif 9821 9822 #if (DBVER >= 43) 9823 ADD_INT(d, DB_BUFFER_SMALL); 9824 ADD_INT(d, DB_SEQ_DEC); 9825 ADD_INT(d, DB_SEQ_INC); 9826 ADD_INT(d, DB_SEQ_WRAP); 9827 #endif 9828 9829 #if (DBVER >= 43) && (DBVER < 47) 9830 ADD_INT(d, DB_LOG_INMEMORY); 9831 ADD_INT(d, DB_DSYNC_LOG); 9832 #endif 9833 9834 ADD_INT(d, DB_ENCRYPT_AES); 9835 ADD_INT(d, DB_AUTO_COMMIT); 9836 ADD_INT(d, DB_PRIORITY_VERY_LOW); 9837 ADD_INT(d, DB_PRIORITY_LOW); 9838 ADD_INT(d, DB_PRIORITY_DEFAULT); 9839 ADD_INT(d, DB_PRIORITY_HIGH); 9840 ADD_INT(d, DB_PRIORITY_VERY_HIGH); 9841 9842 #if (DBVER >= 46) 9843 ADD_INT(d, DB_PRIORITY_UNCHANGED); 9844 #endif 9845 9846 ADD_INT(d, EINVAL); 9847 ADD_INT(d, EACCES); 9848 ADD_INT(d, ENOSPC); 9849 ADD_INT(d, ENOMEM); 9850 ADD_INT(d, EAGAIN); 9851 ADD_INT(d, EBUSY); 9852 ADD_INT(d, EEXIST); 9853 ADD_INT(d, ENOENT); 9854 ADD_INT(d, EPERM); 9855 9856 ADD_INT(d, DB_SET_LOCK_TIMEOUT); 9857 ADD_INT(d, DB_SET_TXN_TIMEOUT); 9858 9859 /* The exception name must be correct for pickled exception * 9860 * objects to unpickle properly. */ 9861 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */ 9862 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db." 9863 #else 9864 #define PYBSDDB_EXCEPTION_BASE "bsddb.db." 9865 #endif 9866 9867 /* All the rest of the exceptions derive only from DBError */ 9868 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \ 9869 PyDict_SetItemString(d, #name, name) 9870 9871 /* The base exception class is DBError */ 9872 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */ 9873 MAKE_EX(DBError); 9874 9875 #if (PY_VERSION_HEX < 0x03000000) 9876 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive 9877 * from both DBError and KeyError, since the API only supports 9878 * using one base class. */ 9879 PyDict_SetItemString(d, "KeyError", PyExc_KeyError); 9880 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n" 9881 "class DBKeyEmptyError(DBError, KeyError): pass", 9882 Py_file_input, d, d); 9883 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError"); 9884 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError"); 9885 PyDict_DelItemString(d, "KeyError"); 9886 #else 9887 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to 9888 ** derive from several classes. We use this new API only for Python 3.0, 9889 ** though. 9890 */ 9891 { 9892 PyObject* bases; 9893 9894 bases = PyTuple_Pack(2, DBError, PyExc_KeyError); 9895 9896 #define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \ 9897 PyDict_SetItemString(d, #name, name) 9898 MAKE_EX2(DBNotFoundError); 9899 MAKE_EX2(DBKeyEmptyError); 9900 9901 #undef MAKE_EX2 9902 9903 Py_XDECREF(bases); 9904 } 9905 #endif 9906 9907 MAKE_EX(DBCursorClosedError); 9908 MAKE_EX(DBKeyExistError); 9909 MAKE_EX(DBLockDeadlockError); 9910 MAKE_EX(DBLockNotGrantedError); 9911 MAKE_EX(DBOldVersionError); 9912 MAKE_EX(DBRunRecoveryError); 9913 MAKE_EX(DBVerifyBadError); 9914 MAKE_EX(DBNoServerError); 9915 MAKE_EX(DBNoServerHomeError); 9916 MAKE_EX(DBNoServerIDError); 9917 MAKE_EX(DBPageNotFoundError); 9918 MAKE_EX(DBSecondaryBadError); 9919 9920 MAKE_EX(DBInvalidArgError); 9921 MAKE_EX(DBAccessError); 9922 MAKE_EX(DBNoSpaceError); 9923 MAKE_EX(DBNoMemoryError); 9924 MAKE_EX(DBAgainError); 9925 MAKE_EX(DBBusyError); 9926 MAKE_EX(DBFileExistsError); 9927 MAKE_EX(DBNoSuchFileError); 9928 MAKE_EX(DBPermissionsError); 9929 9930 #if (DBVER >= 42) 9931 MAKE_EX(DBRepHandleDeadError); 9932 #endif 9933 #if (DBVER >= 44) 9934 MAKE_EX(DBRepLockoutError); 9935 #endif 9936 9937 MAKE_EX(DBRepUnavailError); 9938 9939 #if (DBVER >= 46) 9940 MAKE_EX(DBRepLeaseExpiredError); 9941 #endif 9942 9943 #if (DBVER >= 47) 9944 MAKE_EX(DBForeignConflictError); 9945 #endif 9946 9947 #undef MAKE_EX 9948 9949 /* Initialise the C API structure and add it to the module */ 9950 bsddb_api.db_type = &DB_Type; 9951 bsddb_api.dbcursor_type = &DBCursor_Type; 9952 bsddb_api.dblogcursor_type = &DBLogCursor_Type; 9953 bsddb_api.dbenv_type = &DBEnv_Type; 9954 bsddb_api.dbtxn_type = &DBTxn_Type; 9955 bsddb_api.dblock_type = &DBLock_Type; 9956 #if (DBVER >= 43) 9957 bsddb_api.dbsequence_type = &DBSequence_Type; 9958 #endif 9959 bsddb_api.makeDBError = makeDBError; 9960 9961 /* 9962 ** Capsules exist from Python 3.1, but I 9963 ** don't want to break the API compatibility 9964 ** for already published Python versions. 9965 */ 9966 #if (PY_VERSION_HEX < 0x03020000) 9967 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL); 9968 #else 9969 { 9970 char py_api_name[250]; 9971 9972 strcpy(py_api_name, _bsddbModuleName); 9973 strcat(py_api_name, ".api"); 9974 9975 py_api = PyCapsule_New((void*)&bsddb_api, py_api_name, NULL); 9976 } 9977 #endif 9978 9979 /* Check error control */ 9980 /* 9981 ** PyErr_NoMemory(); 9982 ** py_api = NULL; 9983 */ 9984 9985 if (py_api) { 9986 PyDict_SetItemString(d, "api", py_api); 9987 Py_DECREF(py_api); 9988 } else { /* Something bad happened */ 9989 PyErr_WriteUnraisable(m); 9990 if(PyErr_Warn(PyExc_RuntimeWarning, 9991 "_bsddb/_pybsddb C API will be not available")) { 9992 PyErr_WriteUnraisable(m); 9993 } 9994 PyErr_Clear(); 9995 } 9996 9997 /* Check for errors */ 9998 if (PyErr_Occurred()) { 9999 PyErr_Print(); 10000 Py_FatalError("can't initialize module _bsddb/_pybsddb"); 10001 Py_DECREF(m); 10002 m = NULL; 10003 } 10004 #if (PY_VERSION_HEX < 0x03000000) 10005 return; 10006 #else 10007 return m; 10008 #endif 10009 } 10010 10011 /* allow this module to be named _pybsddb so that it can be installed 10012 * and imported on top of python >= 2.3 that includes its own older 10013 * copy of the library named _bsddb without importing the old version. */ 10014 #if (PY_VERSION_HEX < 0x03000000) 10015 DL_EXPORT(void) init_pybsddb(void) 10016 #else 10017 PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */ 10018 #endif 10019 { 10020 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN); 10021 #if (PY_VERSION_HEX < 0x03000000) 10022 init_bsddb(); 10023 #else 10024 return PyInit__bsddb(); /* Note the two underscores */ 10025 #endif 10026 }