summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_bsddb.c3378
-rw-r--r--Modules/bsddb.h57
2 files changed, 2454 insertions, 981 deletions
diff --git a/Modules/_bsddb.c b/Modules/_bsddb.c
index 7c0eae3..9e89273 100644
--- a/Modules/_bsddb.c
+++ b/Modules/_bsddb.c
@@ -36,7 +36,7 @@
/*
* 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.
+ * to compile with Berkeley DB 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 who based his work on a
@@ -48,7 +48,10 @@
* 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@krypto.org> is once again the maintainer.
+ * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
+ *
+ * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
+ * Jesus Cea licenses this code to PSF under a Contributor Agreement.
*
* 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
@@ -92,7 +95,7 @@
#include "bsddb.h"
#undef COMPILING_BSDDB_C
-static char *svn_id = "$Id$";
+static char *rcs_id = "$Id$";
/* --------------------------------------------------------------------- */
/* Various macro definitions */
@@ -101,6 +104,27 @@ static char *svn_id = "$Id$";
typedef int Py_ssize_t;
#endif
+#if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
+/* This code now uses PyBytes* API function names instead of PyString*.
+ * These #defines map to their equivalent on earlier python versions. */
+#define PyBytes_FromStringAndSize PyString_FromStringAndSize
+#define PyBytes_FromString PyString_FromString
+#define PyBytes_AsStringAndSize PyString_AsStringAndSize
+#define PyBytes_Check PyString_Check
+#define PyBytes_GET_SIZE PyString_GET_SIZE
+#define PyBytes_AS_STRING PyString_AS_STRING
+#endif
+
+#if (PY_VERSION_HEX >= 0x03000000)
+#define NUMBER_Check PyLong_Check
+#define NUMBER_AsLong PyLong_AsLong
+#define NUMBER_FromLong PyLong_FromLong
+#else
+#define NUMBER_Check PyInt_Check
+#define NUMBER_AsLong PyInt_AsLong
+#define NUMBER_FromLong PyInt_FromLong
+#endif
+
#ifdef WITH_THREAD
/* These are for when calling Python --> C */
@@ -164,10 +188,8 @@ 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 */
@@ -183,6 +205,12 @@ static PyObject* DBFileExistsError; /* EEXIST */
static PyObject* DBNoSuchFileError; /* ENOENT */
static PyObject* DBPermissionsError; /* EPERM */
+#if (DBVER >= 42)
+static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
+#endif
+
+static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
+
#if (DBVER < 43)
#define DB_BUFFER_SMALL ENOMEM
#endif
@@ -201,7 +229,24 @@ static PyObject* DBPermissionsError; /* EPERM */
#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
-static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
+/* See comment in Python 2.6 "object.h" */
+#ifndef staticforward
+#define staticforward static
+#endif
+#ifndef statichere
+#define statichere static
+#endif
+
+staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
+ DBLock_Type;
+#if (DBVER >= 43)
+staticforward PyTypeObject DBSequence_Type;
+#endif
+
+#ifndef Py_TYPE
+/* for compatibility with Python 2.5 and earlier */
+#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
+#endif
#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
@@ -212,10 +257,77 @@ static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
#endif
+#if (DBVER < 46)
+ #define _DBC_close(dbc) dbc->c_close(dbc)
+ #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
+ #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
+ #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
+ #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
+ #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
+ #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
+#else
+ #define _DBC_close(dbc) dbc->close(dbc)
+ #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
+ #define _DBC_del(dbc,a) dbc->del(dbc,a)
+ #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
+ #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
+ #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
+ #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
+#endif
+
/* --------------------------------------------------------------------- */
/* Utility macros and functions */
+#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
+ { \
+ object->sibling_next=backlink; \
+ object->sibling_prev_p=&(backlink); \
+ backlink=object; \
+ if (object->sibling_next) { \
+ object->sibling_next->sibling_prev_p=&(object->sibling_next); \
+ } \
+ }
+
+#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
+ { \
+ if (object->sibling_next) { \
+ object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
+ } \
+ *(object->sibling_prev_p)=object->sibling_next; \
+ }
+
+#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
+ { \
+ if (object->sibling_next) { \
+ object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
+ } \
+ if (object->sibling_prev_p) { \
+ *(object->sibling_prev_p)=object->sibling_next; \
+ } \
+ }
+
+#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
+ { \
+ object->sibling_next_txn=backlink; \
+ object->sibling_prev_p_txn=&(backlink); \
+ backlink=object; \
+ if (object->sibling_next_txn) { \
+ object->sibling_next_txn->sibling_prev_p_txn= \
+ &(object->sibling_next_txn); \
+ } \
+ }
+
+#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
+ { \
+ if (object->sibling_next_txn) { \
+ object->sibling_next_txn->sibling_prev_p_txn= \
+ object->sibling_prev_p_txn; \
+ } \
+ *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
+ }
+
+
#define RETURN_IF_ERR() \
if (makeDBError(err)) { \
return NULL; \
@@ -227,8 +339,10 @@ static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
if ((nonNull) == NULL) { \
PyObject *errTuple = NULL; \
errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
- PyErr_SetObject((pyErrObj), errTuple); \
- Py_DECREF(errTuple); \
+ if (errTuple) { \
+ PyErr_SetObject((pyErrObj), errTuple); \
+ Py_DECREF(errTuple); \
+ } \
return NULL; \
}
@@ -251,6 +365,9 @@ static PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
#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); dbt.data = NULL; }
+
static int makeDBError(int err);
@@ -258,104 +375,34 @@ 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
-}
-
-
-/* Handy function to free a DBT and any self-allocated data within.
- To be used on self created DBTs. The make_dbt and make_key_dbt
- functions have their own free routines that do more that this. */
-static void free_dbt(DBT *dbt)
-{
- if ((dbt->flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && dbt->data != NULL) {
- free(dbt->data);
- dbt->data = NULL;
- }
-}
-
-
-/* Cleanup a Python buffer API view created by make_dbt() */
-static void free_buf_view(PyObject *obj, Py_buffer *view)
-{
- if (view) {
- PyBuffer_Release(view);
- PyMem_Free(view);
- }
-}
-
-
-/* Cleanup a DBT and an associated Python buffer API view
- created by make_key_dbt() */
-#define FREE_DBT_VIEW(dbt, obj, view) \
- do { \
- free_dbt(&(dbt)); \
- free_buf_view((obj), (view)); \
- } while(0);
-
-
-static Py_buffer * _malloc_view(PyObject *obj)
-{
- Py_buffer *view;
-
- if (!(view = PyMem_Malloc(sizeof(Py_buffer)))) {
- PyErr_SetString(PyExc_MemoryError,
- "Py_buffer malloc failed");
- return NULL;
- }
-
- if (PyObject_GetBuffer(obj, view, PyBUF_SIMPLE))
- return NULL;
-
- if (view->ndim > 1) {
- PyErr_SetString(PyExc_BufferError,
- "buffers must be single dimension");
- PyBuffer_Release(view);
- PyMem_Free(view);
- return NULL;
- }
- return view;
}
/* Create a DBT structure (containing key and data values) from Python
- strings. Returns >= 1 on success, 0 on an error. The returned_view_p
- may be filled with a newly allocated Py_buffer view on success.
- The caller MUST call free_buf_view() on any returned Py_buffer. */
-static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
+ strings. Returns 1 on success, 0 on an error. */
+static int make_dbt(PyObject* obj, DBT* dbt)
{
- Py_buffer *view;
-
- /* simple way to ensure the caller can detect if we've returned a
- new buffer view or not: require their pointer to start out NULL. */
- assert(*returned_view_p == NULL);
-
CLEAR_DBT(*dbt);
if (obj == Py_None) {
/* no need to do anything, the structure has already been zeroed */
- return 1;
}
- if (!PyObject_CheckBuffer(obj)) {
+ else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
PyErr_SetString(PyExc_TypeError,
- "Data values must support the buffer API or be None.");
+#if (PY_VERSION_HEX < 0x03000000)
+ "Data values must be of type string or None.");
+#else
+ "Data values must be of type bytes or None.");
+#endif
return 0;
}
-
- if ( !(view = _malloc_view(obj)) )
- return 0;
-
- dbt->data = view->buf;
- dbt->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
- *returned_view_p = view;
return 1;
}
@@ -363,19 +410,12 @@ static int make_dbt(PyObject* obj, DBT* dbt, Py_buffer** returned_view_p)
/* 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 MUST call FREE_DBT_VIEW(keydbt, keyobj, key_view) with all
- returned DBT and Py_buffer values when done. */
+ Caller MUST call FREE_DBT(key) when done. */
static int
-make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
- Py_buffer** returned_view_p)
+make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
{
db_recno_t recno;
int type;
- Py_buffer *view;
-
- /* simple way to ensure the caller can detect if we've returned a
- new buffer view or not: require their pointer to start out NULL. */
- assert(*returned_view_p == NULL);
CLEAR_DBT(*key);
if (keyobj == Py_None) {
@@ -391,73 +431,76 @@ make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags,
/* no need to do anything, the structure has already been zeroed */
}
- else if (PyLong_Check(keyobj)) {
+ else if (PyBytes_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) {
+ if (type == DB_RECNO || type == DB_QUEUE) {
PyErr_SetString(
PyExc_TypeError,
- "Integer keys only allowed for Recno and Queue DB's");
+#if (PY_VERSION_HEX < 0x03000000)
+ "String keys not allowed for Recno and Queue DB's");
+#else
+ "Bytes keys not allowed for Recno and Queue DB's");
+#endif
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 = PyLong_AS_LONG(keyobj);
- key->data = malloc(sizeof(db_recno_t));
+ /*
+ * NOTE(gps): I don't like doing a data copy here, it seems
+ * wasteful. But without a clean way to tell FREE_DBT if it
+ * should free key->data or not we have to. Other places in
+ * the code check for DB_THREAD and forceably set DBT_MALLOC
+ * when we otherwise would leave flags 0 to indicate that.
+ */
+ key->data = malloc(PyBytes_GET_SIZE(keyobj));
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));
+ memcpy(key->data, PyBytes_AS_STRING(keyobj),
+ PyBytes_GET_SIZE(keyobj));
key->flags = DB_DBT_REALLOC;
+ key->size = PyBytes_GET_SIZE(keyobj);
}
- else if (PyObject_CheckBuffer(keyobj)) {
+ else if (NUMBER_Check(keyobj)) {
/* verify access method type */
type = _DB_get_type(self);
if (type == -1)
return 0;
- if (type == DB_RECNO || type == DB_QUEUE) {
+ 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,
- "Non-integer keys not allowed for Recno and Queue DB's");
+ "Integer keys only allowed for Recno and Queue DB's");
return 0;
}
- if ( !(view = _malloc_view(keyobj)) )
- return 0;
-
- /*
- * NOTE(gps): I don't like doing a data copy here, it seems
- * wasteful. But without a clean way to tell FREE_DBT if it
- * should free key->data or not we have to. Other places in
- * the code check for DB_THREAD and forceably set DBT_MALLOC
- * when we otherwise would leave flags 0 to indicate that.
- */
- key->size = Py_SAFE_DOWNCAST(view->len, Py_ssize_t, u_int32_t);
- key->data = malloc(key->size);
+ /* 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 = NUMBER_AsLong(keyobj);
+ key->data = malloc(sizeof(db_recno_t));
if (key->data == NULL) {
PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
- key->size = 0;
return 0;
}
- memcpy(key->data, view->buf, key->size);
+ key->ulen = key->size = sizeof(db_recno_t);
+ memcpy(key->data, &recno, sizeof(db_recno_t));
key->flags = DB_DBT_REALLOC;
- *returned_view_p = view;
}
-
else {
PyErr_Format(PyExc_TypeError,
- "buffer or int object expected for key, %s found",
+#if (PY_VERSION_HEX < 0x03000000)
+ "String or Integer object expected for key, %s found",
+#else
+ "Bytes or Integer object expected for key, %s found",
+#endif
Py_TYPE(keyobj)->tp_name);
return 0;
}
@@ -518,6 +561,102 @@ static void _db_errorCallback(const DB_ENV *db_env,
}
+/*
+** We need these functions because some results
+** are undefined if pointer is NULL. Some other
+** give None instead of "".
+**
+** This functions are static and will be
+** -I hope- inlined.
+*/
+static const char *DummyString = "This string is a simple placeholder";
+static PyObject *Build_PyString(const char *p,int s)
+{
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+ return PyBytes_FromStringAndSize(p,s);
+}
+
+static PyObject *BuildValue_S(const void *p,int s)
+{
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+ return PyBytes_FromStringAndSize(p, s);
+}
+
+static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
+{
+PyObject *a, *b, *r;
+
+ if (!p1) {
+ p1=DummyString;
+ assert(s1==0);
+ }
+ if (!p2) {
+ p2=DummyString;
+ assert(s2==0);
+ }
+
+ if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
+ return NULL;
+ }
+ if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
+ Py_DECREF(a);
+ return NULL;
+ }
+
+#if (PY_VERSION_HEX >= 0x02040000)
+ r = PyTuple_Pack(2, a, b) ;
+#else
+ r = Py_BuildValue("OO", a, b);
+#endif
+ Py_DECREF(a);
+ Py_DECREF(b);
+ return r;
+}
+
+static PyObject *BuildValue_IS(int i,const void *p,int s)
+{
+ PyObject *a, *r;
+
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+
+ if (!(a = PyBytes_FromStringAndSize(p, s))) {
+ return NULL;
+ }
+
+ r = Py_BuildValue("iO", i, a);
+ Py_DECREF(a);
+ return r;
+}
+
+static PyObject *BuildValue_LS(long l,const void *p,int s)
+{
+ PyObject *a, *r;
+
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+
+ if (!(a = PyBytes_FromStringAndSize(p, s))) {
+ return NULL;
+ }
+
+ r = Py_BuildValue("lO", l, a);
+ Py_DECREF(a);
+ return r;
+}
+
+
+
/* make a nice exception object to raise for errors. */
static int makeDBError(int err)
{
@@ -542,7 +681,7 @@ static int makeDBError(int err)
strncat(errTxt, _db_errmsg, bytes_left);
}
_db_errmsg[0] = 0;
- exceptionRaised = PyErr_WarnEx(PyExc_RuntimeWarning, errTxt, 1);
+ exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
#else /* do an exception instead */
errObj = DBIncompleteError;
@@ -561,10 +700,8 @@ static int makeDBError(int err)
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 DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
#if (DBVER >= 43)
@@ -580,6 +717,12 @@ static int makeDBError(int err)
case ENOENT: errObj = DBNoSuchFileError; break;
case EPERM : errObj = DBPermissionsError; break;
+#if (DBVER >= 42)
+ case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
+#endif
+
+ case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
+
default: errObj = DBError; break;
}
@@ -594,9 +737,13 @@ static int makeDBError(int err)
}
_db_errmsg[0] = 0;
- errTuple = Py_BuildValue("(is)", err, errTxt);
+ errTuple = Py_BuildValue("(is)", err, errTxt);
+ if (errTuple == NULL) {
+ Py_DECREF(errObj);
+ return !0;
+ }
PyErr_SetObject(errObj, errTuple);
- Py_DECREF(errTuple);
+ Py_DECREF(errTuple);
}
return ((errObj != NULL) || exceptionRaised);
@@ -683,16 +830,11 @@ static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
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);
+ err = _DBC_get(self->dbc, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
@@ -713,21 +855,15 @@ static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
case DB_RECNO:
case DB_QUEUE:
- retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
- data.data, data.size);
+ retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
case DB_HASH:
case DB_BTREE:
default:
- retval = Py_BuildValue("y#y#", key.data, key.size,
- data.data, data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
break;
}
}
- if (!err) {
- free_dbt(&key);
- free_dbt(&data);
- }
return retval;
}
@@ -735,7 +871,7 @@ static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
/* add an integer to a dictionary using the given name as a key */
static void _addIntToDict(PyObject* dict, char *name, int value)
{
- PyObject* v = PyLong_FromLong((long) value);
+ PyObject* v = NUMBER_FromLong((long) value);
if (!v || PyDict_SetItemString(dict, name, v))
PyErr_Clear();
@@ -747,12 +883,12 @@ static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
{
PyObject* v;
/* if the value fits in regular int, use that. */
-#ifdef HAVE_LONG_LONG
+#ifdef PY_LONG_LONG
if (sizeof(time_t) > sizeof(long))
v = PyLong_FromLongLong((PY_LONG_LONG) value);
else
#endif
- v = PyLong_FromLong((long) value);
+ v = NUMBER_FromLong((long) value);
if (!v || PyDict_SetItemString(dict, name, v))
PyErr_Clear();
@@ -771,7 +907,14 @@ static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
}
#endif
+static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
+{
+ PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
+ if (!v || PyDict_SetItemString(dict, name, v))
+ PyErr_Clear();
+ Py_XDECREF(v);
+}
/* --------------------------------------------------------------------- */
/* Allocators and deallocators */
@@ -791,11 +934,16 @@ newDBObject(DBEnvObject* arg, int flags)
self->flags = 0;
self->setflags = 0;
self->myenvobj = NULL;
-#if (DBVER >= 33)
+ self->db = NULL;
+ self->children_cursors = NULL;
+#if (DBVER >=43)
+ self->children_sequences = NULL;
+#endif
self->associateCallback = NULL;
self->btCompareCallback = NULL;
self->primaryDBType = 0;
-#endif
+ Py_INCREF(Py_None);
+ self->private_obj = Py_None;
self->in_weakreflist = NULL;
/* keep a reference to our python DBEnv object */
@@ -803,7 +951,14 @@ newDBObject(DBEnvObject* arg, int flags)
Py_INCREF(arg);
self->myenvobj = arg;
db_env = arg->db_env;
+ INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
+ } else {
+ self->sibling_prev_p=NULL;
+ self->sibling_next=NULL;
}
+ self->txn=NULL;
+ self->sibling_prev_p_txn=NULL;
+ self->sibling_next_txn=NULL;
if (self->myenvobj)
self->moduleFlags = self->myenvobj->moduleFlags;
@@ -815,9 +970,7 @@ newDBObject(DBEnvObject* arg, int flags)
err = db_create(&self->db, db_env, flags);
if (self->db != NULL) {
self->db->set_errcall(self->db, _db_errorCallback);
-#if (DBVER >= 33)
self->db->app_private = (void*)self;
-#endif
}
MYDB_END_ALLOW_THREADS;
/* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
@@ -828,32 +981,24 @@ newDBObject(DBEnvObject* arg, int flags)
Py_DECREF(self->myenvobj);
self->myenvobj = NULL;
}
- PyObject_Del(self);
+ Py_DECREF(self);
self = NULL;
}
return self;
}
+/* Forward declaration */
+static PyObject *DB_close_internal(DBObject* self, int flags);
+
static void
DB_dealloc(DBObject* self)
{
+ PyObject *dummy;
+
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;
- } else {
- PyErr_WarnEx(PyExc_RuntimeWarning,
- "DB could not be closed in destructor:"
- " DBEnv already closed",
- 1);
- }
- self->db = NULL;
+ dummy=DB_close_internal(self,0);
+ Py_XDECREF(dummy);
}
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
@@ -862,7 +1007,6 @@ DB_dealloc(DBObject* self)
Py_DECREF(self->myenvobj);
self->myenvobj = NULL;
}
-#if (DBVER >= 33)
if (self->associateCallback != NULL) {
Py_DECREF(self->associateCallback);
self->associateCallback = NULL;
@@ -871,13 +1015,12 @@ DB_dealloc(DBObject* self)
Py_DECREF(self->btCompareCallback);
self->btCompareCallback = NULL;
}
-#endif
+ Py_DECREF(self->private_obj);
PyObject_Del(self);
}
-
static DBCursorObject*
-newDBCursorObject(DBC* dbc, DBObject* db)
+newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
{
DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
if (self == NULL)
@@ -885,40 +1028,37 @@ newDBCursorObject(DBC* dbc, DBObject* db)
self->dbc = dbc;
self->mydb = db;
+
+ INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
+ if (txn && ((PyObject *)txn!=Py_None)) {
+ INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
+ self->txn=txn;
+ } else {
+ self->txn=NULL;
+ }
+
self->in_weakreflist = NULL;
Py_INCREF(self->mydb);
return self;
}
+/* Forward declaration */
+static PyObject *DBC_close_internal(DBCursorObject* self);
+
static void
DBCursor_dealloc(DBCursorObject* self)
{
- int err;
+ PyObject *dummy;
+ if (self->dbc != NULL) {
+ dummy=DBC_close_internal(self);
+ Py_XDECREF(dummy);
+ }
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
}
-
- if (self->dbc != NULL) {
- /* 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)
- /* test for: open db + no environment or non-closed environment */
- if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
- !self->mydb->myenvobj->closed))) {
- MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_close(self->dbc);
- MYDB_END_ALLOW_THREADS;
- }
- self->dbc = NULL;
- }
- Py_XDECREF( self->mydb );
+ Py_DECREF(self->mydb);
PyObject_Del(self);
}
@@ -935,88 +1075,134 @@ newDBEnvObject(int flags)
self->flags = flags;
self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
+ self->children_dbs = NULL;
+ self->children_txns = NULL;
+ Py_INCREF(Py_None);
+ self->private_obj = Py_None;
+ Py_INCREF(Py_None);
+ self->rep_transport = Py_None;
self->in_weakreflist = NULL;
+ self->event_notifyCallback = NULL;
MYDB_BEGIN_ALLOW_THREADS;
err = db_env_create(&self->db_env, flags);
MYDB_END_ALLOW_THREADS;
if (makeDBError(err)) {
- PyObject_Del(self);
+ Py_DECREF(self);
self = NULL;
}
else {
self->db_env->set_errcall(self->db_env, _db_errorCallback);
+ self->db_env->app_private = self;
}
return self;
}
+/* Forward declaration */
+static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
static void
DBEnv_dealloc(DBEnvObject* self)
{
- if (self->in_weakreflist != NULL) {
- PyObject_ClearWeakRefs((PyObject *) self);
- }
+ PyObject *dummy;
if (self->db_env && !self->closed) {
- MYDB_BEGIN_ALLOW_THREADS;
- self->db_env->close(self->db_env, 0);
- MYDB_END_ALLOW_THREADS;
+ dummy=DBEnv_close_internal(self,0);
+ Py_XDECREF(dummy);
+ }
+
+ Py_XDECREF(self->event_notifyCallback);
+ self->event_notifyCallback = NULL;
+
+ if (self->in_weakreflist != NULL) {
+ PyObject_ClearWeakRefs((PyObject *) self);
}
+ Py_DECREF(self->private_obj);
+ Py_DECREF(self->rep_transport);
PyObject_Del(self);
}
static DBTxnObject*
-newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
+newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
{
int err;
+ DB_TXN *parent_txn = NULL;
+
DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
if (self == NULL)
return NULL;
- Py_INCREF(myenv);
- self->env = (PyObject*)myenv;
+
self->in_weakreflist = NULL;
+ self->children_txns = NULL;
+ self->children_dbs = NULL;
+ self->children_cursors = NULL;
+ self->children_sequences = NULL;
+ self->flag_prepare = 0;
+ self->parent_txn = NULL;
+ self->env = 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)) {
- Py_DECREF(self->env);
- PyObject_Del(self);
- self = NULL;
+ if (parent && ((PyObject *)parent!=Py_None)) {
+ parent_txn = parent->txn;
}
+
+ if (txn) {
+ self->txn = txn;
+ } else {
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
+ MYDB_END_ALLOW_THREADS;
+
+ if (makeDBError(err)) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ }
+
+ /* Can't use 'parent' because could be 'parent==Py_None' */
+ if (parent_txn) {
+ self->parent_txn = parent;
+ Py_INCREF(parent);
+ self->env = NULL;
+ INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
+ } else {
+ self->parent_txn = NULL;
+ Py_INCREF(myenv);
+ self->env = myenv;
+ INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
+ }
+
return self;
}
+/* Forward declaration */
+static PyObject *
+DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
static void
DBTxn_dealloc(DBTxnObject* self)
{
+ PyObject *dummy;
+
+ if (self->txn) {
+ int flag_prepare = self->flag_prepare;
+ dummy=DBTxn_abort_discard_internal(self,0);
+ Py_XDECREF(dummy);
+ if (!flag_prepare) {
+ PyErr_Warn(PyExc_RuntimeWarning,
+ "DBTxn aborted in destructor. No prior commit() or abort().");
+ }
+ }
+
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
}
- if (self->txn) {
- /* it hasn't been finalized, abort it! */
- MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
- self->txn->abort(self->txn);
-#else
- txn_abort(self->txn);
-#endif
- MYDB_END_ALLOW_THREADS;
- PyErr_WarnEx(PyExc_RuntimeWarning,
- "DBTxn aborted in destructor. "
- " No prior commit() or abort().",
- 1);
+ if (self->env) {
+ Py_DECREF(self->env);
+ } else {
+ Py_DECREF(self->parent_txn);
}
-
- Py_DECREF(self->env);
PyObject_Del(self);
}
@@ -1032,15 +1218,11 @@ newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
self->in_weakreflist = 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)) {
- PyObject_Del(self);
+ Py_DECREF(self);
self = NULL;
}
@@ -1070,25 +1252,37 @@ newDBSequenceObject(DBObject* mydb, int flags)
return NULL;
Py_INCREF(mydb);
self->mydb = mydb;
- self->in_weakreflist = NULL;
+ INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
+ self->txn = NULL;
+
+ self->in_weakreflist = NULL;
MYDB_BEGIN_ALLOW_THREADS;
err = db_sequence_create(&self->sequence, self->mydb->db, flags);
MYDB_END_ALLOW_THREADS;
if (makeDBError(err)) {
- Py_DECREF(self->mydb);
- PyObject_Del(self);
+ Py_DECREF(self);
self = NULL;
}
return self;
}
+/* Forward declaration */
+static PyObject
+*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
static void
DBSequence_dealloc(DBSequenceObject* self)
{
+ PyObject *dummy;
+
+ if (self->sequence != NULL) {
+ dummy=DBSequence_close_internal(self,0,0);
+ Py_XDECREF(dummy);
+ }
+
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
}
@@ -1102,16 +1296,17 @@ DBSequence_dealloc(DBSequenceObject* self)
/* DB methods */
static PyObject*
-DB_append(DBObject* self, PyObject* args)
+DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
{
PyObject* txnobj = NULL;
PyObject* dataobj;
- Py_buffer* data_buf_view = NULL;
db_recno_t recno;
DBT key, data;
DB_TXN *txn = NULL;
+ static char* kwnames[] = { "data", "txn", NULL };
- if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
+ &dataobj, &txnobj))
return NULL;
CHECK_DB_NOT_CLOSED(self);
@@ -1124,21 +1319,16 @@ DB_append(DBObject* self, PyObject* args)
key.ulen = key.size;
key.flags = DB_DBT_USERMEM;
+ if (!make_dbt(dataobj, &data)) return NULL;
if (!checkTxnObj(txnobj, &txn)) return NULL;
- if (!make_dbt(dataobj, &data, &data_buf_view)) return NULL;
- if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND)) {
- free_buf_view(dataobj, data_buf_view);
+ if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
return NULL;
- }
- free_buf_view(dataobj, data_buf_view);
- return PyLong_FromLong(recno);
+ return NUMBER_FromLong(recno);
}
-#if (DBVER >= 33)
-
static int
_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
DBT* secKey)
@@ -1155,11 +1345,9 @@ _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
MYDB_BEGIN_BLOCK_THREADS;
if (type == DB_RECNO || type == DB_QUEUE)
- args = Py_BuildValue("(ly#)", *((db_recno_t*)priKey->data),
- priData->data, priData->size);
+ args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
else
- args = Py_BuildValue("(y#y#)", priKey->data, priKey->size,
- priData->data, priData->size);
+ args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
if (args != NULL) {
result = PyEval_CallObject(callback, args);
}
@@ -1169,19 +1357,15 @@ _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
else if (result == Py_None) {
retval = DB_DONOTINDEX;
}
- else if (PyLong_Check(result)) {
- retval = PyLong_AsLong(result);
+ else if (NUMBER_Check(result)) {
+ retval = NUMBER_AsLong(result);
}
- else if (PyByteArray_Check(result) || PyBytes_Check(result)) {
+ else if (PyBytes_Check(result)) {
char* data;
Py_ssize_t size;
CLEAR_DBT(*secKey);
- size = Py_SIZE(result);
- if (PyByteArray_Check(result))
- data = PyByteArray_AS_STRING(result);
- else
- data = PyBytes_AS_STRING(result);
+ PyBytes_AsStringAndSize(result, &data, &size);
secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
secKey->data = malloc(size); /* TODO, check this */
if (secKey->data) {
@@ -1198,7 +1382,7 @@ _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
else {
PyErr_SetString(
PyExc_TypeError,
- "DB associate callback should return DB_DONOTINDEX or bytes.");
+ "DB associate callback should return DB_DONOTINDEX or string.");
PyErr_Print();
}
@@ -1300,25 +1484,51 @@ DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
}
-#endif
-
-
static PyObject*
-DB_close(DBObject* self, PyObject* args)
+DB_close_internal(DBObject* self, int flags)
{
- int err, flags=0;
- if (!PyArg_ParseTuple(args,"|i:close", &flags))
- return NULL;
+ PyObject *dummy;
+ int err;
+
if (self->db != NULL) {
- if (self->myenvobj)
- CHECK_ENV_NOT_CLOSED(self->myenvobj);
+ /* Can be NULL if db is not in an environment */
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
+
+ if (self->txn) {
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
+ self->txn=NULL;
+ }
+
+ while(self->children_cursors) {
+ dummy=DBC_close_internal(self->children_cursors);
+ Py_XDECREF(dummy);
+ }
+
+#if (DBVER >= 43)
+ while(self->children_sequences) {
+ dummy=DBSequence_close_internal(self->children_sequences,0,0);
+ Py_XDECREF(dummy);
+ }
+#endif
+
+ MYDB_BEGIN_ALLOW_THREADS;
err = self->db->close(self->db, flags);
+ MYDB_END_ALLOW_THREADS;
self->db = NULL;
RETURN_IF_ERR();
}
RETURN_NONE();
}
+static PyObject*
+DB_close(DBObject* self, PyObject* args)
+{
+ int flags=0;
+ if (!PyArg_ParseTuple(args,"|i:close", &flags))
+ return NULL;
+ return DB_close_internal(self,flags);
+}
+
static PyObject*
_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
@@ -1349,7 +1559,7 @@ _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
CLEAR_DBT(key);
CLEAR_DBT(data);
if (CHECK_DBFLAG(self, DB_THREAD)) {
- /* Tell BerkeleyDB to malloc the return value (thread safe) */
+ /* Tell Berkeley DB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
key.flags = DB_DBT_MALLOC;
}
@@ -1365,10 +1575,9 @@ _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
retval = Py_None;
}
else if (!err) {
- retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
- data.size);
- free_dbt(&key);
- free_dbt(&data);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
+ FREE_DBT(key);
+ FREE_DBT(data);
}
RETURN_IF_ERR();
@@ -1409,7 +1618,7 @@ DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
err = self->db->cursor(self->db, txn, &dbc, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
- return (PyObject*) newDBCursorObject(dbc, self);
+ return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
}
@@ -1419,7 +1628,6 @@ DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
PyObject* txnobj = NULL;
int flags = 0;
PyObject* keyobj;
- Py_buffer* key_buf_view = NULL;
DBT key;
DB_TXN *txn = NULL;
static char* kwnames[] = { "key", "txn", "flags", NULL };
@@ -1428,37 +1636,35 @@ DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
&keyobj, &txnobj, &flags))
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
if (!checkTxnObj(txnobj, &txn)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
if (-1 == _DB_delete(self, txn, &key, 0)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
RETURN_NONE();
}
static PyObject*
-DB_fd(DBObject* self, PyObject* args)
+DB_fd(DBObject* self)
{
int err, the_fd;
- if (!PyArg_ParseTuple(args,":fd"))
- return NULL;
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 PyLong_FromLong(the_fd);
+ return NUMBER_FromLong(the_fd);
}
@@ -1470,7 +1676,6 @@ DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
PyObject* keyobj;
PyObject* dfltobj = NULL;
PyObject* retval = NULL;
- Py_buffer* key_buf_view = NULL;
int dlen = -1;
int doff = -1;
DBT key, data;
@@ -1484,20 +1689,20 @@ DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, &flags))
return NULL;
if (!checkTxnObj(txnobj, &txn)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
CLEAR_DBT(data);
if (CHECK_DBFLAG(self, DB_THREAD)) {
- /* Tell BerkeleyDB to malloc the return value (thread safe) */
+ /* Tell Berkeley DB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
}
if (!add_partial_dbt(&data, dlen, doff)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
@@ -1518,19 +1723,17 @@ DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
}
else if (!err) {
if (flags & DB_SET_RECNO) /* return both key and data */
- retval = Py_BuildValue("y#y#", key.data, key.size, data.data,
- data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
else /* return just the data */
- retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
- free_dbt(&data);
+ retval = Build_PyString(data.data, data.size);
+ FREE_DBT(data);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
RETURN_IF_ERR();
return retval;
}
-#if (DBVER >= 33)
static PyObject*
DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
{
@@ -1539,7 +1742,6 @@ DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
PyObject* keyobj;
PyObject* dfltobj = NULL;
PyObject* retval = NULL;
- Py_buffer* key_buf_view = NULL;
int dlen = -1;
int doff = -1;
DBT key, pkey, data;
@@ -1553,26 +1755,26 @@ DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, &flags))
return NULL;
if (!checkTxnObj(txnobj, &txn)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
CLEAR_DBT(data);
if (CHECK_DBFLAG(self, DB_THREAD)) {
- /* Tell BerkeleyDB to malloc the return value (thread safe) */
+ /* Tell Berkeley DB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
}
if (!add_partial_dbt(&data, dlen, doff)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
CLEAR_DBT(pkey);
pkey.flags = DB_DBT_MALLOC;
-
+
MYDB_BEGIN_ALLOW_THREADS;
err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
MYDB_END_ALLOW_THREADS;
@@ -1591,22 +1793,22 @@ DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
else if (!err) {
PyObject *pkeyObj;
PyObject *dataObj;
- dataObj = PyBytes_FromStringAndSize(data.data, data.size);
+ dataObj = Build_PyString(data.data, data.size);
if (self->primaryDBType == DB_RECNO ||
self->primaryDBType == DB_QUEUE)
- pkeyObj = PyLong_FromLong(*(int *)pkey.data);
+ pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
else
- pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
+ pkeyObj = Build_PyString(pkey.data, pkey.size);
if (flags & DB_SET_RECNO) /* return key , pkey and data */
{
PyObject *keyObj;
int type = _DB_get_type(self);
if (type == DB_RECNO || type == DB_QUEUE)
- keyObj = PyLong_FromLong(*(int *)key.data);
+ keyObj = NUMBER_FromLong(*(int *)key.data);
else
- keyObj = PyBytes_FromStringAndSize(key.data, key.size);
+ keyObj = Build_PyString(key.data, key.size);
#if (PY_VERSION_HEX >= 0x02040000)
retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
#else
@@ -1624,15 +1826,14 @@ DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
}
Py_DECREF(dataObj);
Py_DECREF(pkeyObj);
- free_dbt(&pkey);
- free_dbt(&data);
+ FREE_DBT(pkey);
+ FREE_DBT(data);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
RETURN_IF_ERR();
return retval;
}
-#endif
/* Return size of entry */
@@ -1643,7 +1844,6 @@ DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
PyObject* txnobj = NULL;
PyObject* keyobj;
PyObject* retval = NULL;
- Py_buffer* key_buf_view = NULL;
DBT key, data;
DB_TXN *txn = NULL;
static char* kwnames[] = { "key", "txn", NULL };
@@ -1652,10 +1852,10 @@ DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
&keyobj, &txnobj))
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, &flags, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, &flags))
return NULL;
if (!checkTxnObj(txnobj, &txn)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
CLEAR_DBT(data);
@@ -1668,12 +1868,12 @@ DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
err = self->db->get(self->db, txn, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
if (err == DB_BUFFER_SMALL) {
- retval = PyLong_FromLong((long)data.size);
+ retval = NUMBER_FromLong((long)data.size);
err = 0;
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_dbt(&data);
+ FREE_DBT(key);
+ FREE_DBT(data);
RETURN_IF_ERR();
return retval;
}
@@ -1687,25 +1887,22 @@ DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
PyObject* keyobj;
PyObject* dataobj;
PyObject* retval = NULL;
- Py_buffer* data_buf_view = NULL;
- Py_buffer* key_buf_view = NULL;
DBT key, data;
void *orig_data;
DB_TXN *txn = NULL;
static 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, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
- if ( !checkTxnObj(txnobj, &txn) ||
- !make_dbt(dataobj, &data, &data_buf_view) )
+ if ( !make_dbt(dataobj, &data) ||
+ !checkTxnObj(txnobj, &txn) )
{
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
@@ -1713,7 +1910,7 @@ DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
orig_data = data.data;
if (CHECK_DBFLAG(self, DB_THREAD)) {
- /* Tell BerkeleyDB to malloc the return value (thread safe) */
+ /* Tell Berkeley DB to malloc the return value (thread safe) */
/* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
data.flags = DB_DBT_MALLOC;
}
@@ -1722,8 +1919,6 @@ DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
err = self->db->get(self->db, txn, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
- free_buf_view(dataobj, data_buf_view);
-
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
&& self->moduleFlags.getReturnsNone) {
err = 0;
@@ -1732,61 +1927,47 @@ DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
}
else if (!err) {
/* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
- /* XXX(gps) I think not: buffer API input vs. bytes object output. */
- /* XXX(guido) But what if the input is PyString? */
- retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
+ retval = Build_PyString(data.data, data.size);
/* Even though the flags require DB_DBT_MALLOC, data is not always
allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
if (data.data != orig_data)
- free_dbt(&data);
+ FREE_DBT(data);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
RETURN_IF_ERR();
return retval;
}
static PyObject*
-DB_get_byteswapped(DBObject* self, PyObject* args)
+DB_get_byteswapped(DBObject* self)
{
-#if (DBVER >= 33)
int err = 0;
-#endif
int retval = -1;
- if (!PyArg_ParseTuple(args,":get_byteswapped"))
- return NULL;
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 PyLong_FromLong(retval);
+ return NUMBER_FromLong(retval);
}
static PyObject*
-DB_get_type(DBObject* self, PyObject* args)
+DB_get_type(DBObject* self)
{
int type;
- if (!PyArg_ParseTuple(args,":get_type"))
- return NULL;
CHECK_DB_NOT_CLOSED(self);
type = _DB_get_type(self);
if (type == -1)
return NULL;
- return PyLong_FromLong(type);
+ return NUMBER_FromLong(type);
}
@@ -1845,7 +2026,7 @@ DB_join(DBObject* self, PyObject* args)
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);
+ return (PyObject*) newDBCursorObject(dbc, NULL, self);
}
@@ -1855,7 +2036,6 @@ DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
int err, flags=0;
PyObject* txnobj = NULL;
PyObject* keyobj;
- Py_buffer* key_buf_view = NULL;
DBT key;
DB_TXN *txn = NULL;
DB_KEY_RANGE range;
@@ -1865,18 +2045,16 @@ DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
&keyobj, &txnobj, &flags))
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!checkTxnObj(txnobj, &txn))
- return NULL;
- if (!make_dbt(keyobj, &key, &key_buf_view))
+ 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;
- free_buf_view(keyobj, key_buf_view);
-
RETURN_IF_ERR();
return Py_BuildValue("ddd", range.less, range.equal, range.greater);
}
@@ -1940,11 +2118,24 @@ DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
if (NULL == self->db) {
PyObject *t = Py_BuildValue("(is)", 0,
"Cannot call open() twice for DB object");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
return NULL;
}
+#if (DBVER >= 41)
+ if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
+ INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
+ self->txn=(DBTxnObject *)txnobj;
+ } else {
+ self->txn=NULL;
+ }
+#else
+ self->txn=NULL;
+#endif
+
MYDB_BEGIN_ALLOW_THREADS;
#if (DBVER >= 41)
err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
@@ -1953,8 +2144,10 @@ DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
#endif
MYDB_END_ALLOW_THREADS;
if (makeDBError(err)) {
- self->db->close(self->db, 0);
- self->db = NULL;
+ PyObject *dummy;
+
+ dummy=DB_close_internal(self,0);
+ Py_XDECREF(dummy);
return NULL;
}
@@ -1963,6 +2156,7 @@ DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
#endif
self->flags = flags;
+
RETURN_NONE();
}
@@ -1974,9 +2168,7 @@ DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
PyObject* txnobj = NULL;
int dlen = -1;
int doff = -1;
- PyObject *keyobj, *dataobj, *retval;
- Py_buffer *data_buf_view = NULL;
- Py_buffer *key_buf_view = NULL;
+ PyObject* keyobj, *dataobj, *retval;
DBT key, data;
DB_TXN *txn = NULL;
static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
@@ -1987,31 +2179,28 @@ DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
return NULL;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
- if ( !make_dbt(dataobj, &data, &data_buf_view) ||
+ if ( !make_dbt(dataobj, &data) ||
!add_partial_dbt(&data, dlen, doff) ||
!checkTxnObj(txnobj, &txn) )
{
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key);
return NULL;
}
if (-1 == _DB_put(self, txn, &key, &data, flags)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key);
return NULL;
}
if (flags & DB_APPEND)
- retval = PyLong_FromLong(*((db_recno_t*)key.data));
+ retval = NUMBER_FromLong(*((db_recno_t*)key.data));
else {
retval = Py_None;
Py_INCREF(retval);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key);
return retval;
}
@@ -2030,7 +2219,12 @@ DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
return NULL;
CHECK_DB_NOT_CLOSED(self);
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
err = self->db->remove(self->db, filename, database, flags);
+ MYDB_END_ALLOW_THREADS;
+
self->db = NULL;
RETURN_IF_ERR();
RETURN_NONE();
@@ -2060,6 +2254,25 @@ DB_rename(DBObject* self, PyObject* args)
static PyObject*
+DB_get_private(DBObject* self)
+{
+ /* We can give out the private field even if db is closed */
+ Py_INCREF(self->private_obj);
+ return self->private_obj;
+}
+
+static PyObject*
+DB_set_private(DBObject* self, PyObject* private_obj)
+{
+ /* We can set the private field even if db is closed */
+ Py_DECREF(self->private_obj);
+ Py_INCREF(private_obj);
+ self->private_obj = private_obj;
+ RETURN_NONE();
+}
+
+
+static PyObject*
DB_set_bt_minkey(DBObject* self, PyObject* args)
{
int err, minkey;
@@ -2075,17 +2288,16 @@ DB_set_bt_minkey(DBObject* self, PyObject* args)
RETURN_NONE();
}
-#if (DBVER >= 33)
-static int
+static int
_default_cmp(const DBT *leftKey,
const DBT *rightKey)
{
int res;
int lsize = leftKey->size, rsize = rightKey->size;
- res = memcmp(leftKey->data, rightKey->data,
+ res = memcmp(leftKey->data, rightKey->data,
lsize < rsize ? lsize : rsize);
-
+
if (res == 0) {
if (lsize < rsize) {
res = -1;
@@ -2098,7 +2310,7 @@ _default_cmp(const DBT *leftKey,
}
static int
-_db_compareCallback(DB* db,
+_db_compareCallback(DB* db,
const DBT *leftKey,
const DBT *rightKey)
{
@@ -2120,8 +2332,7 @@ _db_compareCallback(DB* db,
} else {
MYDB_BEGIN_BLOCK_THREADS;
- args = Py_BuildValue("y#y#", leftKey->data, leftKey->size,
- rightKey->data, rightKey->size);
+ args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
if (args != NULL) {
/* XXX(twouters) I highly doubt this INCREF is correct */
Py_INCREF(self);
@@ -2131,8 +2342,8 @@ _db_compareCallback(DB* db,
/* we're in a callback within the DB code, we can't raise */
PyErr_Print();
res = _default_cmp(leftKey, rightKey);
- } else if (PyLong_Check(result)) {
- res = PyLong_AsLong(result);
+ } else if (NUMBER_Check(result)) {
+ res = NUMBER_AsLong(result);
} else {
PyErr_SetString(PyExc_TypeError,
"DB_bt_compare callback MUST return an int.");
@@ -2140,7 +2351,7 @@ _db_compareCallback(DB* db,
PyErr_Print();
res = _default_cmp(leftKey, rightKey);
}
-
+
Py_XDECREF(args);
Py_XDECREF(result);
@@ -2150,15 +2361,11 @@ _db_compareCallback(DB* db,
}
static PyObject*
-DB_set_bt_compare(DBObject* self, PyObject* args)
+DB_set_bt_compare(DBObject* self, PyObject* comparator)
{
int err;
- PyObject *comparator;
PyObject *tuple, *result;
- if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
- return NULL;
-
CHECK_DB_NOT_CLOSED(self);
if (!PyCallable_Check(comparator)) {
@@ -2166,7 +2373,7 @@ DB_set_bt_compare(DBObject* self, PyObject* args)
return NULL;
}
- /*
+ /*
* Perform a test call of the comparator function with two empty
* string objects here. verify that it returns an int (0).
* err if not.
@@ -2176,11 +2383,11 @@ DB_set_bt_compare(DBObject* self, PyObject* args)
Py_DECREF(tuple);
if (result == NULL)
return NULL;
- if (!PyLong_Check(result)) {
+ if (!NUMBER_Check(result)) {
PyErr_SetString(PyExc_TypeError,
"callback MUST return an int");
return NULL;
- } else if (PyLong_AsLong(result) != 0) {
+ } else if (NUMBER_AsLong(result) != 0) {
PyErr_SetString(PyExc_TypeError,
"callback failed to return 0 on two empty strings");
return NULL;
@@ -2215,7 +2422,6 @@ DB_set_bt_compare(DBObject* self, PyObject* args)
RETURN_IF_ERR();
RETURN_NONE();
}
-#endif /* DBVER >= 33 */
static PyObject*
@@ -2447,10 +2653,8 @@ DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
MYDB_BEGIN_ALLOW_THREADS;
#if (DBVER >= 43)
err = self->db->stat(self->db, txn, &sp, flags);
-#elif (DBVER >= 33)
- err = self->db->stat(self->db, &sp, flags);
#else
- err = self->db->stat(self->db, &sp, NULL, flags);
+ err = self->db->stat(self->db, &sp, flags);
#endif
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
@@ -2474,6 +2678,9 @@ DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
MAKE_HASH_ENTRY(version);
MAKE_HASH_ENTRY(nkeys);
MAKE_HASH_ENTRY(ndata);
+#if (DBVER >= 46)
+ MAKE_HASH_ENTRY(pagecnt);
+#endif
MAKE_HASH_ENTRY(pagesize);
#if (DBVER < 41)
MAKE_HASH_ENTRY(nelem);
@@ -2496,6 +2703,9 @@ DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
MAKE_BT_ENTRY(version);
MAKE_BT_ENTRY(nkeys);
MAKE_BT_ENTRY(ndata);
+#if (DBVER >= 46)
+ MAKE_BT_ENTRY(pagecnt);
+#endif
MAKE_BT_ENTRY(pagesize);
MAKE_BT_ENTRY(minkey);
MAKE_BT_ENTRY(re_len);
@@ -2505,6 +2715,9 @@ DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
MAKE_BT_ENTRY(leaf_pg);
MAKE_BT_ENTRY(dup_pg);
MAKE_BT_ENTRY(over_pg);
+#if (DBVER >= 43)
+ MAKE_BT_ENTRY(empty_pg);
+#endif
MAKE_BT_ENTRY(free);
MAKE_BT_ENTRY(int_pgfree);
MAKE_BT_ENTRY(leaf_pgfree);
@@ -2518,6 +2731,9 @@ DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
MAKE_QUEUE_ENTRY(nkeys);
MAKE_QUEUE_ENTRY(ndata);
MAKE_QUEUE_ENTRY(pagesize);
+#if (DBVER >= 41)
+ MAKE_QUEUE_ENTRY(extentsize);
+#endif
MAKE_QUEUE_ENTRY(pages);
MAKE_QUEUE_ENTRY(re_len);
MAKE_QUEUE_ENTRY(re_pad);
@@ -2561,7 +2777,6 @@ DB_sync(DBObject* self, PyObject* args)
}
-#if (DBVER >= 33)
static PyObject*
DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
{
@@ -2582,9 +2797,8 @@ DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
err = self->db->truncate(self->db, txn, &count, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
- return PyLong_FromLong(count);
+ return NUMBER_FromLong(count);
}
-#endif
static PyObject*
@@ -2632,15 +2846,14 @@ DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
if (outFile)
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;
+ { /* DB.verify acts as a DB handle destructor (like close) */
+ PyObject *error;
+
+ error=DB_close_internal(self,0);
+ if (error ) {
+ return error;
+ }
+ }
RETURN_IF_ERR();
RETURN_NONE();
@@ -2663,7 +2876,7 @@ DB_set_get_returns_none(DBObject* self, PyObject* args)
++oldValue;
self->moduleFlags.getReturnsNone = (flags >= 1);
self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
- return PyLong_FromLong(oldValue);
+ return NUMBER_FromLong(oldValue);
}
#if (DBVER >= 41)
@@ -2703,8 +2916,10 @@ Py_ssize_t DB_length(PyObject* _self)
if (self->db == NULL) {
PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
return -1;
}
@@ -2717,17 +2932,15 @@ Py_ssize_t DB_length(PyObject* _self)
redo_stat_for_length:
#if (DBVER >= 43)
err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
-#elif (DBVER >= 33)
- err = self->db->stat(self->db, &sp, flags);
#else
- err = self->db->stat(self->db, &sp, NULL, flags);
+ err = self->db->stat(self->db, &sp, flags);
#endif
/* 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;
- /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
+ /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
* redo a full stat to make sure.
* Fixes SF python bug 1493322, pybsddb bug 1184012
*/
@@ -2754,17 +2967,16 @@ PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
{
int err;
PyObject* retval;
- Py_buffer* key_buf_view = NULL;
DBT key;
DBT data;
CHECK_DB_NOT_CLOSED(self);
- if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+ 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) */
+ /* Tell Berkeley DB to malloc the return value (thread safe) */
data.flags = DB_DBT_MALLOC;
}
MYDB_BEGIN_ALLOW_THREADS;
@@ -2778,11 +2990,11 @@ PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
retval = NULL;
}
else {
- retval = PyBytes_FromStringAndSize((char*)data.data, data.size);
- free_dbt(&data);
+ retval = Build_PyString(data.data, data.size);
+ FREE_DBT(data);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return retval;
}
@@ -2793,21 +3005,21 @@ DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
DBT key, data;
int retval;
int flags = 0;
- Py_buffer *data_buf_view = NULL;
- Py_buffer *key_buf_view = NULL;
if (self->db == NULL) {
PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
return -1;
}
- if (!make_key_dbt(self, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, NULL))
return -1;
if (dataobj != NULL) {
- if (!make_dbt(dataobj, &data, &data_buf_view))
+ if (!make_dbt(dataobj, &data))
retval = -1;
else {
if (self->setflags & (DB_DUP|DB_DUPSORT))
@@ -2828,29 +3040,30 @@ DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
/* dataobj == NULL, so delete the key */
retval = _DB_delete(self, NULL, &key, 0);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key);
return retval;
}
static PyObject*
-DB_has_key(DBObject* self, PyObject* args)
+DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
{
int err;
PyObject* keyobj;
- Py_buffer* key_buf_view = NULL;
DBT key, data;
PyObject* txnobj = NULL;
DB_TXN *txn = NULL;
+ static char* kwnames[] = {"key","txn", NULL};
- if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
+ 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, &key_buf_view))
+ if (!make_key_dbt(self, keyobj, &key, NULL))
return NULL;
if (!checkTxnObj(txnobj, &txn)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
return NULL;
}
@@ -2864,12 +3077,12 @@ DB_has_key(DBObject* self, PyObject* args)
MYDB_BEGIN_ALLOW_THREADS;
err = self->db->get(self->db, txn, &key, &data, 0);
MYDB_END_ALLOW_THREADS;
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key);
if (err == DB_BUFFER_SMALL || err == 0) {
- return PyLong_FromLong(1);
+ return NUMBER_FromLong(1);
} else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
- return PyLong_FromLong(0);
+ return NUMBER_FromLong(0);
}
makeDBError(err);
@@ -2912,14 +3125,9 @@ _DB_make_list(DBObject* self, DB_TXN* txn, int type)
return NULL;
}
- 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);
+ err = _DBC_get(cursor, &key, &data, DB_NEXT);
MYDB_END_ALLOW_THREADS;
if (err) {
@@ -2933,17 +3141,17 @@ _DB_make_list(DBObject* self, DB_TXN* txn, int type)
case DB_BTREE:
case DB_HASH:
default:
- item = PyBytes_FromStringAndSize((char*)key.data, key.size);
+ item = Build_PyString(key.data, key.size);
break;
case DB_RECNO:
case DB_QUEUE:
- item = PyLong_FromLong(*((db_recno_t*)key.data));
+ item = NUMBER_FromLong(*((db_recno_t*)key.data));
break;
}
break;
case _VALUES_LIST:
- item = PyBytes_FromStringAndSize((char*)data.data, data.size);
+ item = Build_PyString(data.data, data.size);
break;
case _ITEMS_LIST:
@@ -2951,13 +3159,11 @@ _DB_make_list(DBObject* self, DB_TXN* txn, int type)
case DB_BTREE:
case DB_HASH:
default:
- item = Py_BuildValue("y#y#", key.data, key.size, data.data,
- data.size);
+ item = BuildValue_SS(key.data, key.size, data.data, data.size);
break;
case DB_RECNO:
case DB_QUEUE:
- item = Py_BuildValue("iy#", *((db_recno_t*)key.data),
- data.data, data.size);
+ item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
}
break;
@@ -2971,7 +3177,12 @@ _DB_make_list(DBObject* self, DB_TXN* txn, int type)
list = NULL;
goto done;
}
- PyList_Append(list, item);
+ if (PyList_Append(list, item)) {
+ Py_DECREF(list);
+ Py_DECREF(item);
+ list = NULL;
+ goto done;
+ }
Py_DECREF(item);
}
@@ -2982,10 +3193,8 @@ _DB_make_list(DBObject* self, DB_TXN* txn, int type)
}
done:
- free_dbt(&key);
- free_dbt(&data);
MYDB_BEGIN_ALLOW_THREADS;
- cursor->c_close(cursor);
+ _DBC_close(cursor);
MYDB_END_ALLOW_THREADS;
return list;
}
@@ -3037,23 +3246,32 @@ DB_values(DBObject* self, PyObject* args)
static PyObject*
-DBC_close(DBCursorObject* self, PyObject* args)
+DBC_close_internal(DBCursorObject* self)
{
int err = 0;
- if (!PyArg_ParseTuple(args, ":close"))
- return NULL;
-
if (self->dbc != NULL) {
+ EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+ if (self->txn) {
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
+ self->txn=NULL;
+ }
+
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_close(self->dbc);
- self->dbc = NULL;
+ err = _DBC_close(self->dbc);
MYDB_END_ALLOW_THREADS;
+ self->dbc = NULL;
}
RETURN_IF_ERR();
RETURN_NONE();
}
+static PyObject*
+DBC_close(DBCursorObject* self)
+{
+ return DBC_close_internal(self);
+}
+
static PyObject*
DBC_count(DBCursorObject* self, PyObject* args)
@@ -3068,11 +3286,11 @@ DBC_count(DBCursorObject* self, PyObject* args)
CHECK_CURSOR_NOT_CLOSED(self);
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_count(self->dbc, &count, flags);
+ err = _DBC_count(self->dbc, &count, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
- return PyLong_FromLong(count);
+ return NUMBER_FromLong(count);
}
@@ -3094,7 +3312,7 @@ DBC_delete(DBCursorObject* self, PyObject* args)
CHECK_CURSOR_NOT_CLOSED(self);
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_del(self->dbc, flags);
+ err = _DBC_del(self->dbc, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
@@ -3115,11 +3333,11 @@ DBC_dup(DBCursorObject* self, PyObject* args)
CHECK_CURSOR_NOT_CLOSED(self);
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_dup(self->dbc, &dbc, flags);
+ err = _DBC_dup(self->dbc, &dbc, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
- return (PyObject*) newDBCursorObject(dbc, self->mydb);
+ return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
}
static PyObject*
@@ -3136,8 +3354,6 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
PyObject* keyobj = NULL;
PyObject* dataobj = NULL;
PyObject* retval = NULL;
- Py_buffer* data_buf_view = NULL;
- Py_buffer* key_buf_view = NULL;
int dlen = -1;
int doff = -1;
DBT key, data;
@@ -3151,7 +3367,7 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
{
PyErr_Clear();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
- &kwnames[1],
+ &kwnames[1],
&keyobj, &flags, &dlen, &doff))
{
PyErr_Clear();
@@ -3166,25 +3382,17 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
CHECK_CURSOR_NOT_CLOSED(self);
- if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
+ if ( (dataobj && !make_dbt(dataobj, &data)) ||
(!add_partial_dbt(&data, dlen, doff)) )
{
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return NULL;
}
- if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
- data.flags = DB_DBT_MALLOC;
- if (!(key.flags & DB_DBT_REALLOC)) {
- key.flags |= DB_DBT_MALLOC;
- }
- }
-
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_get(self->dbc, &key, &data, flags);
+ err = _DBC_get(self->dbc, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
@@ -3203,23 +3411,18 @@ DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("y#y#", key.data, key.size,
- data.data, data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
break;
case DB_RECNO:
case DB_QUEUE:
- retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
- data.data, data.size);
+ retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
}
- free_dbt(&data);
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return retval;
}
-#if (DBVER >= 33)
static PyObject*
DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
{
@@ -3227,8 +3430,6 @@ DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
PyObject* keyobj = NULL;
PyObject* dataobj = NULL;
PyObject* retval = NULL;
- Py_buffer* data_buf_view = NULL;
- Py_buffer* key_buf_view = NULL;
int dlen = -1;
int doff = -1;
DBT key, pkey, data;
@@ -3257,27 +3458,19 @@ DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
CHECK_CURSOR_NOT_CLOSED(self);
- if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if ( (dataobj && !make_dbt(dataobj, &data, &data_buf_view)) ||
+ if ( (dataobj && !make_dbt(dataobj, &data)) ||
(!add_partial_dbt(&data, dlen, doff)) ) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return NULL;
}
- if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
- data.flags = DB_DBT_MALLOC;
- if (!(key.flags & DB_DBT_REALLOC)) {
- key.flags |= DB_DBT_MALLOC;
- }
- }
-
CLEAR_DBT(pkey);
pkey.flags = DB_DBT_MALLOC;
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
+ err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
@@ -3291,76 +3484,71 @@ DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
else {
PyObject *pkeyObj;
PyObject *dataObj;
- dataObj = PyBytes_FromStringAndSize(data.data, data.size);
+ dataObj = Build_PyString(data.data, data.size);
if (self->mydb->primaryDBType == DB_RECNO ||
self->mydb->primaryDBType == DB_QUEUE)
- pkeyObj = PyLong_FromLong(*(int *)pkey.data);
+ pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
else
- pkeyObj = PyBytes_FromStringAndSize(pkey.data, pkey.size);
+ pkeyObj = Build_PyString(pkey.data, pkey.size);
if (key.data && key.size) /* return key, pkey and data */
{
PyObject *keyObj;
int type = _DB_get_type(self->mydb);
if (type == DB_RECNO || type == DB_QUEUE)
- keyObj = PyLong_FromLong(*(int *)key.data);
+ keyObj = NUMBER_FromLong(*(int *)key.data);
else
- keyObj = PyBytes_FromStringAndSize(key.data, key.size);
+ keyObj = Build_PyString(key.data, key.size);
+#if (PY_VERSION_HEX >= 0x02040000)
retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
+#else
+ retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
+#endif
Py_DECREF(keyObj);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
}
else /* return just the pkey and data */
{
+#if (PY_VERSION_HEX >= 0x02040000)
retval = PyTuple_Pack(2, pkeyObj, dataObj);
+#else
+ retval = Py_BuildValue("OO", pkeyObj, dataObj);
+#endif
}
Py_DECREF(dataObj);
Py_DECREF(pkeyObj);
- free_dbt(&pkey);
- free_dbt(&data);
+ FREE_DBT(pkey);
}
/* the only time REALLOC should be set is if we used an integer
* key that make_key_dbt malloc'd for us. always free these. */
- if (key.flags & DB_DBT_REALLOC) {
- free_dbt(&key);
+ if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
+ FREE_DBT(key);
}
- free_buf_view(keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
return retval;
}
-#endif
static PyObject*
-DBC_get_recno(DBCursorObject* self, PyObject* args)
+DBC_get_recno(DBCursorObject* self)
{
int err;
db_recno_t recno;
DBT key;
DBT data;
- if (!PyArg_ParseTuple(args, ":get_recno"))
- 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) */
- 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);
+ err = _DBC_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 PyLong_FromLong(recno);
+ return NUMBER_FromLong(recno);
}
@@ -3389,9 +3577,7 @@ static PyObject*
DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
{
int err, flags = 0;
- PyObject *keyobj, *dataobj;
- Py_buffer *data_buf_view = NULL;
- Py_buffer *key_buf_view = NULL;
+ PyObject* keyobj, *dataobj;
DBT key, data;
static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
NULL };
@@ -3404,21 +3590,19 @@ DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
CHECK_CURSOR_NOT_CLOSED(self);
- if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if (!make_dbt(dataobj, &data, &data_buf_view) ||
+ if (!make_dbt(dataobj, &data) ||
!add_partial_dbt(&data, dlen, doff) )
{
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return NULL;
}
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_put(self->dbc, &key, &data, flags);
+ err = _DBC_put(self->dbc, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
RETURN_IF_ERR();
self->mydb->haveStat = 0;
RETURN_NONE();
@@ -3430,8 +3614,7 @@ DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
{
int err, flags = 0;
DBT key, data;
- PyObject *retval, *keyobj;
- Py_buffer *key_buf_view = NULL;
+ PyObject* retval, *keyobj;
static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
int dlen = -1;
int doff = -1;
@@ -3442,21 +3625,17 @@ DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
CHECK_CURSOR_NOT_CLOSED(self);
- if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ 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)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return NULL;
}
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
+ err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
&& self->mydb->moduleFlags.cursorSetReturnsNone) {
@@ -3474,24 +3653,20 @@ DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("y#y#", key.data, key.size,
- data.data, data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
break;
case DB_RECNO:
case DB_QUEUE:
- retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
- data.data, data.size);
+ retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
}
- free_dbt(&data);
- free_dbt(&key);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
}
/* the only time REALLOC should be set is if we used an integer
* key that make_key_dbt malloc'd for us. always free these. */
if (key.flags & DB_DBT_REALLOC) {
- free_dbt(&key);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
}
- free_buf_view(keyobj, key_buf_view);
return retval;
}
@@ -3502,8 +3677,7 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
{
int err, flags = 0;
DBT key, data;
- PyObject *retval, *keyobj;
- Py_buffer *key_buf_view = NULL;
+ PyObject* retval, *keyobj;
static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
int dlen = -1;
int doff = -1;
@@ -3514,24 +3688,16 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
CHECK_CURSOR_NOT_CLOSED(self);
- if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
CLEAR_DBT(data);
if (!add_partial_dbt(&data, dlen, doff)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return NULL;
}
- if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
- /* Tell BerkeleyDB to malloc the return value (thread safe) */
- data.flags |= DB_DBT_MALLOC;
- /* only BTREE databases will return anything in the key */
- if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
- key.flags |= DB_DBT_MALLOC;
- }
- }
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
+ err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
&& self->mydb->moduleFlags.cursorSetReturnsNone) {
@@ -3549,24 +3715,20 @@ DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("y#y#", key.data, key.size,
- data.data, data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
break;
case DB_RECNO:
case DB_QUEUE:
- retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
- data.data, data.size);
+ retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
}
- free_dbt(&key);
- free_dbt(&data);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
}
/* the only time REALLOC should be set is if we used an integer
* key that make_key_dbt malloc'd for us. always free these. */
if (key.flags & DB_DBT_REALLOC) {
- free_dbt(&key);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
}
- free_buf_view(keyobj, key_buf_view);
return retval;
}
@@ -3577,20 +3739,18 @@ _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
{
int err;
DBT key, data;
- PyObject *retval;
- Py_buffer *data_buf_view = NULL;
- Py_buffer *key_buf_view = NULL;
+ PyObject* retval;
/* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
- if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
- if (!make_dbt(dataobj, &data, &data_buf_view)) {
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ if (!make_dbt(dataobj, &data)) {
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return NULL;
}
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
+ err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Py_INCREF(Py_None);
@@ -3607,19 +3767,16 @@ _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("y#y#", key.data, key.size,
- data.data, data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
break;
case DB_RECNO:
case DB_QUEUE:
- retval = Py_BuildValue("iy#", *((db_recno_t*)key.data),
- data.data, data.size);
+ retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
}
}
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
- free_buf_view(dataobj, data_buf_view);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
return retval;
}
@@ -3641,14 +3798,12 @@ DBC_get_both(DBCursorObject* self, PyObject* args)
/* Return size of entry */
static PyObject*
-DBC_get_current_size(DBCursorObject* self, PyObject* args)
+DBC_get_current_size(DBCursorObject* self)
{
int err, flags=DB_CURRENT;
PyObject* retval = NULL;
DBT key, data;
- if (!PyArg_ParseTuple(args, ":get_current_size"))
- return NULL;
CHECK_CURSOR_NOT_CLOSED(self);
CLEAR_DBT(key);
CLEAR_DBT(data);
@@ -3658,16 +3813,14 @@ DBC_get_current_size(DBCursorObject* self, PyObject* args)
data.flags = DB_DBT_USERMEM;
data.ulen = 0;
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_get(self->dbc, &key, &data, flags);
+ err = _DBC_get(self->dbc, &key, &data, flags);
MYDB_END_ALLOW_THREADS;
if (err == DB_BUFFER_SMALL || !err) {
/* DB_BUFFER_SMALL means positive size, !err means zero length value */
- retval = PyLong_FromLong((long)data.size);
+ retval = NUMBER_FromLong((long)data.size);
err = 0;
}
- free_dbt(&key);
- free_dbt(&data);
RETURN_IF_ERR();
return retval;
}
@@ -3721,17 +3874,13 @@ DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
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)) {
- free_dbt(&key);
+ FREE_DBT(key);
return NULL;
}
MYDB_BEGIN_ALLOW_THREADS;
- err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
+ err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
&& self->mydb->moduleFlags.cursorSetReturnsNone) {
@@ -3742,11 +3891,9 @@ DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
retval = NULL;
}
else { /* Can only be used for BTrees, so no need to return int key */
- retval = Py_BuildValue("y#y#", key.data, key.size,
- data.data, data.size);
- free_dbt(&data);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
}
- free_dbt(&key);
+ FREE_DBT(key);
return retval;
}
@@ -3794,13 +3941,9 @@ DBC_join_item(DBCursorObject* self, PyObject* args)
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);
+ err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
MYDB_END_ALLOW_THREADS;
if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
&& self->mydb->moduleFlags.getReturnsNone) {
@@ -3811,8 +3954,7 @@ DBC_join_item(DBCursorObject* self, PyObject* args)
retval = NULL;
}
else {
- retval = Py_BuildValue("y#", key.data, key.size);
- free_dbt(&key);
+ retval = BuildValue_S(key.data, key.size);
}
return retval;
@@ -3825,18 +3967,26 @@ DBC_join_item(DBCursorObject* self, PyObject* args)
static PyObject*
-DBEnv_close(DBEnvObject* self, PyObject* args)
+DBEnv_close_internal(DBEnvObject* self, int flags)
{
- int err, flags = 0;
+ PyObject *dummy;
+ int err;
- if (!PyArg_ParseTuple(args, "|i:close", &flags))
- return NULL;
if (!self->closed) { /* Don't close more than once */
+ while(self->children_txns) {
+ dummy=DBTxn_abort_discard_internal(self->children_txns,0);
+ Py_XDECREF(dummy);
+ }
+ while(self->children_dbs) {
+ dummy=DB_close_internal(self->children_dbs,0);
+ Py_XDECREF(dummy);
+ }
+
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). */
+ * may not be accessed again (Berkeley DB docs). */
self->closed = 1;
self->db_env = NULL;
RETURN_IF_ERR();
@@ -3844,6 +3994,16 @@ DBEnv_close(DBEnvObject* self, PyObject* args)
RETURN_NONE();
}
+static PyObject*
+DBEnv_close(DBEnvObject* self, PyObject* args)
+{
+ int flags = 0;
+
+ if (!PyArg_ParseTuple(args, "|i:close", &flags))
+ return NULL;
+ return DBEnv_close_internal(self,flags);
+}
+
static PyObject*
DBEnv_open(DBEnvObject* self, PyObject* args)
@@ -3961,7 +4121,6 @@ DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
}
#endif /* DBVER >= 41 */
-#if (DBVER >= 40)
static PyObject*
DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
{
@@ -3982,7 +4141,6 @@ DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
RETURN_IF_ERR();
RETURN_NONE();
}
-#endif /* DBVER >= 40 */
static PyObject*
DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
@@ -4035,6 +4193,26 @@ DBEnv_set_flags(DBEnvObject* self, PyObject* args)
}
+#if (DBVER >= 47)
+static PyObject*
+DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
+{
+ int err, flags, onoff;
+
+ if (!PyArg_ParseTuple(args, "ii:log_set_config",
+ &flags, &onoff))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->log_set_config(self->db_env, flags, onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif /* DBVER >= 47 */
+
+
static PyObject*
DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
{
@@ -4103,8 +4281,24 @@ DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
RETURN_NONE();
}
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lg_max(DBEnvObject* self)
+{
+ int err;
+ u_int32_t lg_max;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_lg_max(self->db_env, &lg_max);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(lg_max);
+}
+#endif
+
-#if (DBVER >= 33)
static PyObject*
DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
{
@@ -4120,7 +4314,6 @@ DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
RETURN_IF_ERR();
RETURN_NONE();
}
-#endif
static PyObject*
@@ -4247,6 +4440,79 @@ DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
static PyObject*
+DBEnv_txn_recover(DBEnvObject* self)
+{
+ int flags = DB_FIRST;
+ int err, i;
+ PyObject *list, *tuple, *gid;
+ DBTxnObject *txn;
+#define PREPLIST_LEN 16
+ DB_PREPLIST preplist[PREPLIST_LEN];
+ long retp;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ list=PyList_New(0);
+ if (!list)
+ return NULL;
+ while (!0) {
+ MYDB_BEGIN_ALLOW_THREADS
+ err=self->db_env->txn_recover(self->db_env,
+ preplist, PREPLIST_LEN, &retp, flags);
+#undef PREPLIST_LEN
+ MYDB_END_ALLOW_THREADS
+ if (err) {
+ Py_DECREF(list);
+ RETURN_IF_ERR();
+ }
+ if (!retp) break;
+ flags=DB_NEXT; /* Prepare for next loop pass */
+ for (i=0; i<retp; i++) {
+ gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
+ DB_XIDDATASIZE);
+ if (!gid) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
+ if (!txn) {
+ Py_DECREF(list);
+ Py_DECREF(gid);
+ return NULL;
+ }
+ txn->flag_prepare=1; /* Recover state */
+ tuple=PyTuple_New(2);
+ if (!tuple) {
+ Py_DECREF(list);
+ Py_DECREF(gid);
+ Py_DECREF(txn);
+ return NULL;
+ }
+ if (PyTuple_SetItem(tuple, 0, gid)) {
+ Py_DECREF(list);
+ Py_DECREF(gid);
+ Py_DECREF(txn);
+ Py_DECREF(tuple);
+ return NULL;
+ }
+ if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
+ Py_DECREF(list);
+ Py_DECREF(txn);
+ Py_DECREF(tuple); /* This delete the "gid" also */
+ return NULL;
+ }
+ if (PyList_Append(list, tuple)) {
+ Py_DECREF(list);
+ Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
+ return NULL;
+ }
+ Py_DECREF(tuple);
+ }
+ }
+ return list;
+}
+
+static PyObject*
DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
{
int flags = 0;
@@ -4262,7 +4528,7 @@ DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
return NULL;
CHECK_ENV_NOT_CLOSED(self);
- return (PyObject*)newDBTxnObject(self, txn, flags);
+ return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
}
@@ -4276,11 +4542,7 @@ DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
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();
@@ -4330,14 +4592,10 @@ DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
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 PyLong_FromLong(aborted);
+ return NUMBER_FromLong(aborted);
}
@@ -4347,44 +4605,34 @@ DBEnv_lock_get(DBEnvObject* self, PyObject* args)
int flags=0;
int locker, lock_mode;
DBT obj;
- PyObject *objobj, *retval;
- Py_buffer *obj_buf_view = NULL;
+ PyObject* objobj;
if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
return NULL;
- if (!make_dbt(objobj, &obj, &obj_buf_view))
+
+ if (!make_dbt(objobj, &obj))
return NULL;
- retval = (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
- free_buf_view(objobj, obj_buf_view);
- return retval;
+ return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
}
static PyObject*
-DBEnv_lock_id(DBEnvObject* self, PyObject* args)
+DBEnv_lock_id(DBEnvObject* self)
{
int err;
u_int32_t theID;
- if (!PyArg_ParseTuple(args, ":lock_id"))
- return NULL;
-
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 PyLong_FromLong((long)theID);
+ return NUMBER_FromLong((long)theID);
}
-#if (DBVER >= 40)
static PyObject*
DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
{
@@ -4401,7 +4649,6 @@ DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
RETURN_IF_ERR();
RETURN_NONE();
}
-#endif
static PyObject*
DBEnv_lock_put(DBEnvObject* self, PyObject* args)
@@ -4414,11 +4661,7 @@ DBEnv_lock_put(DBEnvObject* self, PyObject* args)
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();
@@ -4446,7 +4689,6 @@ DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
}
#endif /* DBVER >= 4.4 */
-#if (DBVER >= 40)
static PyObject*
DBEnv_log_stat(DBEnvObject* self, PyObject* args)
{
@@ -4482,7 +4724,7 @@ DBEnv_log_stat(DBEnvObject* self, PyObject* args)
MAKE_ENTRY(lg_size);
MAKE_ENTRY(record);
#endif
-#if (DBVER <= 40)
+#if (DBVER < 41)
MAKE_ENTRY(lg_max);
#endif
MAKE_ENTRY(w_mbytes);
@@ -4509,7 +4751,6 @@ DBEnv_log_stat(DBEnvObject* self, PyObject* args)
free(statp);
return d;
} /* DBEnv_log_stat */
-#endif /* DBVER >= 4.0 for log_stat method */
static PyObject*
@@ -4525,15 +4766,7 @@ DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
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();
@@ -4549,6 +4782,10 @@ DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
#if (DBVER < 41)
MAKE_ENTRY(lastid);
#endif
+#if (DBVER >=41)
+ MAKE_ENTRY(id);
+ MAKE_ENTRY(cur_maxid);
+#endif
MAKE_ENTRY(nmodes);
MAKE_ENTRY(maxlocks);
MAKE_ENTRY(maxlockers);
@@ -4561,6 +4798,10 @@ DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
MAKE_ENTRY(maxnobjects);
MAKE_ENTRY(nrequests);
MAKE_ENTRY(nreleases);
+#if (DBVER >= 44)
+ MAKE_ENTRY(nupgrade);
+ MAKE_ENTRY(ndowngrade);
+#endif
#if (DBVER < 44)
MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
MAKE_ENTRY(nconflicts);
@@ -4569,6 +4810,26 @@ DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
MAKE_ENTRY(lock_wait);
#endif
MAKE_ENTRY(ndeadlocks);
+#if (DBVER >= 41)
+ MAKE_ENTRY(locktimeout);
+ MAKE_ENTRY(txntimeout);
+#endif
+ MAKE_ENTRY(nlocktimeouts);
+ MAKE_ENTRY(ntxntimeouts);
+#if (DBVER >= 46)
+ MAKE_ENTRY(objs_wait);
+ MAKE_ENTRY(objs_nowait);
+ MAKE_ENTRY(lockers_wait);
+ MAKE_ENTRY(lockers_nowait);
+#if (DBVER >= 47)
+ MAKE_ENTRY(lock_wait);
+ MAKE_ENTRY(lock_nowait);
+#else
+ MAKE_ENTRY(locks_wait);
+ MAKE_ENTRY(locks_nowait);
+#endif
+ MAKE_ENTRY(hash_len);
+#endif
MAKE_ENTRY(regsize);
MAKE_ENTRY(region_wait);
MAKE_ENTRY(region_nowait);
@@ -4578,6 +4839,20 @@ DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
return d;
}
+static PyObject*
+DBEnv_log_flush(DBEnvObject* self)
+{
+ int err;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS
+ err = self->db_env->log_flush(self->db_env, NULL);
+ MYDB_END_ALLOW_THREADS
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
static PyObject*
DBEnv_log_archive(DBEnvObject* self, PyObject* args)
@@ -4593,13 +4868,7 @@ DBEnv_log_archive(DBEnvObject* self, PyObject* args)
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();
@@ -4613,13 +4882,18 @@ DBEnv_log_archive(DBEnvObject* self, PyObject* args)
if (log_list) {
char **log_list_start;
for (log_list_start = log_list; *log_list != NULL; ++log_list) {
- item = PyUnicode_FromString (*log_list);
+ item = PyBytes_FromString (*log_list);
if (item == NULL) {
Py_DECREF(list);
list = NULL;
break;
}
- PyList_Append(list, item);
+ if (PyList_Append(list, item)) {
+ Py_DECREF(list);
+ list = NULL;
+ Py_DECREF(item);
+ break;
+ }
Py_DECREF(item);
}
free(log_list_start);
@@ -4641,13 +4915,7 @@ DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
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();
@@ -4658,21 +4926,29 @@ DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
return NULL;
}
-#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
-#define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
+#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
+#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
+#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
+ MAKE_DB_LSN_ENTRY(last_ckp);
MAKE_TIME_T_ENTRY(time_ckp);
MAKE_ENTRY(last_txnid);
MAKE_ENTRY(maxtxns);
MAKE_ENTRY(nactive);
MAKE_ENTRY(maxnactive);
+#if (DBVER >= 45)
+ MAKE_ENTRY(nsnapshot);
+ MAKE_ENTRY(maxnsnapshot);
+#endif
MAKE_ENTRY(nbegins);
MAKE_ENTRY(naborts);
MAKE_ENTRY(ncommits);
+ MAKE_ENTRY(nrestores);
MAKE_ENTRY(regsize);
MAKE_ENTRY(region_wait);
MAKE_ENTRY(region_nowait);
+#undef MAKE_DB_LSN_ENTRY
#undef MAKE_ENTRY
#undef MAKE_TIME_T_ENTRY
free(sp);
@@ -4696,122 +4972,947 @@ DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
++oldValue;
self->moduleFlags.getReturnsNone = (flags >= 1);
self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
- return PyLong_FromLong(oldValue);
+ return NUMBER_FromLong(oldValue);
+}
+
+static PyObject*
+DBEnv_get_private(DBEnvObject* self)
+{
+ /* We can give out the private field even if dbenv is closed */
+ Py_INCREF(self->private_obj);
+ return self->private_obj;
+}
+
+static PyObject*
+DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
+{
+ /* We can set the private field even if dbenv is closed */
+ Py_DECREF(self->private_obj);
+ Py_INCREF(private_obj);
+ self->private_obj = private_obj;
+ RETURN_NONE();
+}
+
+
+static PyObject*
+DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ char *host;
+ long cl_timeout=0, sv_timeout=0;
+
+ static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
+ &host, &cl_timeout, &sv_timeout))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
+ sv_timeout, 0);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int which, onoff;
+
+ if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_verbose(self->db_env, which, onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int which;
+ int verbose;
+
+ if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->get_verbose(self->db_env, which, &verbose);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return PyBool_FromLong(verbose);
+}
+#endif
+
+#if (DBVER >= 45)
+static void
+_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
+{
+ DBEnvObject *dbenv;
+ PyObject* callback;
+ PyObject* args;
+ PyObject* result = NULL;
+
+ MYDB_BEGIN_BLOCK_THREADS;
+ dbenv = (DBEnvObject *)db_env->app_private;
+ callback = dbenv->event_notifyCallback;
+ if (callback) {
+ if (event == DB_EVENT_REP_NEWMASTER) {
+ args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
+ } else {
+ args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
+ }
+ if (args) {
+ result = PyEval_CallObject(callback, args);
+ }
+ if ((!args) || (!result)) {
+ PyErr_Print();
+ }
+ Py_XDECREF(args);
+ Py_XDECREF(result);
+ }
+ MYDB_END_BLOCK_THREADS;
+}
+#endif
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
+{
+ int err;
+
+ CHECK_ENV_NOT_CLOSED(self);
+
+ if (!PyCallable_Check(notifyFunc)) {
+ makeTypeError("Callable", notifyFunc);
+ return NULL;
+ }
+
+ Py_XDECREF(self->event_notifyCallback);
+ Py_INCREF(notifyFunc);
+ self->event_notifyCallback = notifyFunc;
+
+ /* This is to workaround a problem with un-initialized threads (see
+ comment in DB_associate) */
+#ifdef WITH_THREAD
+ PyEval_InitThreads();
+#endif
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
+ MYDB_END_ALLOW_THREADS;
+
+ if (err) {
+ Py_DECREF(notifyFunc);
+ self->event_notifyCallback = NULL;
+ }
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
}
+#endif
/* --------------------------------------------------------------------- */
-/* DBTxn methods */
+/* REPLICATION METHODS: Base Replication */
static PyObject*
-DBTxn_commit(DBTxnObject* self, PyObject* args)
+DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
{
- int flags=0, err;
- DB_TXN *txn;
+ int err;
+ PyObject *control_py, *rec_py;
+ DBT control, rec;
+ int envid;
+#if (DBVER >= 42)
+ DB_LSN lsn;
+#endif
- if (!PyArg_ParseTuple(args, "|i:commit", &flags))
+ if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
+ &rec_py, &envid))
return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
- if (!self->txn) {
- PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+ if (!make_dbt(control_py, &control))
+ return NULL;
+ if (!make_dbt(rec_py, &rec))
return NULL;
+
+ MYDB_BEGIN_ALLOW_THREADS;
+#if (DBVER >= 46)
+ err = self->db_env->rep_process_message(self->db_env, &control, &rec,
+ envid, &lsn);
+#else
+#if (DBVER >= 42)
+ err = self->db_env->rep_process_message(self->db_env, &control, &rec,
+ &envid, &lsn);
+#else
+ err = self->db_env->rep_process_message(self->db_env, &control, &rec,
+ &envid);
+#endif
+#endif
+ MYDB_END_ALLOW_THREADS;
+ switch (err) {
+ case DB_REP_NEWMASTER :
+ return Py_BuildValue("(iO)", envid, Py_None);
+ break;
+
+ case DB_REP_DUPMASTER :
+ case DB_REP_HOLDELECTION :
+#if (DBVER >= 44)
+ case DB_REP_IGNORE :
+ case DB_REP_JOIN_FAILURE :
+#endif
+ return Py_BuildValue("(iO)", err, Py_None);
+ break;
+ case DB_REP_NEWSITE :
+ {
+ PyObject *tmp, *r;
+
+ if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
+ return NULL;
+ }
+
+ r = Py_BuildValue("(iO)", err, tmp);
+ Py_DECREF(tmp);
+ return r;
+ break;
+ }
+#if (DBVER >= 42)
+ case DB_REP_NOTPERM :
+ case DB_REP_ISPERM :
+ return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
+ break;
+#endif
}
- txn = self->txn;
- self->txn = NULL; /* this DB_TXN is no longer valid after this call */
+ RETURN_IF_ERR();
+ return Py_BuildValue("(OO)", Py_None, Py_None);
+}
+
+static int
+_DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
+ const DB_LSN *lsn, int envid, u_int32_t flags)
+{
+ DBEnvObject *dbenv;
+ PyObject* rep_transport;
+ PyObject* args;
+ PyObject *a, *b;
+ PyObject* result = NULL;
+ int ret=0;
+
+ MYDB_BEGIN_BLOCK_THREADS;
+ dbenv = (DBEnvObject *)db_env->app_private;
+ rep_transport = dbenv->rep_transport;
+
+ /*
+ ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
+ */
+ a = PyBytes_FromStringAndSize(control->data, control->size);
+ b = PyBytes_FromStringAndSize(rec->data, rec->size);
+
+ args = Py_BuildValue(
+#if (PY_VERSION_HEX >= 0x02040000)
+ "(OOO(ll)iI)",
+#else
+ "(OOO(ll)ii)",
+#endif
+ dbenv,
+ a, b,
+ lsn->file, lsn->offset, envid, flags);
+ if (args) {
+ result = PyEval_CallObject(rep_transport, args);
+ }
+
+ if ((!args) || (!result)) {
+ PyErr_Print();
+ ret = -1;
+ }
+ Py_XDECREF(a);
+ Py_XDECREF(b);
+ Py_XDECREF(args);
+ Py_XDECREF(result);
+ MYDB_END_BLOCK_THREADS;
+ return ret;
+}
+
+#if (DBVER <= 41)
+static int
+_DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
+ int envid, u_int32_t flags)
+{
+ DB_LSN lsn;
+
+ lsn.file = -1; /* Dummy values */
+ lsn.offset = -1;
+ return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
+ flags);
+}
+#endif
+
+static PyObject*
+DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int envid;
+ PyObject *rep_transport;
+
+ if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+ if (!PyCallable_Check(rep_transport)) {
+ makeTypeError("Callable", rep_transport);
+ return NULL;
+ }
+
MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
- err = txn->commit(txn, flags);
+#if (DBVER >=45)
+ err = self->db_env->rep_set_transport(self->db_env, envid,
+ &_DBEnv_rep_transportCallback);
+#else
+#if (DBVER >= 42)
+ err = self->db_env->set_rep_transport(self->db_env, envid,
+ &_DBEnv_rep_transportCallback);
#else
- err = txn_commit(txn, flags);
+ err = self->db_env->set_rep_transport(self->db_env, envid,
+ &_DBEnv_rep_transportCallbackOLD);
+#endif
#endif
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
+
+ Py_DECREF(self->rep_transport);
+ Py_INCREF(rep_transport);
+ self->rep_transport = rep_transport;
RETURN_NONE();
}
+#if (DBVER >= 47)
static PyObject*
-DBTxn_prepare(DBTxnObject* self, PyObject* args)
+DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
{
-#if (DBVER >= 33)
int err;
- char* gid=NULL;
- int gid_size=0;
+ unsigned int minimum, maximum;
- if (!PyArg_ParseTuple(args, "y#:prepare", &gid, &gid_size))
+ if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
- if (gid_size != DB_XIDDATASIZE) {
- PyErr_SetString(PyExc_TypeError,
- "gid must be DB_XIDDATASIZE bytes long");
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_request(DBEnvObject* self)
+{
+ int err;
+ u_int32_t minimum, maximum;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+#if (PY_VERSION_HEX >= 0x02040000)
+ return Py_BuildValue("II", minimum, maximum);
+#else
+ return Py_BuildValue("ii", minimum, maximum);
+#endif
+}
+#endif
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int limit;
+
+ if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_limit(self->db_env, 0, limit);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_limit(DBEnvObject* self)
+{
+ int err;
+ u_int32_t gbytes, bytes;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(bytes);
+}
+#endif
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int which;
+ int onoff;
+
+ if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_config(self->db_env, which, onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int which;
+ int onoff;
+
+ if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
return NULL;
}
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_get_config(self->db_env, which, &onoff);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return PyBool_FromLong(onoff);
+}
+#endif
- if (!self->txn) {
- PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
- "after txn_commit or txn_abort");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+#if (DBVER >= 46)
+static PyObject*
+DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ u_int32_t nsites, nvotes;
+
+ if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
return NULL;
}
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+static PyObject*
+DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
+{
+ int err;
+ PyObject *cdata_py = Py_None;
+ DBT cdata;
+ int flags;
+ static char* kwnames[] = {"flags","cdata", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "i|O:rep_start", kwnames, &flags, &cdata_py))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+
+ if (!make_dbt(cdata_py, &cdata))
+ return NULL;
+
MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
- err = self->txn->prepare(self->txn, (u_int8_t*)gid);
+ err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
+ flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+#if (DBVER >= 44)
+static PyObject*
+DBEnv_rep_sync(DBEnvObject* self)
+{
+ int err;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_sync(self->db_env, 0);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+#endif
+
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int nsites;
+
+ if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_nsites(self->db_env, nsites);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_nsites(DBEnvObject* self)
+{
+ int err;
+#if (DBVER >= 47)
+ u_int32_t nsites;
#else
- err = txn_prepare(self->txn, (u_int8_t*)gid);
+ int nsites;
#endif
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_get_nsites(self->db_env, &nsites);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(nsites);
+}
+
+static PyObject*
+DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int priority;
+
+ if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_priority(self->db_env, priority);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_rep_get_priority(DBEnvObject* self)
+{
+ int err;
+#if (DBVER >= 47)
+ u_int32_t priority;
#else
+ int priority;
+#endif
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_get_priority(self->db_env, &priority);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(priority);
+}
+
+static PyObject*
+DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
+{
int err;
+ int which, timeout;
- if (!PyArg_ParseTuple(args, ":prepare"))
+ if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
- if (!self->txn) {
- PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+static PyObject*
+DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int which;
+ u_int32_t timeout;
+
+ if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
return NULL;
}
+ CHECK_ENV_NOT_CLOSED(self);
MYDB_BEGIN_ALLOW_THREADS;
- err = txn_prepare(self->txn);
+ err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(timeout);
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+/* REPLICATION METHODS: Replication Manager */
+
+#if (DBVER >= 45)
+static PyObject*
+DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
+ kwargs)
+{
+ int err;
+ int nthreads, flags;
+ static char* kwnames[] = {"nthreads","flags", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "ii:repmgr_start", kwnames, &nthreads, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
+ kwargs)
+{
+ int err;
+ char *host;
+ int port;
+ int flags = 0;
+ static char* kwnames[] = {"host", "port", "flags", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
+ kwargs)
+{
+ int err;
+ char *host;
+ int port;
+ int flags = 0;
+ int eidp;
+ static char* kwnames[] = {"host", "port", "flags", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+ "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(eidp);
+}
+
+static PyObject*
+DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int ack_policy;
+
+ if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
+{
+ int err;
+ int ack_policy;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return NUMBER_FromLong(ack_policy);
+}
+
+static PyObject*
+DBEnv_repmgr_site_list(DBEnvObject* self)
+{
+ int err;
+ unsigned int countp;
+ DB_REPMGR_SITE *listp;
+ PyObject *stats, *key, *tuple;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ stats=PyDict_New();
+ if (stats == NULL) {
+ free(listp);
+ return NULL;
+ }
+
+ for(;countp--;) {
+ key=NUMBER_FromLong(listp[countp].eid);
+ if(!key) {
+ Py_DECREF(stats);
+ free(listp);
+ return NULL;
+ }
+#if (PY_VERSION_HEX >= 0x02040000)
+ tuple=Py_BuildValue("(sII)", listp[countp].host,
+ listp[countp].port, listp[countp].status);
+#else
+ tuple=Py_BuildValue("(sii)", listp[countp].host,
+ listp[countp].port, listp[countp].status);
#endif
+ if(!tuple) {
+ Py_DECREF(key);
+ Py_DECREF(stats);
+ free(listp);
+ return NULL;
+ }
+ if(PyDict_SetItem(stats, key, tuple)) {
+ Py_DECREF(key);
+ Py_DECREF(tuple);
+ Py_DECREF(stats);
+ free(listp);
+ return NULL;
+ }
+ }
+ free(listp);
+ return stats;
}
+#endif
+#if (DBVER >= 46)
+static PyObject*
+DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
+{
+ int err;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_stat_print(self->db_env, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
static PyObject*
-DBTxn_abort(DBTxnObject* self, PyObject* args)
+DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
{
int err;
+ int flags=0;
+ DB_REPMGR_STAT *statp;
+ PyObject *stats;
+ static char* kwnames[] = { "flags", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
+ kwnames, &flags))
+ {
+ return NULL;
+ }
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ stats=PyDict_New();
+ if (stats == NULL) {
+ free(statp);
+ return NULL;
+ }
+
+#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
+
+ MAKE_ENTRY(perm_failed);
+ MAKE_ENTRY(msgs_queued);
+ MAKE_ENTRY(msgs_dropped);
+ MAKE_ENTRY(connection_drop);
+ MAKE_ENTRY(connect_fail);
+
+#undef MAKE_ENTRY
+
+ free(statp);
+ return stats;
+}
+#endif
+
+
+/* --------------------------------------------------------------------- */
+/* DBTxn methods */
+
+
+static void _close_transaction_cursors(DBTxnObject* txn)
+{
+ PyObject *dummy;
+
+ while(txn->children_cursors) {
+ PyErr_Warn(PyExc_RuntimeWarning,
+ "Must close cursors before resolving a transaction.");
+ dummy=DBC_close_internal(txn->children_cursors);
+ Py_XDECREF(dummy);
+ }
+}
+
+static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
+{
+ DBObject *db;
+#if (DBVER >= 43)
+ DBSequenceObject *dbs;
+#endif
+
+ while (txn->children_dbs) {
+ db=txn->children_dbs;
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
+ if (txn->parent_txn) {
+ INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
+ db->txn=txn->parent_txn;
+ } else {
+ /* The db is already linked to its environment,
+ ** so nothing to do.
+ */
+ db->txn=NULL;
+ }
+ }
+
+#if (DBVER >= 43)
+ while (txn->children_sequences) {
+ dbs=txn->children_sequences;
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
+ if (txn->parent_txn) {
+ INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
+ dbs->txn=txn->parent_txn;
+ } else {
+ /* The sequence is already linked to its
+ ** parent db. Nothing to do.
+ */
+ dbs->txn=NULL;
+ }
+ }
+#endif
+}
+
+
+static PyObject*
+DBTxn_commit(DBTxnObject* self, PyObject* args)
+{
+ int flags=0, err;
DB_TXN *txn;
- if (!PyArg_ParseTuple(args, ":abort"))
+ if (!PyArg_ParseTuple(args, "|i:commit", &flags))
return NULL;
+ _close_transaction_cursors(self);
+
if (!self->txn) {
- PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+ PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
+ "after txn_commit, txn_abort "
+ "or txn_discard");
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
return NULL;
}
+ self->flag_prepare=0;
txn = self->txn;
self->txn = NULL; /* this DB_TXN is no longer valid after this call */
+
+ EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+
MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
- err = txn->abort(txn);
-#else
- err = txn_abort(txn);
-#endif
+ err = txn->commit(txn, flags);
+ MYDB_END_ALLOW_THREADS;
+
+ _promote_transaction_dbs_and_sequences(self);
+
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBTxn_prepare(DBTxnObject* self, PyObject* args)
+{
+ int err;
+ char* gid=NULL;
+ int gid_size=0;
+
+ if (!PyArg_ParseTuple(args, "s#:prepare", &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) {
+ PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
+ "after txn_commit, txn_abort "
+ "or txn_discard");
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
+ return NULL;
+ }
+ self->flag_prepare=1; /* Prepare state */
+ MYDB_BEGIN_ALLOW_THREADS;
+ err = self->txn->prepare(self->txn, (u_int8_t*)gid);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
RETURN_NONE();
@@ -4819,28 +5920,95 @@ DBTxn_abort(DBTxnObject* self, PyObject* args)
static PyObject*
-DBTxn_id(DBTxnObject* self, PyObject* args)
+DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
{
- int id;
+ PyObject *dummy;
+ int err=0;
+ DB_TXN *txn;
- if (!PyArg_ParseTuple(args, ":id"))
+ if (!self->txn) {
+ PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
+ "after txn_commit, txn_abort "
+ "or txn_discard");
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
return NULL;
+ }
+ txn = self->txn;
+ self->txn = NULL; /* this DB_TXN is no longer valid after this call */
+
+ _close_transaction_cursors(self);
+#if (DBVER >= 43)
+ while (self->children_sequences) {
+ dummy=DBSequence_close_internal(self->children_sequences,0,0);
+ Py_XDECREF(dummy);
+ }
+#endif
+ while (self->children_dbs) {
+ dummy=DB_close_internal(self->children_dbs,0);
+ Py_XDECREF(dummy);
+ }
+
+ EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+ if (discard) {
+ assert(!self->flag_prepare);
+ err = txn->discard(txn,0);
+ } else {
+ /*
+ ** If the transaction is in the "prepare" or "recover" state,
+ ** we better do not implicitly abort it.
+ */
+ if (!self->flag_prepare) {
+ err = txn->abort(txn);
+ }
+ }
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ RETURN_NONE();
+}
+
+static PyObject*
+DBTxn_abort(DBTxnObject* self)
+{
+ self->flag_prepare=0;
+ _close_transaction_cursors(self);
+
+ return DBTxn_abort_discard_internal(self,0);
+}
+
+static PyObject*
+DBTxn_discard(DBTxnObject* self)
+{
+ self->flag_prepare=0;
+ _close_transaction_cursors(self);
+
+ return DBTxn_abort_discard_internal(self,1);
+}
+
+
+static PyObject*
+DBTxn_id(DBTxnObject* self)
+{
+ int id;
if (!self->txn) {
PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
- PyErr_SetObject(DBError, t);
- Py_DECREF(t);
+ "after txn_commit, txn_abort "
+ "or txn_discard");
+ if (t) {
+ PyErr_SetObject(DBError, t);
+ Py_DECREF(t);
+ }
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 PyLong_FromLong(id);
+ return NUMBER_FromLong(id);
}
#if (DBVER >= 43)
@@ -4849,24 +6017,41 @@ DBTxn_id(DBTxnObject* self, PyObject* args)
static PyObject*
-DBSequence_close(DBSequenceObject* self, PyObject* args)
+DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
{
- int err, flags=0;
- if (!PyArg_ParseTuple(args,"|i:close", &flags))
- return NULL;
- CHECK_SEQUENCE_NOT_CLOSED(self)
+ int err=0;
- MYDB_BEGIN_ALLOW_THREADS
- err = self->sequence->close(self->sequence, flags);
- self->sequence = NULL;
- MYDB_END_ALLOW_THREADS
+ if (self->sequence!=NULL) {
+ EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
+ if (self->txn) {
+ EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
+ self->txn=NULL;
+ }
- RETURN_IF_ERR();
+ if (!do_not_close) {
+ MYDB_BEGIN_ALLOW_THREADS
+ err = self->sequence->close(self->sequence, flags);
+ MYDB_END_ALLOW_THREADS
+ }
+ self->sequence = NULL;
+
+ RETURN_IF_ERR();
+ }
RETURN_NONE();
}
static PyObject*
+DBSequence_close(DBSequenceObject* self, PyObject* args)
+{
+ int flags=0;
+ if (!PyArg_ParseTuple(args,"|i:close", &flags))
+ return NULL;
+
+ return DBSequence_close_internal(self,flags,0);
+}
+
+static PyObject*
DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
{
int err, flags = 0;
@@ -4888,25 +6073,23 @@ DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
RETURN_IF_ERR();
return PyLong_FromLongLong(value);
-
}
static PyObject*
-DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
+DBSequence_get_dbp(DBSequenceObject* self)
{
- if (!PyArg_ParseTuple(args,":get_dbp"))
- return NULL;
CHECK_SEQUENCE_NOT_CLOSED(self)
Py_INCREF(self->mydb);
return (PyObject* )self->mydb;
}
static PyObject*
-DBSequence_get_key(DBSequenceObject* self, PyObject* args)
+DBSequence_get_key(DBSequenceObject* self)
{
int err;
DBT key;
PyObject *retval = NULL;
+
key.flags = DB_DBT_MALLOC;
CHECK_SEQUENCE_NOT_CLOSED(self)
MYDB_BEGIN_ALLOW_THREADS
@@ -4914,9 +6097,9 @@ DBSequence_get_key(DBSequenceObject* self, PyObject* args)
MYDB_END_ALLOW_THREADS
if (!err)
- retval = PyBytes_FromStringAndSize(key.data, key.size);
+ retval = Build_PyString(key.data, key.size);
- free_dbt(&key);
+ FREE_DBT(key);
RETURN_IF_ERR();
return retval;
@@ -4926,13 +6109,15 @@ static PyObject*
DBSequence_init_value(DBSequenceObject* self, PyObject* args)
{
int err;
- db_seq_t value;
+ PY_LONG_LONG value;
+ db_seq_t value2;
if (!PyArg_ParseTuple(args,"L:init_value", &value))
return NULL;
CHECK_SEQUENCE_NOT_CLOSED(self)
+ value2=value; /* If truncation, compiler should show a warning */
MYDB_BEGIN_ALLOW_THREADS
- err = self->sequence->initial_value(self->sequence, value);
+ err = self->sequence->initial_value(self->sequence, value2);
MYDB_END_ALLOW_THREADS
RETURN_IF_ERR();
@@ -4944,8 +6129,7 @@ static PyObject*
DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
{
int err, flags = 0;
- PyObject *keyobj;
- Py_buffer *key_buf_view = NULL;
+ PyObject* keyobj;
PyObject *txnobj = NULL;
DB_TXN *txn = NULL;
DBT key;
@@ -4957,22 +6141,28 @@ DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
if (!checkTxnObj(txnobj, &txn))
return NULL;
- if (!make_key_dbt(self->mydb, keyobj, &key, NULL, &key_buf_view))
+ if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
MYDB_BEGIN_ALLOW_THREADS
err = self->sequence->open(self->sequence, txn, &key, flags);
MYDB_END_ALLOW_THREADS
- FREE_DBT_VIEW(key, keyobj, key_buf_view);
+ CLEAR_DBT(key);
RETURN_IF_ERR();
+ if (txn) {
+ INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
+ self->txn=(DBTxnObject *)txnobj;
+ }
+
RETURN_NONE();
}
static PyObject*
DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
{
+ PyObject *dummy;
int err, flags = 0;
PyObject *txnobj = NULL;
DB_TXN *txn = NULL;
@@ -4990,6 +6180,9 @@ DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
err = self->sequence->remove(self->sequence, txn, flags);
MYDB_END_ALLOW_THREADS
+ dummy=DBSequence_close_internal(self,flags,1);
+ Py_XDECREF(dummy);
+
RETURN_IF_ERR();
RETURN_NONE();
}
@@ -5011,11 +6204,10 @@ DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
}
static PyObject*
-DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
+DBSequence_get_cachesize(DBSequenceObject* self)
{
int err, size;
- if (!PyArg_ParseTuple(args,":get_cachesize"))
- return NULL;
+
CHECK_SEQUENCE_NOT_CLOSED(self)
MYDB_BEGIN_ALLOW_THREADS
@@ -5023,7 +6215,7 @@ DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
MYDB_END_ALLOW_THREADS
RETURN_IF_ERR();
- return PyLong_FromLong(size);
+ return NUMBER_FromLong(size);
}
static PyObject*
@@ -5040,16 +6232,14 @@ DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
RETURN_IF_ERR();
RETURN_NONE();
-
}
static PyObject*
-DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
+DBSequence_get_flags(DBSequenceObject* self)
{
unsigned int flags;
int err;
- if (!PyArg_ParseTuple(args,":get_flags"))
- return NULL;
+
CHECK_SEQUENCE_NOT_CLOSED(self)
MYDB_BEGIN_ALLOW_THREADS
@@ -5057,20 +6247,23 @@ DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
MYDB_END_ALLOW_THREADS
RETURN_IF_ERR();
- return PyLong_FromLong((int)flags);
+ return NUMBER_FromLong((int)flags);
}
static PyObject*
DBSequence_set_range(DBSequenceObject* self, PyObject* args)
{
int err;
- db_seq_t min, max;
+ PY_LONG_LONG min, max;
+ db_seq_t min2, max2;
if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
return NULL;
CHECK_SEQUENCE_NOT_CLOSED(self)
+ min2=min; /* If truncation, compiler should show a warning */
+ max2=max;
MYDB_BEGIN_ALLOW_THREADS
- err = self->sequence->set_range(self->sequence, min, max);
+ err = self->sequence->set_range(self->sequence, min2, max2);
MYDB_END_ALLOW_THREADS
RETURN_IF_ERR();
@@ -5078,19 +6271,21 @@ DBSequence_set_range(DBSequenceObject* self, PyObject* args)
}
static PyObject*
-DBSequence_get_range(DBSequenceObject* self, PyObject* args)
+DBSequence_get_range(DBSequenceObject* self)
{
int err;
- db_seq_t min, max;
- if (!PyArg_ParseTuple(args,":get_range"))
- return NULL;
+ PY_LONG_LONG min, max;
+ db_seq_t min2, max2;
+
CHECK_SEQUENCE_NOT_CLOSED(self)
MYDB_BEGIN_ALLOW_THREADS
- err = self->sequence->get_range(self->sequence, &min, &max);
+ err = self->sequence->get_range(self->sequence, &min2, &max2);
MYDB_END_ALLOW_THREADS
RETURN_IF_ERR();
+ min=min2; /* If truncation, compiler should show a warning */
+ max=max2;
return Py_BuildValue("(LL)", min, max);
}
@@ -5142,27 +6337,23 @@ DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
/* Method definition tables and type objects */
static PyMethodDef DB_methods[] = {
- {"append", (PyCFunction)DB_append, METH_VARARGS},
-#if (DBVER >= 33)
+ {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
{"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
-#endif
{"close", (PyCFunction)DB_close, METH_VARARGS},
{"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
{"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
{"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
{"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
- {"fd", (PyCFunction)DB_fd, METH_VARARGS},
+ {"fd", (PyCFunction)DB_fd, METH_NOARGS},
{"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
-#if (DBVER >= 33)
{"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
-#endif
{"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
- {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
+ {"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_VARARGS},
+ {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
{"join", (PyCFunction)DB_join, METH_VARARGS},
{"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
- {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
+ {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
{"items", (PyCFunction)DB_items, METH_VARARGS},
{"keys", (PyCFunction)DB_keys, METH_VARARGS},
{"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
@@ -5170,9 +6361,7 @@ static PyMethodDef DB_methods[] = {
{"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
{"rename", (PyCFunction)DB_rename, METH_VARARGS},
{"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
-#if (DBVER >= 33)
- {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
-#endif
+ {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
{"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
#if (DBVER >= 41)
{"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
@@ -5186,13 +6375,13 @@ static PyMethodDef DB_methods[] = {
{"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
{"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
{"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
- {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
+ {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
+ {"set_private", (PyCFunction)DB_set_private, METH_O},
+ {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
{"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
{"sync", (PyCFunction)DB_sync, METH_VARARGS},
-#if (DBVER >= 33)
{"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
-#endif
- {"type", (PyCFunction)DB_get_type, METH_VARARGS},
+ {"type", (PyCFunction)DB_get_type, METH_NOARGS},
{"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
{"values", (PyCFunction)DB_values, METH_VARARGS},
{"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
@@ -5209,17 +6398,15 @@ static PyMappingMethods DB_mapping = {
static PyMethodDef DBCursor_methods[] = {
- {"close", (PyCFunction)DBC_close, METH_VARARGS},
+ {"close", (PyCFunction)DBC_close, METH_NOARGS},
{"count", (PyCFunction)DBC_count, METH_VARARGS},
{"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
{"delete", (PyCFunction)DBC_delete, METH_VARARGS},
{"dup", (PyCFunction)DBC_dup, METH_VARARGS},
{"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
{"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
-#if (DBVER >= 33)
{"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
-#endif
- {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
+ {"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},
@@ -5227,7 +6414,7 @@ static PyMethodDef DBCursor_methods[] = {
{"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},
- {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
+ {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
{"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
{"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
{"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
@@ -5248,19 +6435,21 @@ static PyMethodDef DBEnv_methods[] = {
{"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},
{"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
{"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
{"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
+#if (DBVER >= 47)
+ {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
+#endif
{"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
{"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
{"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
-#if (DBVER >= 33)
- {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
#endif
+ {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
{"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
#if (DBVER < 45)
{"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
@@ -5277,20 +6466,78 @@ static PyMethodDef DBEnv_methods[] = {
{"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
{"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
{"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
- {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
-#if (DBVER >= 40)
+ {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
{"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
-#endif
{"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
{"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
{"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
-#if (DBVER >= 40)
+ {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
{"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
-#endif
#if (DBVER >= 44)
{"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
#endif
{"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
+ {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
+ {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
+ METH_VARARGS||METH_KEYWORDS},
+ {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
+#endif
+ {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
+ {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
+ {"rep_start", (PyCFunction)DBEnv_rep_start,
+ METH_VARARGS|METH_KEYWORDS},
+ {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
+ {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
+ METH_VARARGS},
+#if (DBVER >= 46)
+ {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
+#endif
+#if (DBVER >= 44)
+ {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
+ {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
+ {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
+#endif
+#if (DBVER >= 45)
+ {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
+ {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
+#endif
+#if (DBVER >= 47)
+ {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
+ {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
+#endif
+#if (DBVER >= 45)
+ {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
+#endif
+#if (DBVER >= 45)
+ {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
+ {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
+ {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
+ {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
+ {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
+ {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
+#endif
+#if (DBVER >= 45)
+ {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
+ METH_VARARGS|METH_KEYWORDS},
+ {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
+ METH_VARARGS|METH_KEYWORDS},
+ {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
+ METH_VARARGS|METH_KEYWORDS},
+ {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
+ METH_VARARGS},
+ {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
+ METH_NOARGS},
+ {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
+ METH_NOARGS},
+#endif
+#if (DBVER >= 46)
+ {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
+ METH_VARARGS|METH_KEYWORDS},
+ {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
+ METH_VARARGS|METH_KEYWORDS},
+#endif
{NULL, NULL} /* sentinel */
};
@@ -5298,8 +6545,9 @@ static PyMethodDef DBEnv_methods[] = {
static PyMethodDef DBTxn_methods[] = {
{"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
{"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
- {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
- {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
+ {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
+ {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
+ {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
{NULL, NULL} /* sentinel */
};
@@ -5308,30 +6556,40 @@ static PyMethodDef DBTxn_methods[] = {
static PyMethodDef DBSequence_methods[] = {
{"close", (PyCFunction)DBSequence_close, METH_VARARGS},
{"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
- {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
- {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
+ {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
+ {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
{"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
{"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
{"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
{"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
- {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
+ {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
{"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
- {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
+ {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
{"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
- {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
+ {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
{"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
{NULL, NULL} /* sentinel */
};
#endif
+
static PyObject*
DBEnv_db_home_get(DBEnvObject* self)
{
+ const char *home = NULL;
+
CHECK_ENV_NOT_CLOSED(self);
- if (self->db_env->db_home == NULL) {
+
+#if (DBVER >= 42)
+ self->db_env->get_home(self->db_env, &home);
+#else
+ home=self->db_env->db_home;
+#endif
+
+ if (home == NULL) {
RETURN_NONE();
}
- return PyUnicode_FromString(self->db_env->db_home);
+ return PyBytes_FromString(home);
}
static PyGetSetDef DBEnv_getsets[] = {
@@ -5340,16 +6598,21 @@ static PyGetSetDef DBEnv_getsets[] = {
};
-static PyTypeObject DB_Type = {
+statichere PyTypeObject DB_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
PyVarObject_HEAD_INIT(NULL, 0)
+#endif
"DB", /*tp_name*/
sizeof(DBObject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)DB_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
@@ -5359,55 +6622,75 @@ static PyTypeObject DB_Type = {
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
- 0, /* tp_setattro */
+ 0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- DB_methods, /* tp_methods */
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DB_methods, /*tp_methods*/
+ 0, /*tp_members*/
};
-static PyTypeObject DBCursor_Type = {
+statichere PyTypeObject DBCursor_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
PyVarObject_HEAD_INIT(NULL, 0)
+#endif
"DBCursor", /*tp_name*/
sizeof(DBCursorObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
+ 0, /*tp_itemsize*/
/* methods */
(destructor)DBCursor_dealloc,/*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*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*/
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
+ 0, /*tp_print*/
+ 0, /*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*/
+ 0, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- DBCursor_methods, /* tp_methods */
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DBCursor_methods, /*tp_methods*/
+ 0, /*tp_members*/
};
-static PyTypeObject DBEnv_Type = {
+statichere PyTypeObject DBEnv_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
PyVarObject_HEAD_INIT(NULL, 0)
+#endif
"DBEnv", /*tp_name*/
sizeof(DBEnvObject), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -5425,23 +6708,32 @@ static PyTypeObject DBEnv_Type = {
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
- 0, /* tp_setattro */
+ 0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
DBEnv_methods, /* tp_methods */
- 0, /* tp_members */
+ 0, /* tp_members */
DBEnv_getsets, /* tp_getsets */
};
-static PyTypeObject DBTxn_Type = {
+statichere PyTypeObject DBTxn_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
PyVarObject_HEAD_INIT(NULL, 0)
+#endif
"DBTxn", /*tp_name*/
sizeof(DBTxnObject), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -5459,22 +6751,32 @@ static PyTypeObject DBTxn_Type = {
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
- 0, /* tp_setattro */
+ 0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- DBTxn_methods, /* tp_methods */
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DBTxn_methods, /*tp_methods*/
+ 0, /*tp_members*/
};
-static PyTypeObject DBLock_Type = {
+statichere PyTypeObject DBLock_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
PyVarObject_HEAD_INIT(NULL, 0)
+#endif
"DBLock", /*tp_name*/
sizeof(DBLockObject), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -5492,19 +6794,28 @@ static PyTypeObject DBLock_Type = {
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
- 0, /* tp_setattro */
+ 0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
};
#if (DBVER >= 43)
-static PyTypeObject DBSequence_Type = {
+statichere PyTypeObject DBSequence_Type = {
+#if (PY_VERSION_HEX < 0x03000000)
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+#else
PyVarObject_HEAD_INIT(NULL, 0)
+#endif
"DBSequence", /*tp_name*/
sizeof(DBSequenceObject), /*tp_basicsize*/
0, /*tp_itemsize*/
@@ -5524,15 +6835,20 @@ static PyTypeObject DBSequence_Type = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
+#if (PY_VERSION_HEX < 0x03000000)
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+#else
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+#endif
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- DBSequence_methods, /* tp_methods */
+ 0, /*tp_iter*/
+ 0, /*tp_iternext*/
+ DBSequence_methods, /*tp_methods*/
+ 0, /*tp_members*/
};
#endif
@@ -5591,29 +6907,27 @@ static char bsddb_version_doc[] =
underlying DB library.";
static PyObject*
-bsddb_version(PyObject* self, PyObject* args)
+bsddb_version(PyObject* self)
{
int major, minor, patch;
- if (!PyArg_ParseTuple(args, ":version"))
- return NULL;
- db_version(&major, &minor, &patch);
- return Py_BuildValue("(iii)", 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},
-#if (DBVER >= 43)
+#if (DBVER >= 43)
{"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
-#endif
- {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
+#endif
+ {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
{NULL, NULL} /* sentinel */
};
+
/* API structure */
static BSDDB_api bsddb_api;
@@ -5630,44 +6944,51 @@ static BSDDB_api bsddb_api;
#define MODULE_NAME_MAX_LEN 11
static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
-
-static struct PyModuleDef _bsddbmodule = {
- PyModuleDef_HEAD_INIT,
- _bsddbModuleName,
- NULL,
- -1,
- bsddb_methods,
- NULL,
- NULL,
- NULL,
- NULL
+#if (PY_VERSION_HEX >= 0x03000000)
+static struct PyModuleDef bsddbmodule = {
+ PyModuleDef_HEAD_INIT,
+ _bsddbModuleName, /* Name of module */
+ NULL, /* module documentation, may be NULL */
+ -1, /* size of per-interpreter state of the module,
+ or -1 if the module keeps state in global variables. */
+ bsddb_methods,
+ NULL, /* Reload */
+ NULL, /* Traverse */
+ NULL, /* Clear */
+ NULL /* Free */
};
+#endif
-PyMODINIT_FUNC PyInit__bsddb(void)
+
+#if (PY_VERSION_HEX < 0x03000000)
+DL_EXPORT(void) init_bsddb(void)
+#else
+PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
+#endif
{
PyObject* m;
PyObject* d;
- PyObject* pybsddb_version_s = PyUnicode_FromString(PY_BSDDB_VERSION);
- PyObject* db_version_s = PyUnicode_FromString(DB_VERSION_STRING);
- PyObject* svnid_s = PyUnicode_FromString(svn_id);
+ PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
+ PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
+ PyObject* cvsid_s = PyBytes_FromString( rcs_id );
PyObject* py_api;
/* Initialize object types */
- if (PyType_Ready(&DB_Type) < 0)
- return NULL;
- if (PyType_Ready(&DBCursor_Type) < 0)
- return NULL;
- if (PyType_Ready(&DBEnv_Type) < 0)
- return NULL;
- if (PyType_Ready(&DBTxn_Type) < 0)
- return NULL;
- if (PyType_Ready(&DBLock_Type) < 0)
- return NULL;
+ if ((PyType_Ready(&DB_Type) < 0)
+ || (PyType_Ready(&DBCursor_Type) < 0)
+ || (PyType_Ready(&DBEnv_Type) < 0)
+ || (PyType_Ready(&DBTxn_Type) < 0)
+ || (PyType_Ready(&DBLock_Type) < 0)
#if (DBVER >= 43)
- if (PyType_Ready(&DBSequence_Type) < 0)
+ || (PyType_Ready(&DBSequence_Type) < 0)
+#endif
+ ) {
+#if (PY_VERSION_HEX < 0x03000000)
+ return;
+#else
return NULL;
#endif
-
+ }
#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
/* Save the current interpreter, so callbacks can do the right thing. */
@@ -5675,19 +6996,28 @@ PyMODINIT_FUNC PyInit__bsddb(void)
#endif
/* Create the module and add the functions */
- m = PyModule_Create(&_bsddbmodule);
- if (m == NULL)
+#if (PY_VERSION_HEX < 0x03000000)
+ m = Py_InitModule(_bsddbModuleName, bsddb_methods);
+#else
+ m=PyModule_Create(&bsddbmodule);
+#endif
+ if (m == NULL) {
+#if (PY_VERSION_HEX < 0x03000000)
+ return;
+#else
return NULL;
+#endif
+ }
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
PyDict_SetItemString(d, "__version__", pybsddb_version_s);
- PyDict_SetItemString(d, "cvsid", svnid_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(svnid_s);
- svnid_s = NULL;
+ Py_DECREF(cvsid_s);
+ cvsid_s = NULL;
Py_DECREF(db_version_s);
db_version_s = NULL;
@@ -5702,7 +7032,7 @@ PyMODINIT_FUNC PyInit__bsddb(void)
ADD_INT(d, DB_RPCCLIENT);
#else
ADD_INT(d, DB_CLIENT);
- /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
+ /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
_addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
#endif
ADD_INT(d, DB_XA_CREATE);
@@ -5710,6 +7040,9 @@ PyMODINIT_FUNC PyInit__bsddb(void)
ADD_INT(d, DB_CREATE);
ADD_INT(d, DB_NOMMAP);
ADD_INT(d, DB_THREAD);
+#if (DBVER >= 45)
+ ADD_INT(d, DB_MULTIVERSION);
+#endif
ADD_INT(d, DB_FORCE);
ADD_INT(d, DB_INIT_CDB);
@@ -5719,6 +7052,8 @@ PyMODINIT_FUNC PyInit__bsddb(void)
ADD_INT(d, DB_INIT_TXN);
ADD_INT(d, DB_JOINENV);
+ ADD_INT(d, DB_XIDDATASIZE);
+
ADD_INT(d, DB_RECOVER);
ADD_INT(d, DB_RECOVER_FATAL);
ADD_INT(d, DB_TXN_NOSYNC);
@@ -5747,10 +7082,7 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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);
@@ -5759,19 +7091,16 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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
+ ADD_INT(d, DB_LOCK_EXPIRE);
+#if (DBVER >= 43)
+ ADD_INT(d, DB_LOCK_MAXWRITE);
+#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);
@@ -5788,39 +7117,31 @@ PyMODINIT_FUNC PyInit__bsddb(void)
ADD_INT(d, DB_LOCK_IWRITE);
ADD_INT(d, DB_LOCK_IREAD);
ADD_INT(d, DB_LOCK_IWR);
-#if (DBVER >= 33)
#if (DBVER < 44)
ADD_INT(d, DB_LOCK_DIRTY);
#else
ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
#endif
ADD_INT(d, DB_LOCK_WWRITE);
-#endif
ADD_INT(d, DB_LOCK_RECORD);
ADD_INT(d, DB_LOCK_UPGRADE);
ADD_INT(d, DB_LOCK_SWITCH);
-#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);
@@ -5850,21 +7171,20 @@ PyMODINIT_FUNC PyInit__bsddb(void)
#if (DBVER < 45)
ADD_INT(d, DB_CACHED_COUNTS);
#endif
+
#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))
+#if (DBVER <= 41)
ADD_INT(d, DB_COMMIT);
#endif
ADD_INT(d, DB_CONSUME);
ADD_INT(d, DB_CONSUME_WAIT);
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);
@@ -5892,21 +7212,16 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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 >= 44)
ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
ADD_INT(d, DB_READ_COMMITTED);
#endif
-#if (DBVER >= 33)
ADD_INT(d, DB_DONOTINDEX);
- ADD_INT(d, DB_XIDDATASIZE);
-#endif
#if (DBVER >= 41)
_addIntToDict(d, "DB_INCOMPLETE", 0);
@@ -5924,17 +7239,17 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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);
+
+#if (DBVER >= 41)
+ ADD_INT(d, DB_OVERWRITE);
#endif
#ifdef DB_REGISTER
@@ -5945,27 +7260,118 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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 >= 42) && (DBVER < 47)
+ ADD_INT(d, DB_LOG_AUTOREMOVE);
+ ADD_INT(d, DB_DIRECT_LOG);
+#endif
+
+#if (DBVER >= 47)
+ ADD_INT(d, DB_LOG_DIRECT);
+ ADD_INT(d, DB_LOG_DSYNC);
+ ADD_INT(d, DB_LOG_IN_MEMORY);
+ ADD_INT(d, DB_LOG_AUTO_REMOVE);
+ ADD_INT(d, DB_LOG_ZERO);
+#endif
+
+#if (DBVER >= 44)
+ ADD_INT(d, DB_DSYNC_DB);
+#endif
+
+#if (DBVER >= 45)
+ ADD_INT(d, DB_TXN_SNAPSHOT);
+#endif
+
+ ADD_INT(d, DB_VERB_DEADLOCK);
+#if (DBVER >= 46)
+ ADD_INT(d, DB_VERB_FILEOPS);
+ ADD_INT(d, DB_VERB_FILEOPS_ALL);
+#endif
+ ADD_INT(d, DB_VERB_RECOVERY);
+#if (DBVER >= 44)
+ ADD_INT(d, DB_VERB_REGISTER);
+#endif
+ ADD_INT(d, DB_VERB_REPLICATION);
+ ADD_INT(d, DB_VERB_WAITSFOR);
+
+#if (DBVER >= 45)
+ ADD_INT(d, DB_EVENT_PANIC);
+ ADD_INT(d, DB_EVENT_REP_CLIENT);
+#if (DBVER >= 46)
+ ADD_INT(d, DB_EVENT_REP_ELECTED);
+#endif
+ ADD_INT(d, DB_EVENT_REP_MASTER);
+ ADD_INT(d, DB_EVENT_REP_NEWMASTER);
+#if (DBVER >= 46)
+ ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
+#endif
+ ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
+ ADD_INT(d, DB_EVENT_WRITE_FAILED);
+#endif
+
+ ADD_INT(d, DB_REP_DUPMASTER);
+ ADD_INT(d, DB_REP_HOLDELECTION);
+#if (DBVER >= 44)
+ ADD_INT(d, DB_REP_IGNORE);
+ ADD_INT(d, DB_REP_JOIN_FAILURE);
+#endif
+#if (DBVER >= 42)
+ ADD_INT(d, DB_REP_ISPERM);
+ ADD_INT(d, DB_REP_NOTPERM);
+#endif
+ ADD_INT(d, DB_REP_NEWSITE);
+
+ ADD_INT(d, DB_REP_MASTER);
+ ADD_INT(d, DB_REP_CLIENT);
+#if (DBVER >= 45)
+ ADD_INT(d, DB_REP_ELECTION);
+
+ ADD_INT(d, DB_REP_ACK_TIMEOUT);
+ ADD_INT(d, DB_REP_CONNECTION_RETRY);
+ ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
+ ADD_INT(d, DB_REP_ELECTION_RETRY);
+#endif
+#if (DBVER >= 46)
+ ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
+ ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
+#endif
+
+#if (DBVER >= 45)
+ ADD_INT(d, DB_REPMGR_PEER);
+ ADD_INT(d, DB_REPMGR_ACKS_ALL);
+ ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
+ ADD_INT(d, DB_REPMGR_ACKS_NONE);
+ ADD_INT(d, DB_REPMGR_ACKS_ONE);
+ ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
+ ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
+ ADD_INT(d, DB_REPMGR_CONNECTED);
+ ADD_INT(d, DB_REPMGR_DISCONNECTED);
+ ADD_INT(d, DB_STAT_CLEAR);
+ ADD_INT(d, DB_STAT_ALL);
+#endif
+
#if (DBVER >= 43)
- ADD_INT(d, DB_LOG_INMEMORY);
ADD_INT(d, DB_BUFFER_SMALL);
ADD_INT(d, DB_SEQ_DEC);
ADD_INT(d, DB_SEQ_INC);
ADD_INT(d, DB_SEQ_WRAP);
#endif
+#if (DBVER >= 43) && (DBVER < 47)
+ ADD_INT(d, DB_LOG_INMEMORY);
+ ADD_INT(d, DB_DSYNC_LOG);
+#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 */
+ /* allow Berkeley DB 4.1 aware apps to run on older versions */
_addIntToDict(d, "DB_AUTO_COMMIT", 0);
#endif
@@ -5979,10 +7385,8 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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 exception name must be correct for pickled exception *
* objects to unpickle properly. */
@@ -6000,20 +7404,37 @@ PyMODINIT_FUNC PyInit__bsddb(void)
DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
MAKE_EX(DBError);
+#if (PY_VERSION_HEX < 0x03000000)
/* Some magic to make DBNotFoundError and DBKeyEmptyError derive
* from both DBError and KeyError, since the API only supports
* using one base class. */
PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
- {
- PyObject *builtin_mod = PyImport_ImportModule("builtins");
- PyDict_SetItemString(d, "__builtins__", builtin_mod);
- }
PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
"class DBKeyEmptyError(DBError, KeyError): pass",
Py_file_input, d, d);
DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
PyDict_DelItemString(d, "KeyError");
+#else
+ /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
+ ** derive from several classes. We use this new API only for Python 3.0,
+ ** though.
+ */
+ {
+ PyObject* bases;
+
+ bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
+
+#define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
+ PyDict_SetItemString(d, #name, name)
+ MAKE_EX2(DBNotFoundError);
+ MAKE_EX2(DBKeyEmptyError);
+
+#undef MAKE_EX2
+
+ Py_XDECREF(bases);
+ }
+#endif
#if !INCOMPLETE_IS_WARNING
@@ -6030,10 +7451,8 @@ PyMODINIT_FUNC PyInit__bsddb(void)
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);
@@ -6045,6 +7464,12 @@ PyMODINIT_FUNC PyInit__bsddb(void)
MAKE_EX(DBNoSuchFileError);
MAKE_EX(DBPermissionsError);
+#if (DBVER >= 42)
+ MAKE_EX(DBRepHandleDeadError);
+#endif
+
+ MAKE_EX(DBRepUnavailError);
+
#undef MAKE_EX
/* Initiliase the C API structure and add it to the module */
@@ -6065,18 +7490,31 @@ PyMODINIT_FUNC PyInit__bsddb(void)
/* Check for errors */
if (PyErr_Occurred()) {
PyErr_Print();
- Py_FatalError("can't initialize module _bsddb");
- Py_DECREF(m);
- m = NULL;
+ Py_FatalError("can't initialize module _bsddb/_pybsddb");
+ Py_DECREF(m);
+ m = NULL;
}
+#if (PY_VERSION_HEX < 0x03000000)
+ return;
+#else
return m;
+#endif
}
/* 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. */
-PyMODINIT_FUNC init_pybsddb(void)
+#if (PY_VERSION_HEX < 0x03000000)
+DL_EXPORT(void) init_pybsddb(void)
+#else
+PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
+#endif
{
strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
- return PyInit__bsddb();
+#if (PY_VERSION_HEX < 0x03000000)
+ init_bsddb();
+#else
+ return PyInit__bsddb(); /* Note the two underscores */
+#endif
}
+
diff --git a/Modules/bsddb.h b/Modules/bsddb.h
index 65c2bea..41f1db9 100644
--- a/Modules/bsddb.h
+++ b/Modules/bsddb.h
@@ -36,7 +36,7 @@
/*
* 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.
+ * to compile with Berkeley DB 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 who based his work on a
@@ -105,7 +105,7 @@
#error "eek! DBVER can't handle minor versions > 9"
#endif
-#define PY_BSDDB_VERSION "4.6.0"
+#define PY_BSDDB_VERSION "4.7.3pre2"
/* Python object definitions */
@@ -119,17 +119,27 @@ struct behaviourFlags {
};
+
+struct DBObject; /* Forward declaration */
+struct DBCursorObject; /* Forward declaration */
+struct DBTxnObject; /* Forward declaration */
+struct DBSequenceObject; /* Forward declaration */
+
typedef struct {
PyObject_HEAD
DB_ENV* db_env;
u_int32_t flags; /* saved flags from open() */
int closed;
struct behaviourFlags moduleFlags;
+ PyObject* event_notifyCallback;
+ struct DBObject *children_dbs;
+ struct DBTxnObject *children_txns;
+ PyObject *private_obj;
+ PyObject *rep_transport;
PyObject *in_weakreflist; /* List of weak references */
} DBEnvObject;
-
-typedef struct {
+typedef struct DBObject {
PyObject_HEAD
DB* db;
DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
@@ -137,27 +147,48 @@ typedef struct {
u_int32_t setflags; /* saved flags from set_flags() */
int haveStat;
struct behaviourFlags moduleFlags;
-#if (DBVER >= 33)
+ struct DBTxnObject *txn;
+ struct DBCursorObject *children_cursors;
+#if (DBVER >=43)
+ struct DBSequenceObject *children_sequences;
+#endif
+ struct DBObject **sibling_prev_p;
+ struct DBObject *sibling_next;
+ struct DBObject **sibling_prev_p_txn;
+ struct DBObject *sibling_next_txn;
PyObject* associateCallback;
PyObject* btCompareCallback;
int primaryDBType;
-#endif
+ PyObject *private_obj;
PyObject *in_weakreflist; /* List of weak references */
} DBObject;
-typedef struct {
+typedef struct DBCursorObject {
PyObject_HEAD
DBC* dbc;
+ struct DBCursorObject **sibling_prev_p;
+ struct DBCursorObject *sibling_next;
+ struct DBCursorObject **sibling_prev_p_txn;
+ struct DBCursorObject *sibling_next_txn;
DBObject* mydb;
+ struct DBTxnObject *txn;
PyObject *in_weakreflist; /* List of weak references */
} DBCursorObject;
-typedef struct {
+typedef struct DBTxnObject {
PyObject_HEAD
DB_TXN* txn;
- PyObject *env;
+ DBEnvObject* env;
+ int flag_prepare;
+ struct DBTxnObject *parent_txn;
+ struct DBTxnObject **sibling_prev_p;
+ struct DBTxnObject *sibling_next;
+ struct DBTxnObject *children_txns;
+ struct DBObject *children_dbs;
+ struct DBSequenceObject *children_sequences;
+ struct DBCursorObject *children_cursors;
PyObject *in_weakreflist; /* List of weak references */
} DBTxnObject;
@@ -170,13 +201,17 @@ typedef struct {
#if (DBVER >= 43)
-typedef struct {
+typedef struct DBSequenceObject {
PyObject_HEAD
DB_SEQUENCE* sequence;
DBObject* mydb;
+ struct DBTxnObject *txn;
+ struct DBSequenceObject **sibling_prev_p;
+ struct DBSequenceObject *sibling_next;
+ struct DBSequenceObject **sibling_prev_p_txn;
+ struct DBSequenceObject *sibling_next_txn;
PyObject *in_weakreflist; /* List of weak references */
} DBSequenceObject;
-static PyTypeObject DBSequence_Type;
#endif