diff options
author | jbj <devnull@localhost> | 2005-02-16 19:23:53 +0000 |
---|---|---|
committer | jbj <devnull@localhost> | 2005-02-16 19:23:53 +0000 |
commit | d27e3e835d6f202c3e564603302d2881eb0c525b (patch) | |
tree | ddd45255fcc5ab9a3bdae1f3c75ffd9c8f06e418 /python | |
parent | 055323fb1baf979295cb2b4c9687b85409466333 (diff) | |
download | rpm-d27e3e835d6f202c3e564603302d2881eb0c525b.tar.gz rpm-d27e3e835d6f202c3e564603302d2881eb0c525b.tar.bz2 rpm-d27e3e835d6f202c3e564603302d2881eb0c525b.zip |
Bye-bye!
CVS patchset: 7772
CVS date: 2005/02/16 19:23:53
Diffstat (limited to 'python')
-rw-r--r-- | python/_rpmdb.c | 4955 |
1 files changed, 0 insertions, 4955 deletions
diff --git a/python/_rpmdb.c b/python/_rpmdb.c deleted file mode 100644 index 8292625e6..000000000 --- a/python/_rpmdb.c +++ /dev/null @@ -1,4955 +0,0 @@ -/** \ingroup py_c - * \file python/_rpmdb.c - */ - -/*---------------------------------------------------------------------- - Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA - and Andrew Kuchling. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - o Redistributions of source code must retain the above copyright - notice, this list of conditions, and the disclaimer that follows. - - o Redistributions in binary form must reproduce the above copyright - notice, this list of conditions, and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - o Neither the name of Digital Creations nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS - IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL - CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH - DAMAGE. -------------------------------------------------------------------------*/ - - -/* - * Handwritten code to wrap version 3.x of the Berkeley DB library, - * written to replace a SWIG-generated file. It has since been updated - * to compile with BerkeleyDB versions 3.2 through 4.2. - * - * This module was started by Andrew Kuchling to remove the dependency - * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who - * based his work on a similar package by Robin Dunn <robin@alldunn.com> - * which wrapped Berkeley DB 2.7.x. - * - * Development of this module then returned full circle back to Robin Dunn - * who worked on behalf of Digital Creations to complete the wrapping of - * the DB 3.x API and to build a solid unit test suite. Robin has - * since gone onto other projects (wxPython). - * - * Gregory P. Smith <greg@electricrain.com> is once again the maintainer. - * - * Use the pybsddb-users@lists.sf.net mailing list for all questions. - * Things can change faster than the header of this file is updated. This - * file is shared with the PyBSDDB project at SourceForge: - * - * http://pybsddb.sf.net - * - * This file should remain backward compatible with Python 2.1, but see PEP - * 291 for the most current backward compatibility requirements: - * - * http://www.python.org/peps/pep-0291.html - * - * This module contains 5 types: - * - * DB (Database) - * DBCursor (Database Cursor) - * DBEnv (database environment) - * DBTxn (An explicit database transaction) - * DBLock (A lock handle) - * - */ - -/* --------------------------------------------------------------------- */ - -/* - * Portions of this module, associated unit tests and build scripts are the - * result of a contract with The Written Word (http://thewrittenword.com/) - * Many thanks go out to them for causing me to raise the bar on quality and - * functionality, resulting in a better bsddb3 package for all of us to use. - * - * --Robin - */ - -/* --------------------------------------------------------------------- */ - -#if defined(__APPLE__) -#include <sys/types.h> -#endif - -#include <Python.h> -#include <stddef.h> /* for offsetof() */ -#include <db.h> - -/* --------------------------------------------------------------------- */ -/* Various macro definitions */ - -/* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */ -#define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR) -#if DB_VERSION_MINOR > 9 -#error "eek! DBVER can't handle minor versions > 9" -#endif - -#define PY_BSDDB_VERSION "4.2.4" -static char *rcs_id = "$Id: _rpmdb.c,v 1.14.2.1 2005/02/12 19:03:32 jbj Exp $"; - - -#ifdef WITH_THREAD - -/* These are for when calling Python --> C */ -#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS; -#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS; - -/* For 2.3, use the PyGILState_ calls */ -#if (PY_VERSION_HEX >= 0x02030000) -#define MYDB_USE_GILSTATE -#endif - -/* and these are for calling C --> Python */ -#if defined(MYDB_USE_GILSTATE) -#define MYDB_BEGIN_BLOCK_THREADS \ - PyGILState_STATE __savestate = PyGILState_Ensure(); -#define MYDB_END_BLOCK_THREADS \ - PyGILState_Release(__savestate); -#else /* MYDB_USE_GILSTATE */ -/* Pre GILState API - do it the long old way */ -static PyInterpreterState* _db_interpreterState = NULL; -#define MYDB_BEGIN_BLOCK_THREADS { \ - PyThreadState* prevState; \ - PyThreadState* newState; \ - PyEval_AcquireLock(); \ - newState = PyThreadState_New(_db_interpreterState); \ - prevState = PyThreadState_Swap(newState); - -#define MYDB_END_BLOCK_THREADS \ - newState = PyThreadState_Swap(prevState); \ - PyThreadState_Clear(newState); \ - PyEval_ReleaseLock(); \ - PyThreadState_Delete(newState); \ - } -#endif /* MYDB_USE_GILSTATE */ - -#else -/* Compiled without threads - avoid all this cruft */ -#define MYDB_BEGIN_ALLOW_THREADS -#define MYDB_END_ALLOW_THREADS -#define MYDB_BEGIN_BLOCK_THREADS -#define MYDB_END_BLOCK_THREADS - -#endif - -/* Should DB_INCOMPLETE be turned into a warning or an exception? */ -#define INCOMPLETE_IS_WARNING 1 - -/* --------------------------------------------------------------------- */ -/* Exceptions */ - -static PyObject* DBError; /* Base class, all others derive from this */ -static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */ -static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */ -static PyObject* DBKeyExistError; /* DB_KEYEXIST */ -static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */ -static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */ -static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */ -static PyObject* DBOldVersionError; /* DB_OLD_VERSION */ -static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */ -static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */ -static PyObject* DBNoServerError; /* DB_NOSERVER */ -static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */ -static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */ -#if (DBVER >= 33) -static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */ -static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */ -#endif - -#if !INCOMPLETE_IS_WARNING -static PyObject* DBIncompleteError; /* DB_INCOMPLETE */ -#endif - -static PyObject* DBInvalidArgError; /* EINVAL */ -static PyObject* DBAccessError; /* EACCES */ -static PyObject* DBNoSpaceError; /* ENOSPC */ -static PyObject* DBNoMemoryError; /* ENOMEM */ -static PyObject* DBAgainError; /* EAGAIN */ -static PyObject* DBBusyError; /* EBUSY */ -static PyObject* DBFileExistsError; /* EEXIST */ -static PyObject* DBNoSuchFileError; /* ENOENT */ -static PyObject* DBPermissionsError; /* EPERM */ - - - -/* --------------------------------------------------------------------- */ -/* Structure definitions */ - -#if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */ -#define HAVE_WEAKREF -#else -#undef HAVE_WEAKREF -#endif - -struct behaviourFlags { - /* What is the default behaviour when DB->get or DBCursor->get returns a - DB_NOTFOUND error? Return None or raise an exception? */ - unsigned int getReturnsNone : 1; - /* What is the default behaviour for DBCursor.set* methods when DBCursor->get - * returns a DB_NOTFOUND error? Return None or raise an exception? */ - unsigned int cursorSetReturnsNone : 1; -}; - -#define DEFAULT_GET_RETURNS_NONE 1 -#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */ - -typedef struct { - PyObject_HEAD - DB_ENV* db_env; - u_int32_t flags; /* saved flags from open() */ - int closed; - struct behaviourFlags moduleFlags; -} DBEnvObject; - - -typedef struct { - PyObject_HEAD - DB* db; - DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */ - u_int32_t flags; /* saved flags from open() */ - u_int32_t setflags; /* saved flags from set_flags() */ - int haveStat; - struct behaviourFlags moduleFlags; -#if (DBVER >= 33) - PyObject* associateCallback; - int primaryDBType; -#endif -} DBObject; - - -typedef struct { - PyObject_HEAD - DBC* dbc; - DBObject* mydb; -#ifdef HAVE_WEAKREF - PyObject *in_weakreflist; /* List of weak references */ -#endif -} DBCursorObject; - - -typedef struct { - PyObject_HEAD - DB_TXN* txn; -} DBTxnObject; - - -typedef struct { - PyObject_HEAD - DB_LOCK lock; -} DBLockObject; - - - -staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type; - -#define DBObject_Check(v) ((v)->ob_type == &DB_Type) -#define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type) -#define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type) -#define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type) -#define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type) - - -/* --------------------------------------------------------------------- */ -/* Utility macros and functions */ - -#define RETURN_IF_ERR() \ - if (makeDBError(err)) { \ - return NULL; \ - } - -#define RETURN_NONE() Py_INCREF(Py_None); return Py_None; - -#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \ - if ((nonNull) == NULL) { \ - PyObject *errTuple = NULL; \ - errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \ - PyErr_SetObject((pyErrObj), errTuple); \ - Py_DECREF(errTuple); \ - return NULL; \ - } - -#define CHECK_DB_NOT_CLOSED(dbobj) \ - _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB) - -#define CHECK_ENV_NOT_CLOSED(env) \ - _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv) - -#define CHECK_CURSOR_NOT_CLOSED(curs) \ - _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor) - - -#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \ - (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag)))) - -#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt))) - -#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \ - dbt.data != NULL) { free(dbt.data); } - - -static int makeDBError(int err); - - -/* Return the access method type of the DBObject */ -static int _DB_get_type(DBObject* self) -{ -#if (DBVER >= 33) - DBTYPE type; - int err; - err = self->db->get_type(self->db, &type); - if (makeDBError(err)) { - return -1; - } - return type; -#else - return self->db->get_type(self->db); -#endif -} - - -/* Create a DBT structure (containing key and data values) from Python - strings. Returns 1 on success, 0 on an error. */ -static int make_dbt(PyObject* obj, DBT* dbt) -{ - CLEAR_DBT(*dbt); - if (obj == Py_None) { - /* no need to do anything, the structure has already been zeroed */ - } - else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) { - PyErr_SetString(PyExc_TypeError, - "Key and Data values must be of type string or None."); - return 0; - } - return 1; -} - - -/* Recno and Queue DBs can have integer keys. This function figures out - what's been given, verifies that it's allowed, and then makes the DBT. - - Caller should call FREE_DBT(key) when done. */ -static int -make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags) -{ - db_recno_t recno; - int type; - - CLEAR_DBT(*key); - if (keyobj == Py_None) { /* TODO: is None really okay for keys? */ - /* no need to do anything, the structure has already been zeroed */ - } - - else if (PyString_Check(keyobj)) { - /* verify access method type */ - type = _DB_get_type(self); - if (type == -1) - return 0; - if (type == DB_RECNO || type == DB_QUEUE) { - PyErr_SetString( - PyExc_TypeError, - "String keys not allowed for Recno and Queue DB's"); - return 0; - } - - key->data = PyString_AS_STRING(keyobj); - key->size = PyString_GET_SIZE(keyobj); - } - - else if (PyInt_Check(keyobj)) { - /* verify access method type */ - type = _DB_get_type(self); - if (type == -1) - return 0; - if (type == DB_BTREE && pflags != NULL) { - /* if BTREE then an Integer key is allowed with the - * DB_SET_RECNO flag */ - *pflags |= DB_SET_RECNO; - } - else if (type != DB_RECNO && type != DB_QUEUE) { - PyErr_SetString( - PyExc_TypeError, - "Integer keys only allowed for Recno and Queue DB's"); - return 0; - } - - /* Make a key out of the requested recno, use allocated space so DB - * will be able to realloc room for the real key if needed. */ - recno = PyInt_AS_LONG(keyobj); - key->data = malloc(sizeof(db_recno_t)); - if (key->data == NULL) { - PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); - return 0; - } - key->ulen = key->size = sizeof(db_recno_t); - memcpy(key->data, &recno, sizeof(db_recno_t)); - key->flags = DB_DBT_REALLOC; - } - else { - PyErr_Format(PyExc_TypeError, - "String or Integer object expected for key, %s found", - keyobj->ob_type->tp_name); - return 0; - } - - return 1; -} - - -/* Add partial record access to an existing DBT data struct. - If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set - and the data storage/retrieval will be done using dlen and doff. */ -static int add_partial_dbt(DBT* d, int dlen, int doff) { - /* if neither were set we do nothing (-1 is the default value) */ - if ((dlen == -1) && (doff == -1)) { - return 1; - } - - if ((dlen < 0) || (doff < 0)) { - PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0"); - return 0; - } - - d->flags = d->flags | DB_DBT_PARTIAL; - d->dlen = (unsigned int) dlen; - d->doff = (unsigned int) doff; - return 1; -} - - -/* Callback used to save away more information about errors from the DB - * library. */ -static char _db_errmsg[1024]; -#if (DBVER >= 43) -static void _db_errorCallback(const DB_ENV *db_env, const char* prefix, char* msg) -{ - strcpy(_db_errmsg, msg); -} -#else -static void _db_errorCallback(const char* prefix, char* msg) -{ - strcpy(_db_errmsg, msg); -} -#endif - - -/* make a nice exception object to raise for errors. */ -static int makeDBError(int err) -{ - char errTxt[2048]; /* really big, just in case... */ - PyObject *errObj = NULL; - PyObject *errTuple = NULL; - int exceptionRaised = 0; - - switch (err) { - case 0: /* successful, no error */ break; - -#if (DBVER < 41) - case DB_INCOMPLETE: -#if INCOMPLETE_IS_WARNING - strcpy(errTxt, db_strerror(err)); - if (_db_errmsg[0]) { - strcat(errTxt, " -- "); - strcat(errTxt, _db_errmsg); - _db_errmsg[0] = 0; - } -/* if Python 2.1 or better use warning framework */ -#if PYTHON_API_VERSION >= 1010 - exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt); -#else - fprintf(stderr, errTxt); - fprintf(stderr, "\n"); -#endif - -#else /* do an exception instead */ - errObj = DBIncompleteError; -#endif - break; -#endif /* DBVER < 41 */ - - case DB_KEYEMPTY: errObj = DBKeyEmptyError; break; - case DB_KEYEXIST: errObj = DBKeyExistError; break; - case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break; - case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break; - case DB_NOTFOUND: errObj = DBNotFoundError; break; - case DB_OLD_VERSION: errObj = DBOldVersionError; break; - case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break; - case DB_VERIFY_BAD: errObj = DBVerifyBadError; break; - case DB_NOSERVER: errObj = DBNoServerError; break; - case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break; - case DB_NOSERVER_ID: errObj = DBNoServerIDError; break; -#if (DBVER >= 33) - case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break; - case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break; -#endif - - case EINVAL: errObj = DBInvalidArgError; break; - case EACCES: errObj = DBAccessError; break; - case ENOSPC: errObj = DBNoSpaceError; break; - case ENOMEM: errObj = DBNoMemoryError; break; - case EAGAIN: errObj = DBAgainError; break; - case EBUSY : errObj = DBBusyError; break; - case EEXIST: errObj = DBFileExistsError; break; - case ENOENT: errObj = DBNoSuchFileError; break; - case EPERM : errObj = DBPermissionsError; break; - - default: errObj = DBError; break; - } - - if (errObj != NULL) { - /* FIXME this needs proper bounds checking on errTxt */ - strcpy(errTxt, db_strerror(err)); - if (_db_errmsg[0]) { - strcat(errTxt, " -- "); - strcat(errTxt, _db_errmsg); - _db_errmsg[0] = 0; - } - - errTuple = Py_BuildValue("(is)", err, errTxt); - PyErr_SetObject(errObj, errTuple); - Py_DECREF(errTuple); - } - - return ((errObj != NULL) || exceptionRaised); -} - - - -/* set a type exception */ -static void makeTypeError(char* expected, PyObject* found) -{ - PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.", - expected, found->ob_type->tp_name); -} - - -/* verify that an obj is either None or a DBTxn, and set the txn pointer */ -static int checkTxnObj(PyObject* txnobj, DB_TXN** txn) -{ - if (txnobj == Py_None || txnobj == NULL) { - *txn = NULL; - return 1; - } - if (DBTxnObject_Check(txnobj)) { - *txn = ((DBTxnObject*)txnobj)->txn; - return 1; - } - else - makeTypeError("DBTxn", txnobj); - return 0; -} - - -/* Delete a key from a database - Returns 0 on success, -1 on an error. */ -static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags) -{ - int err; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->del(self->db, txn, key, 0); - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - return -1; - } - self->haveStat = 0; - return 0; -} - - -/* Store a key into a database - Returns 0 on success, -1 on an error. */ -static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags) -{ - int err; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->put(self->db, txn, key, data, flags); - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - return -1; - } - self->haveStat = 0; - return 0; -} - -/* Get a key/data pair from a cursor */ -static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags, - PyObject *args, PyObject *kwargs, char *format) -{ - int err; - PyObject* retval = NULL; - DBT key, data; - int dlen = -1; - int doff = -1; - int flags = 0; - char* kwnames[] = { "flags", "dlen", "doff", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames, - &flags, &dlen, &doff)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - flags |= extra_flags; - CLEAR_DBT(key); - CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } - if (!add_partial_dbt(&data, dlen, doff)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - - if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { /* otherwise, success! */ - - /* if Recno or Queue, return the key as an Int */ - switch (_DB_get_type(self->mydb)) { - case -1: - retval = NULL; - break; - - case DB_RECNO: - case DB_QUEUE: - retval = Py_BuildValue("is#", *((db_recno_t*)key.data), - data.data, data.size); - break; - case DB_HASH: - case DB_BTREE: - default: - retval = Py_BuildValue("s#s#", key.data, key.size, - data.data, data.size); - break; - } - } - if (!err) { - FREE_DBT(key); - FREE_DBT(data); - } - return retval; -} - - -/* add an integer to a dictionary using the given name as a key */ -static void _addIntToDict(PyObject* dict, char *name, int value) -{ - PyObject* v = PyInt_FromLong((long) value); - if (!v || PyDict_SetItemString(dict, name, v)) - PyErr_Clear(); - - Py_XDECREF(v); -} - - - - -/* --------------------------------------------------------------------- */ -/* Allocators and deallocators */ - -static DBObject* -newDBObject(DBEnvObject* arg, int flags) -{ - DBObject* self; - DB_ENV* db_env = NULL; - int err; - -#if PYTHON_API_VERSION <= 1007 - /* 1.5 compatibility */ - self = PyObject_NEW(DBObject, &DB_Type); -#else - self = PyObject_New(DBObject, &DB_Type); -#endif - - if (self == NULL) - return NULL; - - self->haveStat = 0; - self->flags = 0; - self->setflags = 0; - self->myenvobj = NULL; -#if (DBVER >= 33) - self->associateCallback = NULL; - self->primaryDBType = 0; -#endif - - /* keep a reference to our python DBEnv object */ - if (arg) { - Py_INCREF(arg); - self->myenvobj = arg; - db_env = arg->db_env; - } - - if (self->myenvobj) - self->moduleFlags = self->myenvobj->moduleFlags; - else - self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; - self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; - - MYDB_BEGIN_ALLOW_THREADS; - err = db_create(&self->db, db_env, flags); - self->db->set_errcall(self->db, _db_errorCallback); -#if (DBVER >= 33) - self->db->app_private = (void*)self; -#endif - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - if (self->myenvobj) { - Py_DECREF(self->myenvobj); - self->myenvobj = NULL; - } - self = NULL; - } - return self; -} - - -static void -DB_dealloc(DBObject* self) -{ - if (self->db != NULL) { - /* avoid closing a DB when its DBEnv has been closed out from under - * it */ - if (!self->myenvobj || - (self->myenvobj && self->myenvobj->db_env)) - { - MYDB_BEGIN_ALLOW_THREADS; - self->db->close(self->db, 0); - MYDB_END_ALLOW_THREADS; - /* if Python 2.1 or better use warning framework */ -#if PYTHON_API_VERSION >= 1010 - } else { - PyErr_Warn(PyExc_RuntimeWarning, - "DB could not be closed in destructor: DBEnv already closed"); -#endif - } - self->db = NULL; - } - if (self->myenvobj) { - Py_DECREF(self->myenvobj); - self->myenvobj = NULL; - } -#if (DBVER >= 33) - if (self->associateCallback != NULL) { - Py_DECREF(self->associateCallback); - self->associateCallback = NULL; - } -#endif -#if PYTHON_API_VERSION <= 1007 - PyMem_DEL(self); -#else - PyObject_Del(self); -#endif -} - - -static DBCursorObject* -newDBCursorObject(DBC* dbc, DBObject* db) -{ - DBCursorObject* self; -#if PYTHON_API_VERSION <= 1007 - self = PyObject_NEW(DBCursorObject, &DBCursor_Type); -#else - self = PyObject_New(DBCursorObject, &DBCursor_Type); -#endif - if (self == NULL) - return NULL; - - self->dbc = dbc; - self->mydb = db; -#ifdef HAVE_WEAKREF - self->in_weakreflist = NULL; -#endif - Py_INCREF(self->mydb); - return self; -} - - -static void -DBCursor_dealloc(DBCursorObject* self) -{ - int err; - -#ifdef HAVE_WEAKREF - if (self->in_weakreflist != NULL) { - PyObject_ClearWeakRefs((PyObject *) self); - } -#endif - - if (self->dbc != NULL) { - MYDB_BEGIN_ALLOW_THREADS; - /* If the underlying database has been closed, we don't - need to do anything. If the environment has been closed - we need to leak, as BerkeleyDB will crash trying to access - the environment. There was an exception when the - user closed the environment even though there still was - a database open. */ - if (self->mydb->db && self->mydb->myenvobj && - !self->mydb->myenvobj->closed) - err = self->dbc->c_close(self->dbc); - self->dbc = NULL; - MYDB_END_ALLOW_THREADS; - } - Py_XDECREF( self->mydb ); -#if PYTHON_API_VERSION <= 1007 - PyMem_DEL(self); -#else - PyObject_Del(self); -#endif -} - - -static DBEnvObject* -newDBEnvObject(int flags) -{ - int err; - DBEnvObject* self; -#if PYTHON_API_VERSION <= 1007 - self = PyObject_NEW(DBEnvObject, &DBEnv_Type); -#else - self = PyObject_New(DBEnvObject, &DBEnv_Type); -#endif - - if (self == NULL) - return NULL; - - self->closed = 1; - self->flags = flags; - self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE; - self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE; - - MYDB_BEGIN_ALLOW_THREADS; - err = db_env_create(&self->db_env, flags); - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - self = NULL; - } - else { - self->db_env->set_errcall(self->db_env, _db_errorCallback); - } - return self; -} - - -static void -DBEnv_dealloc(DBEnvObject* self) -{ - if (!self->closed) { - MYDB_BEGIN_ALLOW_THREADS; - self->db_env->close(self->db_env, 0); - MYDB_END_ALLOW_THREADS; - } -#if PYTHON_API_VERSION <= 1007 - PyMem_DEL(self); -#else - PyObject_Del(self); -#endif -} - - -static DBTxnObject* -newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags) -{ - int err; - DBTxnObject* self; - -#if PYTHON_API_VERSION <= 1007 - self = PyObject_NEW(DBTxnObject, &DBTxn_Type); -#else - self = PyObject_New(DBTxnObject, &DBTxn_Type); -#endif - if (self == NULL) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags); -#else - err = txn_begin(myenv->db_env, parent, &(self->txn), flags); -#endif - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - self = NULL; - } - return self; -} - - -static void -DBTxn_dealloc(DBTxnObject* self) -{ - /* XXX nothing to do for transaction objects?!? */ - - /* TODO: if it hasn't been commited, should we abort it? */ - -#if PYTHON_API_VERSION <= 1007 - PyMem_DEL(self); -#else - PyObject_Del(self); -#endif -} - - -static DBLockObject* -newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj, - db_lockmode_t lock_mode, int flags) -{ - int err; - DBLockObject* self; - -#if PYTHON_API_VERSION <= 1007 - self = PyObject_NEW(DBLockObject, &DBLock_Type); -#else - self = PyObject_New(DBLockObject, &DBLock_Type); -#endif - if (self == NULL) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode, - &self->lock); -#else - err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock); -#endif - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - self = NULL; - } - - return self; -} - - -static void -DBLock_dealloc(DBLockObject* self) -{ - /* TODO: if it hasn't been released, should we do it? */ - -#if PYTHON_API_VERSION <= 1007 - PyMem_DEL(self); -#else - PyObject_Del(self); -#endif -} - - -/* --------------------------------------------------------------------- */ -/* DB methods */ - -static PyObject* -DB_append(DBObject* self, PyObject* args, PyObject * kwargs) -{ - PyObject* txnobj = NULL; - PyObject* dataobj; - db_recno_t recno; - DBT key, data; - DB_TXN *txn = NULL; - char* kwnames[] = {"data", "transaction", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames, - &dataobj, &txnobj)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - /* make a dummy key out of a recno */ - recno = 0; - CLEAR_DBT(key); - key.data = &recno; - key.size = sizeof(recno); - key.ulen = key.size; - key.flags = DB_DBT_USERMEM; - - if (!make_dbt(dataobj, &data)) return NULL; - if (!checkTxnObj(txnobj, &txn)) return NULL; - - if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) - return NULL; - - return PyInt_FromLong(recno); -} - - -#if (DBVER >= 33) - -static int -_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData, - DBT* secKey) -{ - int retval = DB_DONOTINDEX; - DBObject* secondaryDB = (DBObject*)db->app_private; - PyObject* callback = secondaryDB->associateCallback; - int type = secondaryDB->primaryDBType; - PyObject* key; - PyObject* data; - PyObject* args; - PyObject* result; - - - if (callback != NULL) { - MYDB_BEGIN_BLOCK_THREADS; - - if (type == DB_RECNO || type == DB_QUEUE) { - key = PyInt_FromLong( *((db_recno_t*)priKey->data)); - } - else { - key = PyString_FromStringAndSize(priKey->data, priKey->size); - } - data = PyString_FromStringAndSize(priData->data, priData->size); - args = PyTuple_New(2); - PyTuple_SET_ITEM(args, 0, key); /* steals reference */ - PyTuple_SET_ITEM(args, 1, data); /* steals reference */ - - result = PyEval_CallObject(callback, args); - - if (result == NULL) { - PyErr_Print(); - } - else if (result == Py_None) { - retval = DB_DONOTINDEX; - } - else if (PyInt_Check(result)) { - retval = PyInt_AsLong(result); - } - else if (PyString_Check(result)) { - char* data; - int size; - - CLEAR_DBT(*secKey); -#if PYTHON_API_VERSION <= 1007 - /* 1.5 compatibility */ - size = PyString_Size(result); - data = PyString_AsString(result); -#else - PyString_AsStringAndSize(result, &data, &size); -#endif - secKey->flags = DB_DBT_APPMALLOC; /* DB will free */ - secKey->data = malloc(size); /* TODO, check this */ - if (secKey->data) { - memcpy(secKey->data, data, size); - secKey->size = size; - retval = 0; - } - else { - PyErr_SetString(PyExc_MemoryError, - "malloc failed in _db_associateCallback"); - PyErr_Print(); - } - } - else { - PyErr_SetString( - PyExc_TypeError, - "DB associate callback should return DB_DONOTINDEX or string."); - PyErr_Print(); - } - - Py_DECREF(args); - if (result) { - Py_DECREF(result); - } - - MYDB_END_BLOCK_THREADS; - } - return retval; -} - - -static PyObject* -DB_associate(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - DBObject* secondaryDB; - PyObject* callback; -#if (DBVER >= 41) - PyObject *txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL}; -#else - char* kwnames[] = {"secondaryDB", "callback", "flags", NULL}; -#endif - -#if (DBVER >= 41) - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames, - &secondaryDB, &callback, &flags, - &txnobj)) { -#else - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames, - &secondaryDB, &callback, &flags)) { -#endif - return NULL; - } - -#if (DBVER >= 41) - if (!checkTxnObj(txnobj, &txn)) return NULL; -#endif - - CHECK_DB_NOT_CLOSED(self); - if (!DBObject_Check(secondaryDB)) { - makeTypeError("DB", (PyObject*)secondaryDB); - return NULL; - } - if (callback == Py_None) { - callback = NULL; - } - else if (!PyCallable_Check(callback)) { - makeTypeError("Callable", callback); - return NULL; - } - - /* Save a reference to the callback in the secondary DB. */ - if (self->associateCallback != NULL) { - Py_DECREF(self->associateCallback); - } - Py_INCREF(callback); - secondaryDB->associateCallback = callback; - secondaryDB->primaryDBType = _DB_get_type(self); - - /* PyEval_InitThreads is called here due to a quirk in python 1.5 - * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>: - * The global interepreter lock is not initialized until the first - * thread is created using thread.start_new_thread() or fork() is - * called. that would cause the ALLOW_THREADS here to segfault due - * to a null pointer reference if no threads or child processes - * have been created. This works around that and is a no-op if - * threads have already been initialized. - * (see pybsddb-users mailing list post on 2002-08-07) - */ -#ifdef WITH_THREAD - PyEval_InitThreads(); -#endif - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 41) - err = self->db->associate(self->db, - txn, - secondaryDB->db, - _db_associateCallback, - flags); -#else - err = self->db->associate(self->db, - secondaryDB->db, - _db_associateCallback, - flags); -#endif - MYDB_END_ALLOW_THREADS; - - if (err) { - Py_DECREF(self->associateCallback); - self->associateCallback = NULL; - secondaryDB->primaryDBType = 0; - } - - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -#endif - - -static PyObject* -DB_close(DBObject* self, PyObject* args, PyObject * kwargs) -{ - int err, flags=0; - char *kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:close", kwnames, &flags)) - return NULL; - - if (self->db != NULL) { - if (self->myenvobj) - CHECK_ENV_NOT_CLOSED(self->myenvobj); - err = self->db->close(self->db, flags); - self->db = NULL; - RETURN_IF_ERR(); - } - RETURN_NONE(); -} - - -#if (DBVER >= 32) -static PyObject* -_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) -{ - int err, flags=0, type; - PyObject* txnobj = NULL; - PyObject* retval = NULL; - DBT key, data; - DB_TXN *txn = NULL; - char* kwnames[] = { "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames, - &txnobj, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - type = _DB_get_type(self); - if (type == -1) - return NULL; - if (type != DB_QUEUE) { - PyErr_SetString(PyExc_TypeError, - "Consume methods only allowed for Queue DB's"); - return NULL; - } - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - CLEAR_DBT(key); - CLEAR_DBT(data); - if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get(self->db, txn, &key, &data, flags|consume_flag); - MYDB_END_ALLOW_THREADS; - - if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { - err = 0; - Py_INCREF(Py_None); - retval = Py_None; - } - else if (!err) { - retval = Py_BuildValue("s#s#", key.data, key.size, data.data, - data.size); - FREE_DBT(key); - FREE_DBT(data); - } - - RETURN_IF_ERR(); - return retval; -} - -/* XXX wtf? This cannot possibly be the right prototype. --pj */ -static PyObject* -DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag) -{ - return _DB_consume(self, args, kwargs, DB_CONSUME); -} - -/* XXX wtf? This cannot possibly be the right prototype. --pj */ -static PyObject* -DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs, - int consume_flag) -{ - return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT); -} -#endif - - - -static PyObject* -DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - DBC* dbc; - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = { "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, - &txnobj, &flags)) - return NULL; - CHECK_DB_NOT_CLOSED(self); - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->cursor(self->db, txn, &dbc, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - return (PyObject*) newDBCursorObject(dbc, self); -} - - -static PyObject* -DB_delete(DBObject* self, PyObject* args, PyObject* kwargs) -{ - PyObject* txnobj = NULL; - int flags = 0; - PyObject* keyobj; - DBT key; - DB_TXN *txn = NULL; - char* kwnames[] = { "key", "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames, - &keyobj, &txnobj, &flags)) - return NULL; - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL)) - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - if (-1 == _DB_delete(self, txn, &key, 0)) - return NULL; - - FREE_DBT(key); - RETURN_NONE(); -} - - -static PyObject* -DB_fd(DBObject* self) -{ - int err, the_fd; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->fd(self->db, &the_fd); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - return PyInt_FromLong(the_fd); -} - - -static PyObject* -DB_get(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - PyObject* txnobj = NULL; - PyObject* keyobj; - PyObject* dfltobj = NULL; - PyObject* retval = NULL; - int dlen = -1; - int doff = -1; - DBT key, data; - DB_TXN *txn = NULL; - char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames, - &keyobj, &dfltobj, &txnobj, &flags, &dlen, - &doff)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, &flags)) - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - CLEAR_DBT(data); - if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - } - if (!add_partial_dbt(&data, dlen, doff)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get(self->db, txn, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - - if ((err == DB_NOTFOUND) && (dfltobj != NULL)) { - err = 0; - Py_INCREF(dfltobj); - retval = dfltobj; - } - else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { - err = 0; - Py_INCREF(Py_None); - retval = Py_None; - } - else if (!err) { - if (flags & DB_SET_RECNO) /* return both key and data */ - retval = Py_BuildValue("s#s#", key.data, key.size, data.data, - data.size); - else /* return just the data */ - retval = PyString_FromStringAndSize((char*)data.data, data.size); - FREE_DBT(key); - FREE_DBT(data); - } - - RETURN_IF_ERR(); - return retval; -} - - -/* Return size of entry */ -static PyObject* -DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - PyObject* txnobj = NULL; - PyObject* keyobj; - PyObject* retval = NULL; - DBT key, data; - DB_TXN *txn = NULL; - char* kwnames[] = { "key", "txn", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames, - &keyobj, &txnobj)) - return NULL; - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, &flags)) - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - CLEAR_DBT(data); - - /* We don't allocate any memory, forcing a ENOMEM error and thus - getting the record size. */ - data.flags = DB_DBT_USERMEM; - data.ulen = 0; - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get(self->db, txn, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - if (err == ENOMEM) { - retval = PyInt_FromLong((long)data.size); - err = 0; - } - - FREE_DBT(key); - FREE_DBT(data); - RETURN_IF_ERR(); - return retval; -} - - -static PyObject* -DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - PyObject* txnobj = NULL; - PyObject* keyobj; - PyObject* dataobj; - PyObject* retval = NULL; - DBT key, data; - DB_TXN *txn = NULL; - char* kwnames[] = { "key", "data", "txn", "flags", NULL }; - - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames, - &keyobj, &dataobj, &txnobj, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL)) - return NULL; - if (!make_dbt(dataobj, &data)) - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - flags |= DB_GET_BOTH; - - if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - /* TODO: Is this flag needed? We're passing a data object that should - match what's in the DB, so there should be no need to malloc. - We run the risk of freeing something twice! Check this. */ - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get(self->db, txn, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - - if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) { - err = 0; - Py_INCREF(Py_None); - retval = Py_None; - } - else if (!err) { - retval = PyString_FromStringAndSize((char*)data.data, data.size); - FREE_DBT(data); /* Only if retrieval was successful */ - } - - FREE_DBT(key); - RETURN_IF_ERR(); - return retval; -} - - -static PyObject* -DB_get_byteswapped(DBObject* self) -{ -#if (DBVER >= 33) - int err = 0; -#endif - int retval = -1; - - CHECK_DB_NOT_CLOSED(self); - -#if (DBVER >= 33) - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get_byteswapped(self->db, &retval); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); -#else - MYDB_BEGIN_ALLOW_THREADS; - retval = self->db->get_byteswapped(self->db); - MYDB_END_ALLOW_THREADS; -#endif - return PyInt_FromLong(retval); -} - - -static PyObject* -DB_get_type(DBObject* self) -{ - int type; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - type = _DB_get_type(self); - MYDB_END_ALLOW_THREADS; - if (type == -1) - return NULL; - return PyInt_FromLong(type); -} - - -static PyObject* -DB_join(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - int length, x; - PyObject* cursorsObj; - DBC** cursors; - DBC* dbc; - char* kwnames[] = {"cursors", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:join", kwnames, - &cursorsObj, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - if (!PySequence_Check(cursorsObj)) { - PyErr_SetString(PyExc_TypeError, - "Sequence of DBCursor objects expected"); - return NULL; - } - - length = PyObject_Length(cursorsObj); - cursors = malloc((length+1) * sizeof(DBC*)); - cursors[length] = NULL; - for (x=0; x<length; x++) { - PyObject* item = PySequence_GetItem(cursorsObj, x); - if (!DBCursorObject_Check(item)) { - PyErr_SetString(PyExc_TypeError, - "Sequence of DBCursor objects expected"); - free(cursors); - return NULL; - } - cursors[x] = ((DBCursorObject*)item)->dbc; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->join(self->db, cursors, &dbc, flags); - MYDB_END_ALLOW_THREADS; - free(cursors); - RETURN_IF_ERR(); - - /* FIXME: this is a buggy interface. The returned cursor - contains internal references to the passed in cursors - but does not hold python references to them or prevent - them from being closed prematurely. This can cause - python to crash when things are done in the wrong order. */ - return (PyObject*) newDBCursorObject(dbc, self); -} - - -static PyObject* -DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - PyObject* txnobj = NULL; - PyObject* keyobj; - DBT key; - DB_TXN *txn = NULL; - DB_KEY_RANGE range; - char* kwnames[] = { "key", "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames, - &keyobj, &txnobj, &flags)) - return NULL; - CHECK_DB_NOT_CLOSED(self); - if (!make_dbt(keyobj, &key)) - /* BTree only, don't need to allow for an int key */ - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->key_range(self->db, txn, &key, &range, flags); - MYDB_END_ALLOW_THREADS; - - RETURN_IF_ERR(); - return Py_BuildValue("ddd", range.less, range.equal, range.greater); -} - - -static PyObject* -DB_open(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, type = DB_UNKNOWN, flags=0, mode=0660; - char* filename = NULL; - char* dbname = NULL; -#if (DBVER >= 41) - PyObject *txnobj = NULL; - DB_TXN *txn = NULL; - /* with dbname */ - char* kwnames[] = { - "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL}; - /* without dbname */ - char* kwnames_basic[] = { - "filename", "dbtype", "flags", "mode", "txn", NULL}; -#else - /* with dbname */ - char* kwnames[] = { - "filename", "dbname", "dbtype", "flags", "mode", NULL}; - /* without dbname */ - char* kwnames_basic[] = { - "filename", "dbtype", "flags", "mode", NULL}; -#endif - -#if (DBVER >= 41) - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames, - &filename, &dbname, &type, &flags, &mode, - &txnobj)) -#else - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames, - &filename, &dbname, &type, &flags, - &mode)) -#endif - { - PyErr_Clear(); - type = DB_UNKNOWN; flags = 0; mode = 0660; - filename = NULL; dbname = NULL; -#if (DBVER >= 41) - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open", - kwnames_basic, - &filename, &type, &flags, &mode, - &txnobj)) - return NULL; -#else - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open", - kwnames_basic, - &filename, &type, &flags, &mode)) - return NULL; -#endif - } - -#if (DBVER >= 41) - if (!checkTxnObj(txnobj, &txn)) return NULL; -#endif - - if (NULL == self->db) { - PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, - "Cannot call open() twice for DB object")); - return NULL; - } - -#if 0 && (DBVER >= 41) - if ((!txn) && (txnobj != Py_None) && self->myenvobj - && (self->myenvobj->flags & DB_INIT_TXN)) - { - /* If no 'txn' parameter was supplied (no DbTxn object and None was not - * explicitly passed) but we are in a transaction ready environment: - * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions - * to work on BerkeleyDB 4.1 without needing to modify their - * DBEnv or DB open calls. - * TODO make this behaviour of the library configurable. - */ - flags |= DB_AUTO_COMMIT; - } -#endif - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 41) - err = self->db->open(self->db, txn, filename, dbname, type, flags, mode); -#else - err = self->db->open(self->db, filename, dbname, type, flags, mode); -#endif - MYDB_END_ALLOW_THREADS; - if (makeDBError(err)) { - self->db->close(self->db, 0); - self->db = NULL; - return NULL; - } - - self->flags = flags; - RETURN_NONE(); -} - - -static PyObject* -DB_put(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - PyObject* txnobj = NULL; - int dlen = -1; - int doff = -1; - PyObject* keyobj, *dataobj, *retval; - DBT key, data; - DB_TXN *txn = NULL; - char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames, - &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL; - if (!make_dbt(dataobj, &data)) return NULL; - if (!add_partial_dbt(&data, dlen, doff)) return NULL; - if (!checkTxnObj(txnobj, &txn)) return NULL; - - if (-1 == _DB_put(self, txn, &key, &data, flags)) { - FREE_DBT(key); - return NULL; - } - - if (flags & DB_APPEND) - retval = PyInt_FromLong(*((db_recno_t*)key.data)); - else { - retval = Py_None; - Py_INCREF(retval); - } - FREE_DBT(key); - return retval; -} - - - -static PyObject* -DB_remove(DBObject* self, PyObject* args, PyObject* kwargs) -{ - char* filename; - char* database = NULL; - int err, flags=0; - char* kwnames[] = { "filename", "dbname", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames, - &filename, &database, &flags)) - return NULL; - CHECK_DB_NOT_CLOSED(self); - - err = self->db->remove(self->db, filename, database, flags); - self->db = NULL; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - - -static PyObject* -DB_rename(DBObject* self, PyObject* args, PyObject * kwargs) -{ - char* filename; - char* database; - char* newname; - int err, flags=0; - char* kwnames[] = {"filename", "database", "newname", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|i:rename", kwnames, - &filename, &database, &newname, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->rename(self->db, filename, database, newname, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_bt_minkey(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, minkey; - char* kwnames[] = {"minkey", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_bt_minkey", kwnames, - &minkey)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_bt_minkey(self->db, minkey); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_cachesize(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - int gbytes = 0, bytes = 0, ncache = 0; - char* kwnames[] = {"gbytes", "bytes", "ncache", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:set_cachesize", - kwnames, &gbytes, &bytes, &ncache)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_cachesize(self->db, gbytes, bytes, ncache); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_flags(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_flags", kwnames, - &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_flags(self->db, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - self->setflags |= flags; - RETURN_NONE(); -} - - -static PyObject* -DB_set_h_ffactor(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, ffactor; - char* kwnames[] = {"ffactor", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_h_ffactor", kwnames, - &ffactor)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_h_ffactor(self->db, ffactor); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_h_nelem(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, nelem; - char* kwnames[] = {"nelem", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_h_nelem", kwnames, - &nelem)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_h_nelem(self->db, nelem); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_lorder(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, lorder; - char* kwnames[] = {"lorder", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lorder", kwnames, - &lorder)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_lorder(self->db, lorder); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_pagesize(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, pagesize; - char* kwnames[] = {"pagesize", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_pagesize", kwnames, - &pagesize)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_pagesize(self->db, pagesize); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_re_delim(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - char delim; - char* kwnames[] = {"delim", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "b:set_re_delim", kwnames, - &delim)) { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "c:set_re_delim", - kwnames, &delim)) - return NULL; - } - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_re_delim(self->db, delim); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -static PyObject* -DB_set_re_len(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, len; - char* kwnames[] = {"len", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_re_len", kwnames, - &len)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_re_len(self->db, len); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_re_pad(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - char pad; - char* kwnames[] = {"pad", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "b:set_re_pad", kwnames, - &pad)) { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "c:set_re_pad", kwnames, - &pad)) - return NULL; - } - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_re_pad(self->db, pad); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_re_source(DBObject* self, PyObject* args, PyObject *kwargs) -{ - int err; - char *re_source; - char* kwnames[] = {"source", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:set_re_source", kwnames, - &re_source)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_re_source(self->db, re_source); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -#if (DBVER >= 32) -static PyObject* -DB_set_q_extentsize(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - int extentsize; - char* kwnames[] = {"extentsize", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_q_extentsize", - kwnames, &extentsize)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_q_extentsize(self->db, extentsize); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} -#endif - -static PyObject* -DB_stat(DBObject* self, PyObject* args, PyObject *kwargs) -{ - int err, flags = 0, type; - void* sp; - PyObject* d; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 33) -#if (DBVER >= 43) - err = self->db->stat(self->db, NULL, &sp, flags); -#else - err = self->db->stat(self->db, &sp, flags); -#endif -#else - err = self->db->stat(self->db, &sp, NULL, flags); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - self->haveStat = 1; - - /* Turn the stat structure into a dictionary */ - type = _DB_get_type(self); - if ((type == -1) || ((d = PyDict_New()) == NULL)) { - free(sp); - return NULL; - } - -#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name) -#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name) -#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name) - - switch (type) { - case DB_HASH: - MAKE_HASH_ENTRY(magic); - MAKE_HASH_ENTRY(version); - MAKE_HASH_ENTRY(nkeys); - MAKE_HASH_ENTRY(ndata); - MAKE_HASH_ENTRY(pagesize); -#if (DBVER < 41) - MAKE_HASH_ENTRY(nelem); -#endif - MAKE_HASH_ENTRY(ffactor); - MAKE_HASH_ENTRY(buckets); - MAKE_HASH_ENTRY(free); - MAKE_HASH_ENTRY(bfree); - MAKE_HASH_ENTRY(bigpages); - MAKE_HASH_ENTRY(big_bfree); - MAKE_HASH_ENTRY(overflows); - MAKE_HASH_ENTRY(ovfl_free); - MAKE_HASH_ENTRY(dup); - MAKE_HASH_ENTRY(dup_free); - break; - - case DB_BTREE: - case DB_RECNO: - MAKE_BT_ENTRY(magic); - MAKE_BT_ENTRY(version); - MAKE_BT_ENTRY(nkeys); - MAKE_BT_ENTRY(ndata); - MAKE_BT_ENTRY(pagesize); - MAKE_BT_ENTRY(minkey); - MAKE_BT_ENTRY(re_len); - MAKE_BT_ENTRY(re_pad); - MAKE_BT_ENTRY(levels); - MAKE_BT_ENTRY(int_pg); - MAKE_BT_ENTRY(leaf_pg); - MAKE_BT_ENTRY(dup_pg); - MAKE_BT_ENTRY(over_pg); - MAKE_BT_ENTRY(free); - MAKE_BT_ENTRY(int_pgfree); - MAKE_BT_ENTRY(leaf_pgfree); - MAKE_BT_ENTRY(dup_pgfree); - MAKE_BT_ENTRY(over_pgfree); - break; - - case DB_QUEUE: - MAKE_QUEUE_ENTRY(magic); - MAKE_QUEUE_ENTRY(version); - MAKE_QUEUE_ENTRY(nkeys); - MAKE_QUEUE_ENTRY(ndata); - MAKE_QUEUE_ENTRY(pagesize); - MAKE_QUEUE_ENTRY(pages); - MAKE_QUEUE_ENTRY(re_len); - MAKE_QUEUE_ENTRY(re_pad); - MAKE_QUEUE_ENTRY(pgfree); -#if (DBVER == 31) - MAKE_QUEUE_ENTRY(start); -#endif - MAKE_QUEUE_ENTRY(first_recno); - MAKE_QUEUE_ENTRY(cur_recno); - break; - - default: - PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat"); - Py_DECREF(d); - d = NULL; - } - -#undef MAKE_HASH_ENTRY -#undef MAKE_BT_ENTRY -#undef MAKE_QUEUE_ENTRY - - free(sp); - return d; -} - -static PyObject* -DB_sync(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - int flags = 0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:sync", kwnames, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->sync(self->db, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -#if (DBVER >= 33) -static PyObject* -DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - u_int32_t count=0; - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = { "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames, - &txnobj, &flags)) - return NULL; - CHECK_DB_NOT_CLOSED(self); - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->truncate(self->db, txn, &count, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - return PyInt_FromLong(count); -} -#endif - - -static PyObject* -DB_upgrade(DBObject* self, PyObject* args, PyObject *kwargs) -{ - int err, flags=0; - char *filename; - char* kwnames[] = {"filename", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:upgrade", kwnames, - &filename, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->upgrade(self->db, filename, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_verify(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - char* fileName; - char* dbName=NULL; - char* outFileName=NULL; - FILE* outFile=NULL; - char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames, - &fileName, &dbName, &outFileName, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - if (outFileName) - outFile = fopen(outFileName, "w"); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->verify(self->db, fileName, dbName, outFile, flags); - MYDB_END_ALLOW_THREADS; - if (outFileName) - fclose(outFile); - - /* DB.verify acts as a DB handle destructor (like close); this was - * documented in BerkeleyDB 4.2 but had the undocumented effect - * of not being safe in prior versions while still requiring an explicit - * DB.close call afterwards. Lets call close for the user to emulate - * the safe 4.2 behaviour. */ -#if (DBVER <= 41) - self->db->close(self->db, 0); -#endif - self->db = NULL; - - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DB_set_get_returns_none(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - int oldValue=0; - char* kwnames[] = {"returns_none", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_get_returns_none", - kwnames, &flags)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - - if (self->moduleFlags.getReturnsNone) - ++oldValue; - if (self->moduleFlags.cursorSetReturnsNone) - ++oldValue; - self->moduleFlags.getReturnsNone = (flags >= 1); - self->moduleFlags.cursorSetReturnsNone = (flags >= 2); - return PyInt_FromLong(oldValue); -} - -#if (DBVER >= 41) -static PyObject* -DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - u_int32_t flags=0; - char *passwd = NULL; - char* kwnames[] = { "passwd", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, - &passwd, &flags)) { - return NULL; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->set_encrypt(self->db, passwd, flags); - MYDB_END_ALLOW_THREADS; - - RETURN_IF_ERR(); - RETURN_NONE(); -} -#endif /* DBVER >= 41 */ - - -/*-------------------------------------------------------------- */ -/* Mapping and Dictionary-like access routines */ - -int DB_length(DBObject* self) -{ - int err; - long size = 0; - int flags = 0; - void* sp; - - if (self->db == NULL) { - PyErr_SetObject(DBError, - Py_BuildValue("(is)", 0, "DB object has been closed")); - return -1; - } - - if (self->haveStat) { /* Has the stat function been called recently? If - so, we can use the cached value. */ - flags = DB_CACHED_COUNTS; - } - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 33) -#if (DBVER >= 43) - err = self->db->stat(self->db, NULL, &sp, flags); -#else - err = self->db->stat(self->db, &sp, flags); -#endif -#else - err = self->db->stat(self->db, &sp, NULL, flags); -#endif - MYDB_END_ALLOW_THREADS; - - if (err) - return -1; - - self->haveStat = 1; - - /* All the stat structures have matching fields upto the ndata field, - so we can use any of them for the type cast */ - size = ((DB_BTREE_STAT*)sp)->bt_ndata; - free(sp); - return size; -} - - -PyObject* DB_subscript(DBObject* self, PyObject* keyobj) -{ - int err; - PyObject* retval; - DBT key; - DBT data; - - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL)) - return NULL; - - CLEAR_DBT(data); - if (CHECK_DBFLAG(self, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - } - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get(self->db, NULL, &key, &data, 0); - MYDB_END_ALLOW_THREADS; - if (err == DB_NOTFOUND || err == DB_KEYEMPTY) { - PyErr_SetObject(PyExc_KeyError, keyobj); - retval = NULL; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { - retval = PyString_FromStringAndSize((char*)data.data, data.size); - FREE_DBT(data); - } - - FREE_DBT(key); - return retval; -} - - -static int -DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj) -{ - DBT key, data; - int retval; - int flags = 0; - - if (self->db == NULL) { - PyErr_SetObject(DBError, - Py_BuildValue("(is)", 0, "DB object has been closed")); - return -1; - } - - if (!make_key_dbt(self, keyobj, &key, NULL)) - return -1; - - if (dataobj != NULL) { - if (!make_dbt(dataobj, &data)) - retval = -1; - else { - if (self->setflags & (DB_DUP|DB_DUPSORT)) - /* dictionaries shouldn't have duplicate keys */ - flags = DB_NOOVERWRITE; - retval = _DB_put(self, NULL, &key, &data, flags); - - if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) { - /* try deleting any old record that matches and then PUT it - * again... */ - _DB_delete(self, NULL, &key, 0); - PyErr_Clear(); - retval = _DB_put(self, NULL, &key, &data, flags); - } - } - } - else { - /* dataobj == NULL, so delete the key */ - retval = _DB_delete(self, NULL, &key, 0); - } - FREE_DBT(key); - return retval; -} - - -static PyObject* -DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - PyObject* keyobj; - DBT key, data; - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = {"key", "txn", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames, - &keyobj, &txnobj)) - return NULL; - - CHECK_DB_NOT_CLOSED(self); - if (!make_key_dbt(self, keyobj, &key, NULL)) - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - - /* This causes ENOMEM to be returned when the db has the key because - it has a record but can't allocate a buffer for the data. This saves - having to deal with data we won't be using. - */ - CLEAR_DBT(data); - data.flags = DB_DBT_USERMEM; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->get(self->db, NULL, &key, &data, 0); - MYDB_END_ALLOW_THREADS; - FREE_DBT(key); - return PyInt_FromLong((err == ENOMEM) || (err == 0)); -} - - -#define _KEYS_LIST 1 -#define _VALUES_LIST 2 -#define _ITEMS_LIST 3 - -static PyObject* -_DB_make_list(DBObject* self, DB_TXN* txn, int type) -{ - int err, dbtype; - DBT key; - DBT data; - DBC *cursor; - PyObject* list; - PyObject* item = NULL; - - CHECK_DB_NOT_CLOSED(self); - CLEAR_DBT(key); - CLEAR_DBT(data); - - dbtype = _DB_get_type(self); - if (dbtype == -1) - return NULL; - - list = PyList_New(0); - if (list == NULL) { - PyErr_SetString(PyExc_MemoryError, "PyList_New failed"); - return NULL; - } - - /* get a cursor */ - MYDB_BEGIN_ALLOW_THREADS; - err = self->db->cursor(self->db, NULL, &cursor, 0); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - if (CHECK_DBFLAG(self, DB_THREAD)) { - key.flags = DB_DBT_REALLOC; - data.flags = DB_DBT_REALLOC; - } - - while (1) { /* use the cursor to traverse the DB, collecting items */ - MYDB_BEGIN_ALLOW_THREADS; - err = cursor->c_get(cursor, &key, &data, DB_NEXT); - MYDB_END_ALLOW_THREADS; - - if (err) { - /* for any error, break out of the loop */ - break; - } - - switch (type) { - case _KEYS_LIST: - switch(dbtype) { - case DB_BTREE: - case DB_HASH: - default: - item = PyString_FromStringAndSize((char*)key.data, key.size); - break; - case DB_RECNO: - case DB_QUEUE: - item = PyInt_FromLong(*((db_recno_t*)key.data)); - break; - } - break; - - case _VALUES_LIST: - item = PyString_FromStringAndSize((char*)data.data, data.size); - break; - - case _ITEMS_LIST: - switch(dbtype) { - case DB_BTREE: - case DB_HASH: - default: - item = Py_BuildValue("s#s#", key.data, key.size, data.data, - data.size); - break; - case DB_RECNO: - case DB_QUEUE: - item = Py_BuildValue("is#", *((db_recno_t*)key.data), - data.data, data.size); - break; - } - break; - } - if (item == NULL) { - Py_DECREF(list); - PyErr_SetString(PyExc_MemoryError, "List item creation failed"); - list = NULL; - goto done; - } - PyList_Append(list, item); - Py_DECREF(item); - } - - /* DB_NOTFOUND is okay, it just means we got to the end */ - if (err != DB_NOTFOUND && makeDBError(err)) { - Py_DECREF(list); - list = NULL; - } - - done: - FREE_DBT(key); - FREE_DBT(data); - MYDB_BEGIN_ALLOW_THREADS; - cursor->c_close(cursor); - MYDB_END_ALLOW_THREADS; - return list; -} - - -static PyObject* -DB_keys(DBObject* self, PyObject* args, PyObject* kwargs) -{ - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = {"txn", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:keys", kwnames, &txnobj)) - return NULL; - - if (!checkTxnObj(txnobj, &txn)) - return NULL; - return _DB_make_list(self, txn, _KEYS_LIST); -} - - -static PyObject* -DB_items(DBObject* self, PyObject* args, PyObject* kwargs) -{ - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = {"txn", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:items", kwnames, - &txnobj)) - return NULL; - - if (!checkTxnObj(txnobj, &txn)) - return NULL; - return _DB_make_list(self, txn, _ITEMS_LIST); -} - - -static PyObject* -DB_values(DBObject* self, PyObject* args, PyObject* kwargs) -{ - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = {"txn", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O:values", kwnames, - &txnobj)) - return NULL; - if (!checkTxnObj(txnobj, &txn)) - return NULL; - return _DB_make_list(self, txn, _VALUES_LIST); -} - -/* --------------------------------------------------------------------- */ -/* DBCursor methods */ - - -static PyObject* -DBC_close(DBCursorObject* self) -{ - int err = 0; - - if (self->dbc != NULL) { - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_close(self->dbc); - self->dbc = NULL; - MYDB_END_ALLOW_THREADS; - } - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBC_count(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int err = 0; - db_recno_t count; - int flags = 0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:count", kwnames, &flags)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_count(self->dbc, &count, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - return PyInt_FromLong(count); -} - - -static PyObject* -DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current"); -} - - -static PyObject* -DBC_delete(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:delete", kwnames, - &flags)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_del(self->dbc, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - self->mydb->haveStat = 0; - RETURN_NONE(); -} - - -static PyObject* -DBC_dup(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags =0; - DBC* dbc = NULL; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:dup", kwnames, &flags)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_dup(self->dbc, &dbc, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - return (PyObject*) newDBCursorObject(dbc, self->mydb); -} - -static PyObject* -DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first"); -} - - -static PyObject* -DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - int err, flags=0; - PyObject* keyobj = NULL; - PyObject* dataobj = NULL; - PyObject* retval = NULL; - int dlen = -1; - int doff = -1; - DBT key, data; - char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL }; - - CLEAR_DBT(key); - CLEAR_DBT(data); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2], - &flags, &dlen, &doff)) - { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get", - &kwnames[1], - &keyobj, &flags, &dlen, &doff)) - { - PyErr_Clear(); - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get", - kwnames, &keyobj, &dataobj, - &flags, &dlen, &doff)) - { - return NULL; - } - } - } - - CHECK_CURSOR_NOT_CLOSED(self); - - if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL)) - return NULL; - if (dataobj && !make_dbt(dataobj, &data)) - return NULL; - if (!add_partial_dbt(&data, dlen, doff)) - return NULL; - - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - - - if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { - switch (_DB_get_type(self->mydb)) { - case -1: - retval = NULL; - break; - case DB_BTREE: - case DB_HASH: - default: - retval = Py_BuildValue("s#s#", key.data, key.size, - data.data, data.size); - break; - case DB_RECNO: - case DB_QUEUE: - retval = Py_BuildValue("is#", *((db_recno_t*)key.data), - data.data, data.size); - break; - } - FREE_DBT(key); - FREE_DBT(data); - } - return retval; -} - - -static PyObject* -DBC_get_recno(DBCursorObject* self) -{ - int err; - db_recno_t recno; - DBT key; - DBT data; - - CHECK_CURSOR_NOT_CLOSED(self); - - CLEAR_DBT(key); - CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - recno = *((db_recno_t*)data.data); - FREE_DBT(key); - FREE_DBT(data); - return PyInt_FromLong(recno); -} - - -static PyObject* -DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last"); -} - - -static PyObject* -DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next"); -} - - -static PyObject* -DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev"); -} - - -static PyObject* -DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags = 0; - PyObject* keyobj, *dataobj; - DBT key, data; - char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL }; - int dlen = -1; - int doff = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames, - &keyobj, &dataobj, &flags, &dlen, &doff)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) - return NULL; - if (!make_dbt(dataobj, &data)) - return NULL; - if (!add_partial_dbt(&data, dlen, doff)) return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_put(self->dbc, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - FREE_DBT(key); - RETURN_IF_ERR(); - self->mydb->haveStat = 0; - RETURN_NONE(); -} - - -static PyObject* -DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - int err, flags = 0; - DBT key, data; - PyObject* retval, *keyobj; - char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; - int dlen = -1; - int doff = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames, - &keyobj, &flags, &dlen, &doff)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) - return NULL; - - CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - } - if (!add_partial_dbt(&data, dlen, doff)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET); - MYDB_END_ALLOW_THREADS; - if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { - switch (_DB_get_type(self->mydb)) { - case -1: - retval = NULL; - break; - case DB_BTREE: - case DB_HASH: - default: - retval = Py_BuildValue("s#s#", key.data, key.size, - data.data, data.size); - break; - case DB_RECNO: - case DB_QUEUE: - retval = Py_BuildValue("is#", *((db_recno_t*)key.data), - data.data, data.size); - break; - } - FREE_DBT(key); - FREE_DBT(data); - } - - return retval; -} - - -static PyObject* -DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags = 0; - DBT key, data; - PyObject* retval, *keyobj; - char* kwnames[] = { "key", "flags", "dlen", "doff", NULL }; - int dlen = -1; - int doff = -1; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames, - &keyobj, &flags, &dlen, &doff)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) - return NULL; - - CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - key.flags = DB_DBT_MALLOC; - } - if (!add_partial_dbt(&data, dlen, doff)) - return NULL; - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE); - MYDB_END_ALLOW_THREADS; - if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { - switch (_DB_get_type(self->mydb)) { - case -1: - retval = NULL; - break; - case DB_BTREE: - case DB_HASH: - default: - retval = Py_BuildValue("s#s#", key.data, key.size, - data.data, data.size); - break; - case DB_RECNO: - case DB_QUEUE: - retval = Py_BuildValue("is#", *((db_recno_t*)key.data), - data.data, data.size); - break; - } - FREE_DBT(key); - FREE_DBT(data); - } - - return retval; -} - -static PyObject* -_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj, - int flags, unsigned int returnsNone) -{ - int err; - DBT key, data; - PyObject* retval; - - /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */ - if (!make_key_dbt(self->mydb, keyobj, &key, NULL)) - return NULL; - if (!make_dbt(dataobj, &data)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH); - MYDB_END_ALLOW_THREADS; - if ((err == DB_NOTFOUND) && returnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { - switch (_DB_get_type(self->mydb)) { - case -1: - retval = NULL; - break; - case DB_BTREE: - case DB_HASH: - default: - retval = Py_BuildValue("s#s#", key.data, key.size, - data.data, data.size); - break; - case DB_RECNO: - case DB_QUEUE: - retval = Py_BuildValue("is#", *((db_recno_t*)key.data), - data.data, data.size); - break; - } - } - - FREE_DBT(key); - return retval; -} - -static PyObject* -DBC_get_both(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - PyObject *keyobj, *dataobj; - char* kwnames[] = {"key", "data", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:get_both", kwnames, - &keyobj, &dataobj, &flags)) - return NULL; - - /* if the cursor is closed, self->mydb may be invalid */ - CHECK_CURSOR_NOT_CLOSED(self); - - return _DBC_get_set_both(self, keyobj, dataobj, flags, - self->mydb->moduleFlags.getReturnsNone); -} - -/* Return size of entry */ -static PyObject* -DBC_get_current_size(DBCursorObject* self) -{ - int err, flags=DB_CURRENT; - PyObject* retval = NULL; - DBT key, data; - - CHECK_CURSOR_NOT_CLOSED(self); - CLEAR_DBT(key); - CLEAR_DBT(data); - - /* We don't allocate any memory, forcing a ENOMEM error and thus - getting the record size. */ - data.flags = DB_DBT_USERMEM; - data.ulen = 0; - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags); - MYDB_END_ALLOW_THREADS; - if (err == ENOMEM || !err) { - /* ENOMEM means positive size, !err means zero length value */ - retval = PyInt_FromLong((long)data.size); - err = 0; - } - - FREE_DBT(key); - FREE_DBT(data); - RETURN_IF_ERR(); - return retval; -} - -static PyObject* -DBC_set_both(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - PyObject *keyobj, *dataobj; - char* kwnames[] = {"key", "data", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:set_both", kwnames, - &keyobj, &dataobj, &flags)) - return NULL; - - /* if the cursor is closed, self->mydb may be invalid */ - CHECK_CURSOR_NOT_CLOSED(self); - - return _DBC_get_set_both(self, keyobj, dataobj, flags, - self->mydb->moduleFlags.cursorSetReturnsNone); -} - - -static PyObject* -DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - int err, irecno, flags=0; - db_recno_t recno; - DBT key, data; - PyObject* retval; - int dlen = -1; - int doff = -1; - char* kwnames[] = { "recno","flags", "dlen", "doff", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames, - &irecno, &flags, &dlen, &doff)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - CLEAR_DBT(key); - recno = (db_recno_t) irecno; - /* use allocated space so DB will be able to realloc room for the real - * key */ - key.data = malloc(sizeof(db_recno_t)); - if (key.data == NULL) { - PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed"); - return NULL; - } - key.size = sizeof(db_recno_t); - key.ulen = key.size; - memcpy(key.data, &recno, sizeof(db_recno_t)); - key.flags = DB_DBT_REALLOC; - - CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - data.flags = DB_DBT_MALLOC; - } - if (!add_partial_dbt(&data, dlen, doff)) - return NULL; - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO); - MYDB_END_ALLOW_THREADS; - if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { /* Can only be used for BTrees, so no need to return int key */ - retval = Py_BuildValue("s#s#", key.data, key.size, - data.data, data.size); - FREE_DBT(key); - FREE_DBT(data); - } - - return retval; -} - - -static PyObject* -DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume"); -} - - -static PyObject* -DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup"); -} - - -static PyObject* -DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup"); -} - - -static PyObject* -DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs) -{ - return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup"); -} - - -static PyObject* -DBC_join_item(DBCursorObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0; - DBT key, data; - PyObject* retval; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:join_item", kwnames, - &flags)) - return NULL; - - CHECK_CURSOR_NOT_CLOSED(self); - - CLEAR_DBT(key); - CLEAR_DBT(data); - if (CHECK_DBFLAG(self->mydb, DB_THREAD)) { - /* Tell BerkeleyDB to malloc the return value (thread safe) */ - key.flags = DB_DBT_MALLOC; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM); - MYDB_END_ALLOW_THREADS; - if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) { - Py_INCREF(Py_None); - retval = Py_None; - } - else if (makeDBError(err)) { - retval = NULL; - } - else { - retval = Py_BuildValue("s#", key.data, key.size); - FREE_DBT(key); - } - - return retval; -} - - - -/* --------------------------------------------------------------------- */ -/* DBEnv methods */ - - -static PyObject* -DBEnv_close(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags = 0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:close", kwnames, &flags)) - return NULL; - if (!self->closed) { /* Don't close more than once */ - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->close(self->db_env, flags); - MYDB_END_ALLOW_THREADS; - /* after calling DBEnv->close, regardless of error, this DBEnv - * may not be accessed again (BerkeleyDB docs). */ - self->closed = 1; - self->db_env = NULL; - RETURN_IF_ERR(); - } - RETURN_NONE(); -} - - -static PyObject* -DBEnv_open(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0, mode=0660; - char *db_home; - char* kwnames[] = {"db_home", "flags", "mode", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ii:open", kwnames, - &db_home, &flags, &mode)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->open(self->db_env, db_home, flags, mode); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - self->closed = 0; - self->flags = flags; - RETURN_NONE(); -} - - -static PyObject* -DBEnv_remove(DBEnvObject* self, PyObject* args, PyObject *kwargs) -{ - int err, flags=0; - char *db_home; - char* kwnames[] = {"db_home", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:remove", kwnames, - &db_home, &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->remove(self->db_env, db_home, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -#if (DBVER >= 41) -static PyObject* -DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - u_int32_t flags=0; - char *file = NULL; - char *database = NULL; - PyObject *txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = { "file", "database", "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames, - &file, &database, &txnobj, &flags)) { - return NULL; - } - if (!checkTxnObj(txnobj, &txn)) { - return NULL; - } - CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->dbremove(self->db_env, txn, file, database, flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -static PyObject* -DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - u_int32_t flags=0; - char *file = NULL; - char *database = NULL; - char *newname = NULL; - PyObject *txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames, - &file, &database, &newname, &txnobj, &flags)) { - return NULL; - } - if (!checkTxnObj(txnobj, &txn)) { - return NULL; - } - CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->dbrename(self->db_env, txn, file, database, newname, - flags); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -static PyObject* -DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - u_int32_t flags=0; - char *passwd = NULL; - char* kwnames[] = { "passwd", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames, - &passwd, &flags)) { - return NULL; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_encrypt(self->db_env, passwd, flags); - MYDB_END_ALLOW_THREADS; - - RETURN_IF_ERR(); - RETURN_NONE(); -} -#endif /* DBVER >= 41 */ - -#if (DBVER >= 40) -static PyObject* -DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - u_int32_t flags=0; - u_int32_t timeout = 0; - char* kwnames[] = { "timeout", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames, - &timeout, &flags)) { - return NULL; - } - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags); - MYDB_END_ALLOW_THREADS; - - RETURN_IF_ERR(); - RETURN_NONE(); -} -#endif /* DBVER >= 40 */ - -static PyObject* -DBEnv_set_shm_key(DBEnvObject* self, PyObject* args, PyObject *kwargs) -{ - int err; - long shm_key = 0; - char* kwnames[] = {"shm_key", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "l:set_shm_key", kwnames, - &shm_key)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - err = self->db_env->set_shm_key(self->db_env, shm_key); - RETURN_IF_ERR(); - RETURN_NONE(); -} - -static PyObject* -DBEnv_set_cachesize(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, gbytes=0, bytes=0, ncache=0; - char* kwnames[] = {"gbytes", "bytes", "ncache", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:set_cachesize", - kwnames, &gbytes, &bytes, &ncache)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -#if (DBVER >= 32) -static PyObject* -DBEnv_set_flags(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, flags=0, onoff=0; - char* kwnames[] = {"flags", "onoff", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_flags", kwnames, - &flags, &onoff)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_flags(self->db_env, flags, onoff); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} -#endif - - -static PyObject* -DBEnv_set_data_dir(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - char *dir; - char* kwnames[] = {"dir", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:set_data_dir", kwnames, - &dir)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_data_dir(self->db_env, dir); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, lg_bsize; - char* kwnames[] = {"lg_bsize", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lg_bsize", kwnames, - &lg_bsize)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lg_bsize(self->db_env, lg_bsize); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - char *dir; - char* kwnames[] = {"dir", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:set_lg_dir", kwnames, - &dir)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lg_dir(self->db_env, dir); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -static PyObject* -DBEnv_set_lg_max(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, lg_max; - char* kwnames[] = {"lg_max", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lg_max", kwnames, - &lg_max)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lg_max(self->db_env, lg_max); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args, PyObject *kwargs) -{ - int err, lk_detect; - char* kwnames[] = {"lk_detect", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lk_detect", kwnames, - &lk_detect)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lk_detect(self->db_env, lk_detect); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_lk_max(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, max; - char* kwnames[] = {"max", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lk_max", kwnames, - &max)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lk_max(self->db_env, max); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -#if (DBVER >= 32) - -static PyObject* -DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, max; - char* kwnames[] = {"max_locks", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lk_max_locks", - kwnames, &max)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lk_max_locks(self->db_env, max); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, max; - char* kwnames[] = {"max_lockers", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lk_max_lockers", - kwnames, &max)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lk_max_lockers(self->db_env, max); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, max; - char* kwnames[] = {"max_objects", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_lk_max_objects", - kwnames, &max)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_lk_max_objects(self->db_env, max); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -#endif - - -static PyObject* -DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, mp_mmapsize; - char* kwnames[] = {"mp_mmapsize", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_mp_mmapsize", kwnames, - &mp_mmapsize)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - char *dir; - char* kwnames[] = {"dir", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:set_tmp_dir", kwnames, - &dir)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_tmp_dir(self->db_env, dir); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int flags = 0; - PyObject* txnobj = NULL; - DB_TXN *txn = NULL; - char* kwnames[] = { "parent", "flags", NULL }; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames, - &txnobj, &flags)) - return NULL; - - if (!checkTxnObj(txnobj, &txn)) - return NULL; - CHECK_ENV_NOT_CLOSED(self); - - return (PyObject*)newDBTxnObject(self, txn, flags); -} - - -static PyObject* -DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, kbyte=0, min=0, flags=0; - char* kwnames[] = {"kbyte", "min", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iii:txn_checkpoint", - kwnames, &kbyte, &min, &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags); -#else - err = txn_checkpoint(self->db_env, kbyte, min, flags); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_set_tx_max(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, max; - char* kwnames[] = {"max", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:set_tx_max", kwnames, - &max)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; - err = self->db_env->set_tx_max(self->db_env, max); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_lock_detect(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err, atype, flags=0; - int aborted = 0; - char* kwnames[] = {"atype", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i:lock_detect", kwnames, - &atype, &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted); -#else - err = lock_detect(self->db_env, flags, atype, &aborted); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - return PyInt_FromLong(aborted); -} - - -static PyObject* -DBEnv_lock_get(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - int locker, lock_mode; - DBT obj; - PyObject* objobj; - char* kwnames[] = {"locker", "object", "mode", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iOi|i:lock_get", kwnames, - &locker, &objobj, &lock_mode, &flags)) - return NULL; - - if (!make_dbt(objobj, &obj)) - return NULL; - - return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags); -} - - -static PyObject* -DBEnv_lock_id(DBEnvObject* self) -{ - int err; - u_int32_t theID; - - CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->lock_id(self->db_env, &theID); -#else - err = lock_id(self->db_env, &theID); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - return PyInt_FromLong((long)theID); -} - - -static PyObject* -DBEnv_lock_put(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - DBLockObject* dblockobj; - char* kwnames[] = {"lock_type", "object", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:lock_put", kwnames, - &DBLock_Type, &dblockobj)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->lock_put(self->db_env, &dblockobj->lock); -#else - err = lock_put(self->db_env, &dblockobj->lock); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBEnv_lock_stat(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - DB_LOCK_STAT* sp; - PyObject* d = NULL; - u_int32_t flags = 0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:lock_stat", kwnames, - &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->lock_stat(self->db_env, &sp, flags); -#else -#if (DBVER >= 33) - err = lock_stat(self->db_env, &sp); -#else - err = lock_stat(self->db_env, &sp, NULL); -#endif -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - /* Turn the stat structure into a dictionary */ - d = PyDict_New(); - if (d == NULL) { - free(sp); - return NULL; - } - -#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) - -#if (DBVER < 41) - MAKE_ENTRY(lastid); -#endif - MAKE_ENTRY(nmodes); -#if (DBVER >= 32) - MAKE_ENTRY(maxlocks); - MAKE_ENTRY(maxlockers); - MAKE_ENTRY(maxobjects); - MAKE_ENTRY(nlocks); - MAKE_ENTRY(maxnlocks); -#endif - MAKE_ENTRY(nlockers); - MAKE_ENTRY(maxnlockers); -#if (DBVER >= 32) - MAKE_ENTRY(nobjects); - MAKE_ENTRY(maxnobjects); -#endif - MAKE_ENTRY(nrequests); - MAKE_ENTRY(nreleases); - MAKE_ENTRY(nnowaits); - MAKE_ENTRY(nconflicts); - MAKE_ENTRY(ndeadlocks); - MAKE_ENTRY(regsize); - MAKE_ENTRY(region_wait); - MAKE_ENTRY(region_nowait); - -#undef MAKE_ENTRY - free(sp); - return d; -} - - -static PyObject* -DBEnv_log_archive(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - int err; - char **log_list_start, **log_list; - PyObject* list; - PyObject* item = NULL; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:log_archive", kwnames, - &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->log_archive(self->db_env, &log_list, flags); -#elif (DBVER == 33) - err = log_archive(self->db_env, &log_list, flags); -#else - err = log_archive(self->db_env, &log_list, flags, NULL); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - list = PyList_New(0); - if (list == NULL) { - PyErr_SetString(PyExc_MemoryError, "PyList_New failed"); - return NULL; - } - - if (log_list) { - for (log_list_start = log_list; *log_list != NULL; ++log_list) { - item = PyString_FromString (*log_list); - if (item == NULL) { - Py_DECREF(list); - PyErr_SetString(PyExc_MemoryError, - "List item creation failed"); - list = NULL; - break; - } - PyList_Append(list, item); - Py_DECREF(item); - } - free(log_list_start); - } - return list; -} - - -static PyObject* -DBEnv_txn_stat(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int err; - DB_TXN_STAT* sp; - PyObject* d = NULL; - u_int32_t flags=0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:txn_stat", kwnames, - &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->db_env->txn_stat(self->db_env, &sp, flags); -#elif (DBVER == 33) - err = txn_stat(self->db_env, &sp); -#else - err = txn_stat(self->db_env, &sp, NULL); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - - /* Turn the stat structure into a dictionary */ - d = PyDict_New(); - if (d == NULL) { - free(sp); - return NULL; - } - -#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name) - - MAKE_ENTRY(time_ckp); - MAKE_ENTRY(last_txnid); - MAKE_ENTRY(maxtxns); - MAKE_ENTRY(nactive); - MAKE_ENTRY(maxnactive); - MAKE_ENTRY(nbegins); - MAKE_ENTRY(naborts); - MAKE_ENTRY(ncommits); - MAKE_ENTRY(regsize); - MAKE_ENTRY(region_wait); - MAKE_ENTRY(region_nowait); - -#undef MAKE_ENTRY - free(sp); - return d; -} - - -static PyObject* -DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0; - int oldValue=0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs,"i:set_get_returns_none", - kwnames, &flags)) - return NULL; - - CHECK_ENV_NOT_CLOSED(self); - - if (self->moduleFlags.getReturnsNone) - ++oldValue; - if (self->moduleFlags.cursorSetReturnsNone) - ++oldValue; - self->moduleFlags.getReturnsNone = (flags >= 1); - self->moduleFlags.cursorSetReturnsNone = (flags >= 2); - return PyInt_FromLong(oldValue); -} - - -/* --------------------------------------------------------------------- */ -/* DBTxn methods */ - - -static PyObject* -DBTxn_commit(DBTxnObject* self, PyObject* args, PyObject* kwargs) -{ - int flags=0, err; - DB_TXN *txn; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:commit", kwnames, - &flags)) - return NULL; - - if (!self->txn) { - PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, - "DBTxn must not be used after txn_commit or txn_abort")); - return NULL; - } - txn = self->txn; - self->txn = NULL; /* this DB_TXN is no longer valid after this call */ - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = txn->commit(txn, flags); -#else - err = txn_commit(txn, flags); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - -static PyObject* -DBTxn_prepare(DBTxnObject* self, PyObject* args, PyObject* kwargs) -{ -#if (DBVER >= 33) - int err; - char* gid=NULL; - int gid_size=0; - char* kwnames[] = {"gid", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#:prepare", kwnames, &gid, - &gid_size)) - return NULL; - - if (gid_size != DB_XIDDATASIZE) { - PyErr_SetString(PyExc_TypeError, - "gid must be DB_XIDDATASIZE bytes long"); - return NULL; - } - - if (!self->txn) { - PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, - "DBTxn must not be used after txn_commit or txn_abort")); - return NULL; - } - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = self->txn->prepare(self->txn, (u_int8_t*)gid); -#else - err = txn_prepare(self->txn, (u_int8_t*)gid); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -#else - int err; - char* kwnames[] = {NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":prepare", kwnames)) - return NULL; - - if (!self->txn) { - PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, - "DBTxn must not be used after txn_commit or txn_abort")); - return NULL; - } - MYDB_BEGIN_ALLOW_THREADS; - err = txn_prepare(self->txn); - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -#endif -} - - -static PyObject* -DBTxn_abort(DBTxnObject* self) -{ - int err; - DB_TXN *txn; - - if (!self->txn) { - PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, - "DBTxn must not be used after txn_commit or txn_abort")); - return NULL; - } - txn = self->txn; - self->txn = NULL; /* this DB_TXN is no longer valid after this call */ - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - err = txn->abort(txn); -#else - err = txn_abort(txn); -#endif - MYDB_END_ALLOW_THREADS; - RETURN_IF_ERR(); - RETURN_NONE(); -} - - -static PyObject* -DBTxn_id(DBTxnObject* self) -{ - int id; - - if (!self->txn) { - PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, - "DBTxn must not be used after txn_commit or txn_abort")); - return NULL; - } - MYDB_BEGIN_ALLOW_THREADS; -#if (DBVER >= 40) - id = self->txn->id(self->txn); -#else - id = txn_id(self->txn); -#endif - MYDB_END_ALLOW_THREADS; - return PyInt_FromLong(id); -} - -/* --------------------------------------------------------------------- */ -/* Method definition tables and type objects */ - -static PyMethodDef DB_methods[] = { - {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 33) - {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS}, -#endif - {"close", (PyCFunction)DB_close, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 32) - {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS}, - {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS}, -#endif - {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS}, - {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS}, - {"fd", (PyCFunction)DB_fd, METH_NOARGS}, - {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS}, - {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS}, - {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS}, - {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS}, - {"get_type", (PyCFunction)DB_get_type, METH_NOARGS}, - {"join", (PyCFunction)DB_join, METH_VARARGS|METH_KEYWORDS}, - {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS}, - {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS}, - {"items", (PyCFunction)DB_items, METH_VARARGS|METH_KEYWORDS}, - {"keys", (PyCFunction)DB_keys, METH_VARARGS|METH_KEYWORDS}, - {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS}, - {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS}, - {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS}, - {"rename", (PyCFunction)DB_rename, METH_VARARGS|METH_KEYWORDS}, - {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS|METH_KEYWORDS}, - {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 41) - {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS}, -#endif - {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS|METH_KEYWORDS}, - {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS|METH_KEYWORDS}, - {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS|METH_KEYWORDS}, - {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS|METH_KEYWORDS}, - {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS|METH_KEYWORDS}, - {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS|METH_KEYWORDS}, - {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS|METH_KEYWORDS}, - {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS|METH_KEYWORDS}, - {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 32) - {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS|METH_KEYWORDS}, -#endif - {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS}, - {"sync", (PyCFunction)DB_sync, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 33) - {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS}, -#endif - {"type", (PyCFunction)DB_get_type, METH_VARARGS|METH_KEYWORDS}, - {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS|METH_KEYWORDS}, - {"values", (PyCFunction)DB_values, METH_VARARGS|METH_KEYWORDS}, - {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS}, - {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS|METH_KEYWORDS}, - {NULL, NULL} /* sentinel */ -}; - - -static PyMappingMethods DB_mapping = { - (inquiry)DB_length, /*mp_length*/ - (binaryfunc)DB_subscript, /*mp_subscript*/ - (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/ -}; - - -static PyMethodDef DBCursor_methods[] = { - {"close", (PyCFunction)DBC_close, METH_NOARGS}, - {"count", (PyCFunction)DBC_count, METH_VARARGS|METH_KEYWORDS}, - {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS}, - {"delete", (PyCFunction)DBC_delete, METH_VARARGS|METH_KEYWORDS}, - {"dup", (PyCFunction)DBC_dup, METH_VARARGS|METH_KEYWORDS}, - {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS}, - {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS}, - {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS}, - {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS}, - {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS}, - {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS}, - {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS}, - {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS}, - {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS}, - {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS|METH_KEYWORDS}, - {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS}, - {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS|METH_KEYWORDS}, - {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS}, - {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS}, - {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS}, - {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS}, - {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS}, - {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS|METH_KEYWORDS}, - {NULL, NULL} /* sentinel */ -}; - - -static PyMethodDef DBEnv_methods[] = { - {"close", (PyCFunction)DBEnv_close, METH_VARARGS|METH_KEYWORDS}, - {"open", (PyCFunction)DBEnv_open, METH_VARARGS|METH_KEYWORDS}, - {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 41) - {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS}, - {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS}, - {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS}, -#endif -#if (DBVER >= 40) - {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS}, -#endif - {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS|METH_KEYWORDS}, - {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS|METH_KEYWORDS}, - {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 32) - {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS|METH_KEYWORDS}, -#endif - {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS|METH_KEYWORDS}, - {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS|METH_KEYWORDS}, - {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS|METH_KEYWORDS}, - {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS|METH_KEYWORDS}, - {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS|METH_KEYWORDS}, -#if (DBVER >= 32) - {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS|METH_KEYWORDS}, - {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS|METH_KEYWORDS}, - {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS|METH_KEYWORDS}, -#endif - {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS|METH_KEYWORDS}, - {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS|METH_KEYWORDS}, - {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS}, - {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS|METH_KEYWORDS}, - {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS|METH_KEYWORDS}, - {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS|METH_KEYWORDS}, - {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS|METH_KEYWORDS}, - {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS|METH_KEYWORDS}, - {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS}, - {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS|METH_KEYWORDS}, - {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS|METH_KEYWORDS}, - {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS|METH_KEYWORDS}, - {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS|METH_KEYWORDS}, - {NULL, NULL} /* sentinel */ -}; - - -static PyMethodDef DBTxn_methods[] = { - {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS|METH_KEYWORDS}, - {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS|METH_KEYWORDS}, - {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS}, - {"id", (PyCFunction)DBTxn_id, METH_NOARGS}, - {NULL, NULL} /* sentinel */ -}; - - -static PyObject* -DB_getattr(DBObject* self, char *name) -{ - return Py_FindMethod(DB_methods, (PyObject* )self, name); -} - - -static PyObject* -DBEnv_getattr(DBEnvObject* self, char *name) -{ - if (!strcmp(name, "db_home")) { - CHECK_ENV_NOT_CLOSED(self); - if (self->db_env->db_home == NULL) { - RETURN_NONE(); - } - return PyString_FromString(self->db_env->db_home); - } - - return Py_FindMethod(DBEnv_methods, (PyObject* )self, name); -} - - -static PyObject* -DBCursor_getattr(DBCursorObject* self, char *name) -{ - return Py_FindMethod(DBCursor_methods, (PyObject* )self, name); -} - -static PyObject* -DBTxn_getattr(DBTxnObject* self, char *name) -{ - return Py_FindMethod(DBTxn_methods, (PyObject* )self, name); -} - -static PyObject* -DBLock_getattr(DBLockObject* self, char *name) -{ - return NULL; -} - -statichere PyTypeObject DB_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DB", /*tp_name*/ - sizeof(DBObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)DB_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)DB_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - &DB_mapping,/*tp_as_mapping*/ - 0, /*tp_hash*/ -}; - - -statichere PyTypeObject DBCursor_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DBCursor", /*tp_name*/ - sizeof(DBCursorObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)DBCursor_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)DBCursor_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ -#ifdef HAVE_WEAKREF - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */ - 0, /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */ -#endif -}; - - -statichere PyTypeObject DBEnv_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DBEnv", /*tp_name*/ - sizeof(DBEnvObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)DBEnv_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)DBEnv_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ -}; - -statichere PyTypeObject DBTxn_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DBTxn", /*tp_name*/ - sizeof(DBTxnObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)DBTxn_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)DBTxn_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ -}; - - -statichere PyTypeObject DBLock_Type = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "DBLock", /*tp_name*/ - sizeof(DBLockObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)DBLock_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - (getattrfunc)DBLock_getattr, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ -}; - - -/* --------------------------------------------------------------------- */ -/* Module-level functions */ - -static PyObject* -DB_construct(PyObject* self, PyObject* args, PyObject* kwargs) -{ - PyObject* dbenvobj = NULL; - int flags = 0; - char* kwnames[] = { "dbEnv", "flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames, - &dbenvobj, &flags)) - return NULL; - if (dbenvobj == Py_None) - dbenvobj = NULL; - else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) { - makeTypeError("DBEnv", dbenvobj); - return NULL; - } - - return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags); -} - - -static PyObject* -DBEnv_construct(PyObject* self, PyObject* args, PyObject* kwargs) -{ - int flags = 0; - char* kwnames[] = {"flags", NULL}; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:DbEnv", kwnames, &flags)) - return NULL; - - return (PyObject* )newDBEnvObject(flags); -} - - -static char bsddb_version_doc[] = -"Returns a tuple of major, minor, and patch release numbers of the\n\ -underlying DB library."; - -static PyObject* -bsddb_version(PyObject* self) -{ - int major, minor, patch; - - db_version(&major, &minor, &patch); - return Py_BuildValue("(iii)", major, minor, patch); -} - - -/* List of functions defined in the module */ - -static PyMethodDef bsddb_methods[] = { - {"DB", (PyCFunction)DB_construct, METH_VARARGS|METH_KEYWORDS}, - {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS|METH_KEYWORDS}, - {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc}, - {NULL, NULL} /* sentinel */ -}; - - -/* --------------------------------------------------------------------- */ -/* Module initialization */ - - -/* Convenience routine to export an integer value. - * Errors are silently ignored, for better or for worse... - */ -#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME) - -#define MODULE_NAME_MAX_LEN 11 -static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb"; - -DL_EXPORT(void) init_bsddb(void) -{ - PyObject* m; - PyObject* d; - PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION ); - PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING ); - PyObject* cvsid_s = PyString_FromString( rcs_id ); - - /* Initialize the type of the new type objects here; doing it here - is required for portability to Windows without requiring C++. */ - DB_Type.ob_type = &PyType_Type; - DBCursor_Type.ob_type = &PyType_Type; - DBEnv_Type.ob_type = &PyType_Type; - DBTxn_Type.ob_type = &PyType_Type; - DBLock_Type.ob_type = &PyType_Type; - - -#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE) - /* Save the current interpreter, so callbacks can do the right thing. */ - _db_interpreterState = PyThreadState_Get()->interp; -#endif - - /* Create the module and add the functions */ - m = Py_InitModule(_bsddbModuleName, bsddb_methods); - - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - PyDict_SetItemString(d, "__version__", pybsddb_version_s); - PyDict_SetItemString(d, "cvsid", cvsid_s); - PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s); - Py_DECREF(pybsddb_version_s); - pybsddb_version_s = NULL; - Py_DECREF(cvsid_s); - cvsid_s = NULL; - Py_DECREF(db_version_s); - db_version_s = NULL; - - ADD_INT(d, DB_VERSION_MAJOR); - ADD_INT(d, DB_VERSION_MINOR); - ADD_INT(d, DB_VERSION_PATCH); - - ADD_INT(d, DB_MAX_PAGES); - ADD_INT(d, DB_MAX_RECORDS); - -#if (DBVER >= 42) - ADD_INT(d, DB_RPCCLIENT); -#else - ADD_INT(d, DB_CLIENT); - /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */ - _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT); -#endif - ADD_INT(d, DB_XA_CREATE); - - ADD_INT(d, DB_CREATE); - ADD_INT(d, DB_NOMMAP); - ADD_INT(d, DB_THREAD); - - ADD_INT(d, DB_FORCE); - ADD_INT(d, DB_INIT_CDB); - ADD_INT(d, DB_INIT_LOCK); - ADD_INT(d, DB_INIT_LOG); - ADD_INT(d, DB_INIT_MPOOL); - ADD_INT(d, DB_INIT_TXN); -#if (DBVER >= 32) - ADD_INT(d, DB_JOINENV); -#endif - - ADD_INT(d, DB_RECOVER); - ADD_INT(d, DB_RECOVER_FATAL); - ADD_INT(d, DB_TXN_NOSYNC); - ADD_INT(d, DB_USE_ENVIRON); - ADD_INT(d, DB_USE_ENVIRON_ROOT); - - ADD_INT(d, DB_LOCKDOWN); - ADD_INT(d, DB_PRIVATE); - ADD_INT(d, DB_SYSTEM_MEM); - - ADD_INT(d, DB_TXN_SYNC); - ADD_INT(d, DB_TXN_NOWAIT); - - ADD_INT(d, DB_EXCL); - ADD_INT(d, DB_FCNTL_LOCKING); - ADD_INT(d, DB_ODDFILESIZE); - ADD_INT(d, DB_RDWRMASTER); - ADD_INT(d, DB_RDONLY); - ADD_INT(d, DB_TRUNCATE); -#if (DBVER >= 32) - ADD_INT(d, DB_EXTENT); - ADD_INT(d, DB_CDB_ALLDB); - ADD_INT(d, DB_VERIFY); -#endif - ADD_INT(d, DB_UPGRADE); - - ADD_INT(d, DB_AGGRESSIVE); - ADD_INT(d, DB_NOORDERCHK); - ADD_INT(d, DB_ORDERCHKONLY); - ADD_INT(d, DB_PR_PAGE); -#if ! (DBVER >= 33) - ADD_INT(d, DB_VRFY_FLAGMASK); - ADD_INT(d, DB_PR_HEADERS); -#endif - ADD_INT(d, DB_PR_RECOVERYTEST); - ADD_INT(d, DB_SALVAGE); - - ADD_INT(d, DB_LOCK_NORUN); - ADD_INT(d, DB_LOCK_DEFAULT); - ADD_INT(d, DB_LOCK_OLDEST); - ADD_INT(d, DB_LOCK_RANDOM); - ADD_INT(d, DB_LOCK_YOUNGEST); -#if (DBVER >= 33) - ADD_INT(d, DB_LOCK_MAXLOCKS); - ADD_INT(d, DB_LOCK_MINLOCKS); - ADD_INT(d, DB_LOCK_MINWRITE); -#endif - - -#if (DBVER >= 33) - /* docs say to use zero instead */ - _addIntToDict(d, "DB_LOCK_CONFLICT", 0); -#else - ADD_INT(d, DB_LOCK_CONFLICT); -#endif - - ADD_INT(d, DB_LOCK_DUMP); - ADD_INT(d, DB_LOCK_GET); - ADD_INT(d, DB_LOCK_INHERIT); - ADD_INT(d, DB_LOCK_PUT); - ADD_INT(d, DB_LOCK_PUT_ALL); - ADD_INT(d, DB_LOCK_PUT_OBJ); - - ADD_INT(d, DB_LOCK_NG); - ADD_INT(d, DB_LOCK_READ); - ADD_INT(d, DB_LOCK_WRITE); - ADD_INT(d, DB_LOCK_NOWAIT); -#if (DBVER >= 32) - ADD_INT(d, DB_LOCK_WAIT); -#endif - ADD_INT(d, DB_LOCK_IWRITE); - ADD_INT(d, DB_LOCK_IREAD); - ADD_INT(d, DB_LOCK_IWR); -#if (DBVER >= 33) - ADD_INT(d, DB_LOCK_DIRTY); - ADD_INT(d, DB_LOCK_WWRITE); -#endif - - ADD_INT(d, DB_LOCK_RECORD); - ADD_INT(d, DB_LOCK_UPGRADE); -#if (DBVER >= 32) - ADD_INT(d, DB_LOCK_SWITCH); -#endif -#if (DBVER >= 33) - ADD_INT(d, DB_LOCK_UPGRADE_WRITE); -#endif - - ADD_INT(d, DB_LOCK_NOWAIT); - ADD_INT(d, DB_LOCK_RECORD); - ADD_INT(d, DB_LOCK_UPGRADE); - -#if (DBVER >= 33) - ADD_INT(d, DB_LSTAT_ABORTED); -#if (DBVER < 43) - ADD_INT(d, DB_LSTAT_ERR); -#endif - ADD_INT(d, DB_LSTAT_FREE); - ADD_INT(d, DB_LSTAT_HELD); -#if (DBVER == 33) - ADD_INT(d, DB_LSTAT_NOGRANT); -#endif - ADD_INT(d, DB_LSTAT_PENDING); - ADD_INT(d, DB_LSTAT_WAITING); -#endif - - ADD_INT(d, DB_ARCH_ABS); - ADD_INT(d, DB_ARCH_DATA); - ADD_INT(d, DB_ARCH_LOG); - - ADD_INT(d, DB_BTREE); - ADD_INT(d, DB_HASH); - ADD_INT(d, DB_RECNO); - ADD_INT(d, DB_QUEUE); - ADD_INT(d, DB_UNKNOWN); - - ADD_INT(d, DB_DUP); - ADD_INT(d, DB_DUPSORT); - ADD_INT(d, DB_RECNUM); - ADD_INT(d, DB_RENUMBER); - ADD_INT(d, DB_REVSPLITOFF); - ADD_INT(d, DB_SNAPSHOT); - - ADD_INT(d, DB_JOIN_NOSORT); - - ADD_INT(d, DB_AFTER); - ADD_INT(d, DB_APPEND); - ADD_INT(d, DB_BEFORE); - ADD_INT(d, DB_CACHED_COUNTS); -#if (DBVER >= 41) - _addIntToDict(d, "DB_CHECKPOINT", 0); -#else - ADD_INT(d, DB_CHECKPOINT); - ADD_INT(d, DB_CURLSN); -#endif -#if ((DBVER >= 33) && (DBVER <= 41)) - ADD_INT(d, DB_COMMIT); -#endif - ADD_INT(d, DB_CONSUME); -#if (DBVER >= 32) - ADD_INT(d, DB_CONSUME_WAIT); -#endif - ADD_INT(d, DB_CURRENT); -#if (DBVER >= 33) - ADD_INT(d, DB_FAST_STAT); -#endif - ADD_INT(d, DB_FIRST); - ADD_INT(d, DB_FLUSH); - ADD_INT(d, DB_GET_BOTH); - ADD_INT(d, DB_GET_RECNO); - ADD_INT(d, DB_JOIN_ITEM); - ADD_INT(d, DB_KEYFIRST); - ADD_INT(d, DB_KEYLAST); - ADD_INT(d, DB_LAST); - ADD_INT(d, DB_NEXT); - ADD_INT(d, DB_NEXT_DUP); - ADD_INT(d, DB_NEXT_NODUP); - ADD_INT(d, DB_NODUPDATA); - ADD_INT(d, DB_NOOVERWRITE); - ADD_INT(d, DB_NOSYNC); - ADD_INT(d, DB_POSITION); - ADD_INT(d, DB_PREV); - ADD_INT(d, DB_PREV_NODUP); - ADD_INT(d, DB_RECORDCOUNT); - ADD_INT(d, DB_SET); - ADD_INT(d, DB_SET_RANGE); - ADD_INT(d, DB_SET_RECNO); - ADD_INT(d, DB_WRITECURSOR); - - ADD_INT(d, DB_OPFLAGS_MASK); - ADD_INT(d, DB_RMW); -#if (DBVER >= 33) - ADD_INT(d, DB_DIRTY_READ); - ADD_INT(d, DB_MULTIPLE); - ADD_INT(d, DB_MULTIPLE_KEY); -#endif - -#if (DBVER >= 33) - ADD_INT(d, DB_DONOTINDEX); -#endif - -#if (DBVER >= 41) - _addIntToDict(d, "DB_INCOMPLETE", 0); -#else - ADD_INT(d, DB_INCOMPLETE); -#endif - ADD_INT(d, DB_KEYEMPTY); - ADD_INT(d, DB_KEYEXIST); - ADD_INT(d, DB_LOCK_DEADLOCK); - ADD_INT(d, DB_LOCK_NOTGRANTED); - ADD_INT(d, DB_NOSERVER); - ADD_INT(d, DB_NOSERVER_HOME); - ADD_INT(d, DB_NOSERVER_ID); - ADD_INT(d, DB_NOTFOUND); - ADD_INT(d, DB_OLD_VERSION); - ADD_INT(d, DB_RUNRECOVERY); - ADD_INT(d, DB_VERIFY_BAD); -#if (DBVER >= 33) - ADD_INT(d, DB_PAGE_NOTFOUND); - ADD_INT(d, DB_SECONDARY_BAD); -#endif -#if (DBVER >= 40) - ADD_INT(d, DB_STAT_CLEAR); - ADD_INT(d, DB_REGION_INIT); - ADD_INT(d, DB_NOLOCKING); - ADD_INT(d, DB_YIELDCPU); - ADD_INT(d, DB_PANIC_ENVIRONMENT); - ADD_INT(d, DB_NOPANIC); -#endif - -#if (DBVER >= 42) - ADD_INT(d, DB_TIME_NOTGRANTED); - ADD_INT(d, DB_TXN_NOT_DURABLE); - ADD_INT(d, DB_TXN_WRITE_NOSYNC); - ADD_INT(d, DB_LOG_AUTOREMOVE); - ADD_INT(d, DB_DIRECT_LOG); - ADD_INT(d, DB_DIRECT_DB); - ADD_INT(d, DB_INIT_REP); - ADD_INT(d, DB_ENCRYPT); - ADD_INT(d, DB_CHKSUM); -#endif - -#if (DBVER >= 41) - ADD_INT(d, DB_ENCRYPT_AES); - ADD_INT(d, DB_AUTO_COMMIT); -#else - /* allow berkeleydb 4.1 aware apps to run on older versions */ - _addIntToDict(d, "DB_AUTO_COMMIT", 0); -#endif - - ADD_INT(d, EINVAL); - ADD_INT(d, EACCES); - ADD_INT(d, ENOSPC); - ADD_INT(d, ENOMEM); - ADD_INT(d, EAGAIN); - ADD_INT(d, EBUSY); - ADD_INT(d, EEXIST); - ADD_INT(d, ENOENT); - ADD_INT(d, EPERM); - -#if (DBVER >= 40) - ADD_INT(d, DB_SET_LOCK_TIMEOUT); - ADD_INT(d, DB_SET_TXN_TIMEOUT); -#endif - - /* The base exception class is DBError */ - DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL); - PyDict_SetItemString(d, "DBError", DBError); - - /* Some magic to make DBNotFoundError derive from both DBError and - KeyError, since the API only supports using one base class. */ - PyDict_SetItemString(d, "KeyError", PyExc_KeyError); - PyRun_String("class DBNotFoundError(DBError, KeyError): pass", - Py_file_input, d, d); - DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError"); - PyDict_DelItemString(d, "KeyError"); - - - /* All the rest of the exceptions derive only from DBError */ -#define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \ - PyDict_SetItemString(d, #name, name) - -#if !INCOMPLETE_IS_WARNING - MAKE_EX(DBIncompleteError); -#endif - MAKE_EX(DBCursorClosedError); - MAKE_EX(DBKeyEmptyError); - MAKE_EX(DBKeyExistError); - MAKE_EX(DBLockDeadlockError); - MAKE_EX(DBLockNotGrantedError); - MAKE_EX(DBOldVersionError); - MAKE_EX(DBRunRecoveryError); - MAKE_EX(DBVerifyBadError); - MAKE_EX(DBNoServerError); - MAKE_EX(DBNoServerHomeError); - MAKE_EX(DBNoServerIDError); -#if (DBVER >= 33) - MAKE_EX(DBPageNotFoundError); - MAKE_EX(DBSecondaryBadError); -#endif - - MAKE_EX(DBInvalidArgError); - MAKE_EX(DBAccessError); - MAKE_EX(DBNoSpaceError); - MAKE_EX(DBNoMemoryError); - MAKE_EX(DBAgainError); - MAKE_EX(DBBusyError); - MAKE_EX(DBFileExistsError); - MAKE_EX(DBNoSuchFileError); - MAKE_EX(DBPermissionsError); - -#undef MAKE_EX - - /* Check for errors */ - if (PyErr_Occurred()) { - PyErr_Print(); - Py_FatalError("can't initialize module _bsddb"); - } -} - -/* allow this module to be named _pybsddb so that it can be installed - * and imported on top of python >= 2.3 that includes its own older - * copy of the library named _bsddb without importing the old version. */ -DL_EXPORT(void) init_pybsddb(void) -{ - strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN); - init_bsddb(); -} - -/* allow this module to be named _rpmdb too. */ -DL_EXPORT(void) init_rpmdb(void) -{ - strncpy(_bsddbModuleName, "_rpmdb", MODULE_NAME_MAX_LEN); - init_bsddb(); -} |