Python-checkins
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
May 2008
- 33 participants
- 1478 discussions
21 Jul '08
Author: jesus.cea
Date: Tue May 13 20:45:46 2008
New Revision: 63207
Log:
bsddb module updated to version 4.6.4
Modified:
python/trunk/Misc/NEWS
python/trunk/Modules/_bsddb.c
python/trunk/Modules/bsddb.h
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Tue May 13 20:45:46 2008
@@ -25,6 +25,8 @@
- Support for Windows9x has been removed from the winsound module.
+- bsddb module updated to version 4.6.4.
+
Library
-------
Modified: python/trunk/Modules/_bsddb.c
==============================================================================
--- python/trunk/Modules/_bsddb.c (original)
+++ python/trunk/Modules/_bsddb.c Tue May 13 20:45:46 2008
@@ -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(a)krypto.org> is once again the maintainer.
+ * Gregory P. Smith <greg(a)krypto.org> was once again the maintainer.
+ *
+ * Since January 2008, new maintainer is Jesus Cea <jcea(a)argo.es>.
+ * Jesus Cea licenses this code to PSF under a Contributor Agreement.
*
* Use the pybsddb-users(a)lists.sf.net mailing list for all questions.
* Things can change faster than the header of this file is updated. This
@@ -183,6 +186,10 @@
static PyObject* DBNoSuchFileError; /* ENOENT */
static PyObject* DBPermissionsError; /* EPERM */
+#if (DBVER >= 42)
+static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
+#endif
+
#if (DBVER < 43)
#define DB_BUFFER_SMALL ENOMEM
#endif
@@ -202,6 +209,9 @@
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 */
@@ -217,10 +227,77 @@
#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; \
@@ -443,6 +520,66 @@
}
+/*
+** 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 PyString_FromStringAndSize(p,s);
+}
+
+static PyObject *BuildValue_S(const void *p,int s)
+{
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+ return Py_BuildValue("s#",p,s);
+}
+
+static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
+{
+ if (!p1) {
+ p1=DummyString;
+ assert(s1==0);
+ }
+ if (!p2) {
+ p2=DummyString;
+ assert(s2==0);
+ }
+ return Py_BuildValue("s#s#",p1,s1,p2,s2);
+}
+
+static PyObject *BuildValue_IS(int i,const void *p,int s)
+{
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+ return Py_BuildValue("is#",i,p,s);
+}
+
+static PyObject *BuildValue_LS(long i,const void *p,int s)
+{
+ if (!p) {
+ p=DummyString;
+ assert(s==0);
+ }
+ return Py_BuildValue("ls#",i,p,s);
+}
+
+
+
/* make a nice exception object to raise for errors. */
static int makeDBError(int err)
{
@@ -505,6 +642,10 @@
case ENOENT: errObj = DBNoSuchFileError; break;
case EPERM : errObj = DBPermissionsError; break;
+#if (DBVER >= 42)
+ case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
+#endif
+
default: errObj = DBError; break;
}
@@ -608,16 +749,11 @@
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)
@@ -638,21 +774,15 @@
case DB_RECNO:
case DB_QUEUE:
- retval = Py_BuildValue("is#", *((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("s#s#", 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;
}
@@ -672,7 +802,7 @@
{
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
@@ -696,7 +826,16 @@
}
#endif
+#if (DBVER >= 40)
+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);
+}
+#endif
/* --------------------------------------------------------------------- */
/* Allocators and deallocators */
@@ -716,6 +855,10 @@
self->flags = 0;
self->setflags = 0;
self->myenvobj = NULL;
+ self->children_cursors = NULL;
+#if (DBVER >=43)
+ self->children_sequences = NULL;
+#endif
#if (DBVER >= 33)
self->associateCallback = NULL;
self->btCompareCallback = NULL;
@@ -728,7 +871,14 @@
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;
@@ -760,23 +910,17 @@
}
+/* 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_Warn(PyExc_RuntimeWarning,
- "DB could not be closed in destructor: DBEnv already closed");
- }
- self->db = NULL;
+ dummy=DB_close_internal(self,0);
+ Py_XDECREF(dummy);
}
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
@@ -798,9 +942,8 @@
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)
@@ -808,40 +951,37 @@
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);
}
@@ -858,8 +998,14 @@
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;
self->in_weakreflist = NULL;
+#if (DBVER >= 40)
+ self->event_notifyCallback = NULL;
+#endif
+
MYDB_BEGIN_ALLOW_THREADS;
err = db_env_create(&self->db_env, flags);
MYDB_END_ALLOW_THREADS;
@@ -869,75 +1015,119 @@
}
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)
{
+ PyObject *dummy;
+
+ if (self->db_env && !self->closed) {
+ dummy=DBEnv_close_internal(self,0);
+ Py_XDECREF(dummy);
+ }
+
+#if (DBVER >= 40)
+ Py_XDECREF(self->event_notifyCallback);
+ self->event_notifyCallback = NULL;
+#endif
+
if (self->in_weakreflist != NULL) {
PyObject_ClearWeakRefs((PyObject *) self);
}
- if (self->db_env && !self->closed) {
- MYDB_BEGIN_ALLOW_THREADS;
- self->db_env->close(self->db_env, 0);
- MYDB_END_ALLOW_THREADS;
- }
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;
- MYDB_BEGIN_ALLOW_THREADS;
+ if (parent && ((PyObject *)parent!=Py_None)) {
+ parent_txn=parent->txn;
+ }
+
+ if (txn) {
+ self->txn=txn;
+ } else {
+ MYDB_BEGIN_ALLOW_THREADS;
#if (DBVER >= 40)
- err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
+ err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
#else
- err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
+ err = txn_begin(myenv->db_env, parent->txn, &(self_txn), flags);
#endif
- MYDB_END_ALLOW_THREADS;
- if (makeDBError(err)) {
- Py_DECREF(self->env);
- PyObject_Del(self);
- self = NULL;
+ MYDB_END_ALLOW_THREADS;
+
+ if (makeDBError(err)) {
+ PyObject_Del(self);
+ return NULL;
+ }
}
+
+ if (parent_txn) { /* Can't use 'parent' because could be 'parent==Py_None' */
+ 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);
+ }
+
+ self->children_txns=NULL;
+ self->children_dbs=NULL;
+ self->children_cursors=NULL;
+ self->children_sequences=NULL;
+ self->flag_prepare=0;
+
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_Warn(PyExc_RuntimeWarning,
- "DBTxn aborted in destructor. No prior commit() or abort().");
+ if (self->env) {
+ Py_DECREF(self->env);
+ } else {
+ Py_DECREF(self->parent_txn);
}
-
- Py_DECREF(self->env);
PyObject_Del(self);
}
@@ -991,8 +1181,11 @@
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);
@@ -1006,10 +1199,20 @@
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);
}
@@ -1072,11 +1275,9 @@
MYDB_BEGIN_BLOCK_THREADS;
if (type == DB_RECNO || type == DB_QUEUE)
- args = Py_BuildValue("(ls#)", *((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("(s#s#)", 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);
}
@@ -1217,21 +1418,49 @@
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)
@@ -1262,7 +1491,7 @@
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;
}
@@ -1278,8 +1507,7 @@
retval = Py_None;
}
else if (!err) {
- retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
- data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
FREE_DBT(key);
FREE_DBT(data);
}
@@ -1322,7 +1550,7 @@
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);
}
@@ -1404,7 +1632,7 @@
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)) {
@@ -1429,10 +1657,9 @@
}
else if (!err) {
if (flags & DB_SET_RECNO) /* return both key and data */
- retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
- data.size);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
else /* return just the data */
- retval = PyString_FromStringAndSize((char*)data.data, data.size);
+ retval = Build_PyString(data.data, data.size);
FREE_DBT(data);
}
FREE_DBT(key);
@@ -1472,7 +1699,7 @@
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)) {
@@ -1501,13 +1728,13 @@
else if (!err) {
PyObject *pkeyObj;
PyObject *dataObj;
- dataObj = PyString_FromStringAndSize(data.data, data.size);
+ dataObj = Build_PyString(data.data, data.size);
if (self->primaryDBType == DB_RECNO ||
self->primaryDBType == DB_QUEUE)
pkeyObj = PyInt_FromLong(*(int *)pkey.data);
else
- pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
+ pkeyObj = Build_PyString(pkey.data, pkey.size);
if (flags & DB_SET_RECNO) /* return key , pkey and data */
{
@@ -1516,7 +1743,7 @@
if (type == DB_RECNO || type == DB_QUEUE)
keyObj = PyInt_FromLong(*(int *)key.data);
else
- keyObj = PyString_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
@@ -1620,7 +1847,7 @@
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;
}
@@ -1637,7 +1864,7 @@
}
else if (!err) {
/* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
- retval = PyString_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. :-( */
@@ -1748,7 +1975,7 @@
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);
}
@@ -1845,6 +2072,17 @@
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);
@@ -1853,8 +2091,10 @@
#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;
}
@@ -1863,6 +2103,7 @@
#endif
self->flags = flags;
+
RETURN_NONE();
}
@@ -1993,7 +2234,7 @@
}
static int
-_db_compareCallback(DB* db,
+_db_compareCallback(DB* db,
const DBT *leftKey,
const DBT *rightKey)
{
@@ -2015,8 +2256,7 @@
} else {
MYDB_BEGIN_BLOCK_THREADS;
- args = Py_BuildValue("s#s#", 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);
@@ -2369,6 +2609,9 @@
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);
@@ -2391,6 +2634,9 @@
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);
@@ -2400,6 +2646,9 @@
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);
@@ -2413,6 +2662,9 @@
MAKE_QUEUE_ENTRY(nkeys);
MAKE_QUEUE_ENTRY(ndata);
MAKE_QUEUE_ENTRY(pagesize);
+#if (DBVER > 40)
+ MAKE_QUEUE_ENTRY(extentsize);
+#endif
MAKE_QUEUE_ENTRY(pages);
MAKE_QUEUE_ENTRY(re_len);
MAKE_QUEUE_ENTRY(re_pad);
@@ -2527,15 +2779,14 @@
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();
@@ -2622,7 +2873,7 @@
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
*/
@@ -2658,7 +2909,7 @@
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;
@@ -2672,7 +2923,7 @@
retval = NULL;
}
else {
- retval = PyString_FromStringAndSize((char*)data.data, data.size);
+ retval = Build_PyString(data.data, data.size);
FREE_DBT(data);
}
@@ -2802,14 +3053,9 @@
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) {
@@ -2823,7 +3069,7 @@
case DB_BTREE:
case DB_HASH:
default:
- item = PyString_FromStringAndSize((char*)key.data, key.size);
+ item = Build_PyString(key.data, key.size);
break;
case DB_RECNO:
case DB_QUEUE:
@@ -2833,7 +3079,7 @@
break;
case _VALUES_LIST:
- item = PyString_FromStringAndSize((char*)data.data, data.size);
+ item = Build_PyString(data.data, data.size);
break;
case _ITEMS_LIST:
@@ -2841,13 +3087,11 @@
case DB_BTREE:
case DB_HASH:
default:
- item = Py_BuildValue("s#s#", 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("is#", *((db_recno_t*)key.data),
- data.data, data.size);
+ item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
break;
}
break;
@@ -2872,10 +3116,8 @@
}
done:
- FREE_DBT(key);
- FREE_DBT(data);
MYDB_BEGIN_ALLOW_THREADS;
- cursor->c_close(cursor);
+ _DBC_close(cursor);
MYDB_END_ALLOW_THREADS;
return list;
}
@@ -2927,23 +3169,35 @@
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, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":close"))
+ return NULL;
+
+ return DBC_close_internal(self);
+}
+
static PyObject*
DBC_count(DBCursorObject* self, PyObject* args)
@@ -2958,7 +3212,7 @@
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();
@@ -2984,7 +3238,7 @@
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();
@@ -3005,11 +3259,11 @@
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*
@@ -3059,19 +3313,12 @@
if ( (dataobj && !make_dbt(dataobj, &data)) ||
(!add_partial_dbt(&data, dlen, doff)) )
{
- FREE_DBT(key);
+ 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)
@@ -3090,18 +3337,15 @@
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("s#s#", 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("is#", *((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' */
return retval;
}
@@ -3145,22 +3389,15 @@
return NULL;
if ( (dataobj && !make_dbt(dataobj, &data)) ||
(!add_partial_dbt(&data, dlen, doff)) ) {
- FREE_DBT(key);
+ 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)
@@ -3174,13 +3411,13 @@
else {
PyObject *pkeyObj;
PyObject *dataObj;
- dataObj = PyString_FromStringAndSize(data.data, data.size);
+ dataObj = Build_PyString(data.data, data.size);
if (self->mydb->primaryDBType == DB_RECNO ||
self->mydb->primaryDBType == DB_QUEUE)
pkeyObj = PyInt_FromLong(*(int *)pkey.data);
else
- pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
+ pkeyObj = Build_PyString(pkey.data, pkey.size);
if (key.data && key.size) /* return key, pkey and data */
{
@@ -3189,14 +3426,14 @@
if (type == DB_RECNO || type == DB_QUEUE)
keyObj = PyInt_FromLong(*(int *)key.data);
else
- keyObj = PyString_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);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
}
else /* return just the pkey and data */
{
@@ -3209,11 +3446,10 @@
Py_DECREF(dataObj);
Py_DECREF(pkeyObj);
FREE_DBT(pkey);
- FREE_DBT(data);
}
/* 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) {
+ if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
FREE_DBT(key);
}
return retval;
@@ -3236,20 +3472,13 @@
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 PyInt_FromLong(recno);
}
@@ -3297,14 +3526,14 @@
if (!make_dbt(dataobj, &data) ||
!add_partial_dbt(&data, dlen, doff) )
{
- FREE_DBT(key);
+ 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(key);
+ FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
RETURN_IF_ERR();
self->mydb->haveStat = 0;
RETURN_NONE();
@@ -3331,17 +3560,13 @@
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(key);
+ 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) {
@@ -3359,22 +3584,19 @@
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("s#s#", 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("is#", *((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' */
}
return retval;
@@ -3402,19 +3624,11 @@
CLEAR_DBT(data);
if (!add_partial_dbt(&data, dlen, doff)) {
- FREE_DBT(key);
+ 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) {
@@ -3432,22 +3646,19 @@
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("s#s#", 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("is#", *((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' */
}
return retval;
@@ -3465,12 +3676,12 @@
if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
return NULL;
if (!make_dbt(dataobj, &data)) {
- FREE_DBT(key);
+ 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);
@@ -3487,18 +3698,16 @@
case DB_BTREE:
case DB_HASH:
default:
- retval = Py_BuildValue("s#s#", 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("is#", *((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(key); /* 'make_key_dbt' could do a 'malloc' */
return retval;
}
@@ -3537,7 +3746,7 @@
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 */
@@ -3545,8 +3754,6 @@
err = 0;
}
- FREE_DBT(key);
- FREE_DBT(data);
RETURN_IF_ERR();
return retval;
}
@@ -3600,17 +3807,13 @@
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);
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) {
@@ -3621,9 +3824,7 @@
retval = NULL;
}
else { /* Can only be used for BTrees, so no need to return int key */
- retval = Py_BuildValue("s#s#", key.data, key.size,
- data.data, data.size);
- FREE_DBT(data);
+ retval = BuildValue_SS(key.data, key.size, data.data, data.size);
}
FREE_DBT(key);
@@ -3673,13 +3874,9 @@
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) {
@@ -3690,8 +3887,7 @@
retval = NULL;
}
else {
- retval = Py_BuildValue("s#", key.data, key.size);
- FREE_DBT(key);
+ retval = BuildValue_S(key.data, key.size);
}
return retval;
@@ -3704,18 +3900,26 @@
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();
@@ -3723,6 +3927,16 @@
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)
@@ -3982,8 +4196,27 @@
RETURN_NONE();
}
-
-#if (DBVER >= 33)
+#if (DBVER >= 42)
+static PyObject*
+DBEnv_get_lg_max(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ u_int32_t lg_max;
+
+ if (!PyArg_ParseTuple(args, ":get_lg_max"))
+ return NULL;
+ 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 PyInt_FromLong(lg_max);
+}
+#endif
+
+
+#if (DBVER >= 33)
static PyObject*
DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
{
@@ -4125,6 +4358,84 @@
}
+#if (DBVER >= 40)
+static PyObject*
+DBEnv_txn_recover(DBEnvObject* self, PyObject* args)
+{
+ int flags = DB_FIRST;
+ int err, i;
+ PyObject *list, *tuple, *gid;
+ DBTxnObject *txn;
+#define PREPLIST_LEN 16
+ DB_PREPLIST preplist[PREPLIST_LEN];
+ long retp;
+
+ if (!PyArg_ParseTuple(args, ":txn_recover"))
+ return NULL;
+
+ 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=PyString_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;
+}
+#endif
+
static PyObject*
DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
{
@@ -4141,7 +4452,7 @@
return NULL;
CHECK_ENV_NOT_CLOSED(self);
- return (PyObject*)newDBTxnObject(self, txn, flags);
+ return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
}
@@ -4426,6 +4737,10 @@
#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);
@@ -4438,6 +4753,10 @@
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);
@@ -4446,6 +4765,23 @@
MAKE_ENTRY(lock_wait);
#endif
MAKE_ENTRY(ndeadlocks);
+#if (DBVER >= 41)
+ MAKE_ENTRY(locktimeout);
+ MAKE_ENTRY(txntimeout);
+#endif
+#if (DBVER >= 40)
+ MAKE_ENTRY(nlocktimeouts);
+ MAKE_ENTRY(ntxntimeouts);
+#endif
+#if (DBVER >= 46)
+ MAKE_ENTRY(objs_wait);
+ MAKE_ENTRY(objs_nowait);
+ MAKE_ENTRY(lockers_wait);
+ MAKE_ENTRY(lockers_nowait);
+ MAKE_ENTRY(locks_wait);
+ MAKE_ENTRY(locks_nowait);
+ MAKE_ENTRY(hash_len);
+#endif
MAKE_ENTRY(regsize);
MAKE_ENTRY(region_wait);
MAKE_ENTRY(region_nowait);
@@ -4455,130 +4791,653 @@
return d;
}
+#if (DBVER >= 40)
+static PyObject*
+DBEnv_log_flush(DBEnvObject* self, PyObject* args)
+{
+ int err;
+
+ if (!PyArg_ParseTuple(args, ":log_flush"))
+ return NULL;
+ 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();
+}
+#endif
static PyObject*
DBEnv_log_archive(DBEnvObject* self, PyObject* args)
{
- int flags=0;
+ int flags=0;
+ int err;
+ char **log_list = NULL;
+ PyObject* list;
+ PyObject* item = NULL;
+
+ if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
+ return NULL;
+
+ CHECK_ENV_NOT_CLOSED(self);
+ MYDB_BEGIN_ALLOW_THREADS;
+#if (DBVER >= 40)
+ err = self->db_env->log_archive(self->db_env, &log_list, flags);
+#elif (DBVER == 33)
+ err = log_archive(self->db_env, &log_list, flags);
+#else
+ err = log_archive(self->db_env, &log_list, flags, NULL);
+#endif
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ list = PyList_New(0);
+ if (list == NULL) {
+ if (log_list)
+ free(log_list);
+ return NULL;
+ }
+
+ if (log_list) {
+ char **log_list_start;
+ for (log_list_start = log_list; *log_list != NULL; ++log_list) {
+ item = PyString_FromString (*log_list);
+ if (item == NULL) {
+ Py_DECREF(list);
+ list = NULL;
+ break;
+ }
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ }
+ free(log_list_start);
+ }
+ return list;
+}
+
+
+static PyObject*
+DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ DB_TXN_STAT* sp;
+ PyObject* d = NULL;
+ u_int32_t flags=0;
+
+ if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ MYDB_BEGIN_ALLOW_THREADS;
+#if (DBVER >= 40)
+ err = self->db_env->txn_stat(self->db_env, &sp, flags);
+#elif (DBVER == 33)
+ err = txn_stat(self->db_env, &sp);
+#else
+ err = txn_stat(self->db_env, &sp, NULL);
+#endif
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+
+ /* Turn the stat structure into a dictionary */
+ d = PyDict_New();
+ if (d == NULL) {
+ free(sp);
+ return NULL;
+ }
+
+#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
+#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)
+
+#if (DBVER >= 40)
+ MAKE_DB_LSN_ENTRY(last_ckp);
+#endif
+ 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);
+#if (DBVER >= 40)
+ MAKE_ENTRY(nrestores);
+#endif
+ 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);
+ return d;
+}
+
+
+static PyObject*
+DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
+{
+ int flags=0;
+ int oldValue=0;
+
+ if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
+ return NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+
+ if (self->moduleFlags.getReturnsNone)
+ ++oldValue;
+ if (self->moduleFlags.cursorSetReturnsNone)
+ ++oldValue;
+ self->moduleFlags.getReturnsNone = (flags >= 1);
+ self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
+ return PyInt_FromLong(oldValue);
+}
+
+#if (DBVER >= 40)
+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
+#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* args)
+{
+ int err;
+ PyObject *notifyFunc;
+
+ if (!PyArg_ParseTuple(args, "O:set_event_notify", ¬ifyFunc)) {
+ return NULL;
+ }
+
+ 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;
+
+ 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
+
+
+/* --------------------------------------------------------------------- */
+/* REPLICATION METHODS: Base Replication */
+
+#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, PyObject* args)
+{
+ int err;
+ int nsites;
+
+ if (!PyArg_ParseTuple(args, ":rep_get_nsites")) {
+ return NULL;
+ }
+ 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 PyInt_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, PyObject* args)
+{
+ int err;
+ int priority;
+
+ if (!PyArg_ParseTuple(args, ":rep_get_priority")) {
+ return NULL;
+ }
+ 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 PyInt_FromLong(priority);
+}
+
+static PyObject*
+DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
+{
+ int err;
+ int which, timeout;
+
+ 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();
+}
+
+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 = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
+ MYDB_END_ALLOW_THREADS;
+ RETURN_IF_ERR();
+ return PyInt_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 PyInt_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, PyObject* args)
+{
+ int err;
+ int ack_policy;
+
+ if (!PyArg_ParseTuple(args, ":repmgr_get_ack_policy"))
+ {
+ return NULL;
+ }
+ 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 PyInt_FromLong(ack_policy);
+}
+
+static PyObject*
+DBEnv_repmgr_site_list(DBEnvObject* self, PyObject* args)
+{
int err;
- char **log_list = NULL;
- PyObject* list;
- PyObject* item = NULL;
+ unsigned int countp;
+ DB_REPMGR_SITE *listp;
+ PyObject *stats, *key, *tuple;
- if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
+ if (!PyArg_ParseTuple(args, ":repmgr_site_list"))
+ {
return NULL;
-
+ }
CHECK_ENV_NOT_CLOSED(self);
MYDB_BEGIN_ALLOW_THREADS;
-#if (DBVER >= 40)
- err = self->db_env->log_archive(self->db_env, &log_list, flags);
-#elif (DBVER == 33)
- err = log_archive(self->db_env, &log_list, flags);
-#else
- err = log_archive(self->db_env, &log_list, flags, NULL);
-#endif
+ err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
- list = PyList_New(0);
- if (list == NULL) {
- if (log_list)
- free(log_list);
+ stats=PyDict_New();
+ if (stats == NULL) {
+ free(listp);
return NULL;
}
- if (log_list) {
- char **log_list_start;
- for (log_list_start = log_list; *log_list != NULL; ++log_list) {
- item = PyString_FromString (*log_list);
- if (item == NULL) {
- Py_DECREF(list);
- list = NULL;
- break;
- }
- PyList_Append(list, item);
- Py_DECREF(item);
+ for(;countp--;) {
+ key=PyInt_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(log_list_start);
}
- return list;
+ free(listp);
+ return stats;
}
+#endif
-
+#if (DBVER >= 46)
static PyObject*
-DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
+DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
{
int err;
- DB_TXN_STAT* sp;
- PyObject* d = NULL;
- u_int32_t flags=0;
+ int flags=0;
+ static char* kwnames[] = { "flags", NULL };
- if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
+ 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*
+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;
-#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
+ err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
- /* Turn the stat structure into a dictionary */
- d = PyDict_New();
- if (d == NULL) {
- free(sp);
+ stats=PyDict_New();
+ if (stats == NULL) {
+ free(statp);
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(stats, #name, statp->st_##name)
- MAKE_TIME_T_ENTRY(time_ckp);
- MAKE_ENTRY(last_txnid);
- MAKE_ENTRY(maxtxns);
- MAKE_ENTRY(nactive);
- MAKE_ENTRY(maxnactive);
- MAKE_ENTRY(nbegins);
- MAKE_ENTRY(naborts);
- MAKE_ENTRY(ncommits);
- MAKE_ENTRY(regsize);
- MAKE_ENTRY(region_wait);
- MAKE_ENTRY(region_nowait);
+ MAKE_ENTRY(perm_failed);
+ MAKE_ENTRY(msgs_queued);
+ MAKE_ENTRY(msgs_dropped);
+ MAKE_ENTRY(connection_drop);
+ MAKE_ENTRY(connect_fail);
#undef MAKE_ENTRY
-#undef MAKE_TIME_T_ENTRY
- free(sp);
- return d;
+
+ free(statp);
+ return stats;
}
+#endif
-static PyObject*
-DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
-{
- int flags=0;
- int oldValue=0;
+/* --------------------------------------------------------------------- */
+/* DBTxn methods */
- if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
- return NULL;
- CHECK_ENV_NOT_CLOSED(self);
- if (self->moduleFlags.getReturnsNone)
- ++oldValue;
- if (self->moduleFlags.cursorSetReturnsNone)
- ++oldValue;
- self->moduleFlags.getReturnsNone = (flags >= 1);
- self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
- return PyInt_FromLong(oldValue);
+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
-/* --------------------------------------------------------------------- */
-/* DBTxn methods */
+ 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*
@@ -4590,15 +5449,22 @@
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");
+ "after txn_commit, txn_abort "
+ "or txn_discard");
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->commit(txn, flags);
@@ -4606,6 +5472,9 @@
err = txn_commit(txn, flags);
#endif
MYDB_END_ALLOW_THREADS;
+
+ _promote_transaction_dbs_and_sequences(self);
+
RETURN_IF_ERR();
RETURN_NONE();
}
@@ -4629,11 +5498,13 @@
if (!self->txn) {
PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
- "after txn_commit or txn_abort");
+ "after txn_commit, txn_abort "
+ "or txn_discard");
PyErr_SetObject(DBError, t);
Py_DECREF(t);
return NULL;
}
+ self->flag_prepare=1; /* Prepare state */
MYDB_BEGIN_ALLOW_THREADS;
#if (DBVER >= 40)
err = self->txn->prepare(self->txn, (u_int8_t*)gid);
@@ -4651,7 +5522,8 @@
if (!self->txn) {
PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
+ "after txn_commit, txn_abort "
+ "or txn_discard");
PyErr_SetObject(DBError, t);
Py_DECREF(t);
return NULL;
@@ -4666,34 +5538,87 @@
static PyObject*
-DBTxn_abort(DBTxnObject* self, PyObject* args)
+DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
{
- int err;
+ PyObject *dummy;
+ int err=0;
DB_TXN *txn;
- if (!PyArg_ParseTuple(args, ":abort"))
- return NULL;
-
if (!self->txn) {
PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
+ "after txn_commit, txn_abort "
+ "or txn_discard");
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);
+#if (DBVER >= 40)
+ err = txn->discard(txn,0);
+#else
+ err = txn_discard(txn);
+#endif
+ } else {
+ /*
+ ** If the transaction is in the "prepare" or "recover" state,
+ ** we better do not implicitly abort it.
+ */
+ if (!self->flag_prepare) {
#if (DBVER >= 40)
- err = txn->abort(txn);
+ err = txn->abort(txn);
#else
- err = txn_abort(txn);
+ err = txn_abort(txn);
#endif
+ }
+ }
MYDB_END_ALLOW_THREADS;
RETURN_IF_ERR();
RETURN_NONE();
}
+static PyObject*
+DBTxn_abort(DBTxnObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":abort"))
+ return NULL;
+
+ self->flag_prepare=0;
+ _close_transaction_cursors(self);
+
+ return DBTxn_abort_discard_internal(self,0);
+}
+
+static PyObject*
+DBTxn_discard(DBTxnObject* self, PyObject* args)
+{
+ if (!PyArg_ParseTuple(args, ":discard"))
+ return NULL;
+
+ self->flag_prepare=0;
+ _close_transaction_cursors(self);
+
+ return DBTxn_abort_discard_internal(self,1);
+}
+
static PyObject*
DBTxn_id(DBTxnObject* self, PyObject* args)
@@ -4705,7 +5630,8 @@
if (!self->txn) {
PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
- "after txn_commit or txn_abort");
+ "after txn_commit, txn_abort "
+ "or txn_discard");
PyErr_SetObject(DBError, t);
Py_DECREF(t);
return NULL;
@@ -4726,24 +5652,41 @@
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;
@@ -4765,7 +5708,6 @@
RETURN_IF_ERR();
return PyLong_FromLongLong(value);
-
}
static PyObject*
@@ -4784,6 +5726,10 @@
int err;
DBT key;
PyObject *retval = NULL;
+
+ if (!PyArg_ParseTuple(args,":get_key"))
+ return NULL;
+
key.flags = DB_DBT_MALLOC;
CHECK_SEQUENCE_NOT_CLOSED(self)
MYDB_BEGIN_ALLOW_THREADS
@@ -4791,7 +5737,7 @@
MYDB_END_ALLOW_THREADS
if (!err)
- retval = PyString_FromStringAndSize(key.data, key.size);
+ retval = Build_PyString(key.data, key.size);
FREE_DBT(key);
RETURN_IF_ERR();
@@ -4803,13 +5749,15 @@
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();
@@ -4843,12 +5791,18 @@
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;
@@ -4866,6 +5820,9 @@
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();
}
@@ -4916,7 +5873,6 @@
RETURN_IF_ERR();
RETURN_NONE();
-
}
static PyObject*
@@ -4940,13 +5896,16 @@
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();
@@ -4957,16 +5916,19 @@
DBSequence_get_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,":get_range"))
return NULL;
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);
}
@@ -5134,6 +6096,9 @@
{"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 >= 42)
+ {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_VARARGS},
+#endif
#if (DBVER >= 33)
{"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
#endif
@@ -5161,12 +6126,55 @@
{"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_VARARGS},
+#endif
+#if (DBVER >= 40)
{"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},
+#if (DBVER >= 40)
+ {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_VARARGS},
+#endif
+#if (DBVER >= 40)
+ {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
+#if (DBVER >= 42)
+ {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
+#endif
+#endif
+#if (DBVER >= 45)
+ {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_VARARGS},
+#endif
+#if (DBVER >= 45)
+ {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
+ {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_VARARGS},
+ {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
+ {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_VARARGS},
+ {"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_VARARGS},
+ {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
+ METH_VARARGS},
+#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 */
};
@@ -5174,6 +6182,7 @@
static PyMethodDef DBTxn_methods[] = {
{"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
{"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
+ {"discard", (PyCFunction)DBTxn_discard, METH_VARARGS},
{"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
{"id", (PyCFunction)DBTxn_id, METH_VARARGS},
{NULL, NULL} /* sentinel */
@@ -5212,11 +6221,17 @@
DBEnv_getattr(DBEnvObject* self, char *name)
{
if (!strcmp(name, "db_home")) {
- CHECK_ENV_NOT_CLOSED(self);
- if (self->db_env->db_home == NULL) {
- RETURN_NONE();
- }
- return PyString_FromString(self->db_env->db_home);
+ const char *home = NULL;
+ CHECK_ENV_NOT_CLOSED(self);
+#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 PyString_FromString(home);
}
return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
@@ -5582,7 +6597,7 @@
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);
@@ -5590,6 +6605,9 @@
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);
@@ -5599,6 +6617,10 @@
ADD_INT(d, DB_INIT_TXN);
ADD_INT(d, DB_JOINENV);
+#if (DBVER >= 40)
+ ADD_INT(d, DB_XIDDATASIZE);
+#endif
+
ADD_INT(d, DB_RECOVER);
ADD_INT(d, DB_RECOVER_FATAL);
ADD_INT(d, DB_TXN_NOSYNC);
@@ -5645,6 +6667,13 @@
ADD_INT(d, DB_LOCK_MINWRITE);
#endif
+#if (DBVER >= 40)
+ ADD_INT(d, DB_LOCK_EXPIRE);
+#endif
+#if (DBVER >= 43)
+ ADD_INT(d, DB_LOCK_MAXWRITE);
+#endif
+
#if (DBVER >= 33)
/* docs say to use zero instead */
@@ -5816,6 +6845,10 @@
ADD_INT(d, DB_NOPANIC);
#endif
+#if (DBVER >= 41)
+ ADD_INT(d, DB_OVERWRITE);
+#endif
+
#ifdef DB_REGISTER
ADD_INT(d, DB_REGISTER);
#endif
@@ -5832,7 +6865,76 @@
ADD_INT(d, DB_CHKSUM);
#endif
+#if (DBVER >= 44)
+ ADD_INT(d, DB_DSYNC_DB);
+#endif
+
+#if (DBVER >= 45)
+ ADD_INT(d, DB_TXN_SNAPSHOT);
+#endif
+
+#if (DBVER >= 40)
+ 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);
+#endif
+
+#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
+
+#if (DBVER >= 40)
+ 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
+#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_DSYNC_LOG);
ADD_INT(d, DB_LOG_INMEMORY);
ADD_INT(d, DB_BUFFER_SMALL);
ADD_INT(d, DB_SEQ_DEC);
@@ -5844,7 +6946,7 @@
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
@@ -5920,6 +7022,10 @@
MAKE_EX(DBNoSuchFileError);
MAKE_EX(DBPermissionsError);
+#if (DBVER >= 42)
+ MAKE_EX(DBRepHandleDeadError);
+#endif
+
#undef MAKE_EX
/* Initiliase the C API structure and add it to the module */
Modified: python/trunk/Modules/bsddb.h
==============================================================================
--- python/trunk/Modules/bsddb.h (original)
+++ python/trunk/Modules/bsddb.h Tue May 13 20:45:46 2008
@@ -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.6.5devel2"
/* Python object definitions */
@@ -119,17 +119,27 @@
};
+
+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;
+#if (DBVER >= 40)
+ PyObject* event_notifyCallback;
+#endif
+ struct DBObject *children_dbs;
+ struct DBTxnObject *children_txns;
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,6 +147,15 @@
u_int32_t setflags; /* saved flags from set_flags() */
int haveStat;
struct behaviourFlags moduleFlags;
+ 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;
#if (DBVER >= 33)
PyObject* associateCallback;
PyObject* btCompareCallback;
@@ -146,18 +165,31 @@
} 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 +202,17 @@
#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;
-staticforward PyTypeObject DBSequence_Type;
#endif
3
2
Author: georg.brandl
Date: Sun Jun 1 00:55:14 2008
New Revision: 63842
Log:
Reword a little.
Modified:
doctools/trunk/CHANGES
Modified: doctools/trunk/CHANGES
==============================================================================
--- doctools/trunk/CHANGES (original)
+++ doctools/trunk/CHANGES Sun Jun 1 00:55:14 2008
@@ -33,8 +33,8 @@
* Add document metadata to the values in the default template context.
-* Let the "previous" and "next" to more logical documents, so that always
- selecting "next" lets you visit every document in the tree.
+* Let the "previous" and "next" to more logical documents, so that by
+ following "next" links you can traverse the entire TOC tree.
Bugs fixed
----------
1
0
Author: georg.brandl
Date: Sun Jun 1 00:54:10 2008
New Revision: 63841
Log:
Refer to a RFC base URL that actually works.
Modified:
doctools/trunk/sphinx/environment.py
Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py (original)
+++ doctools/trunk/sphinx/environment.py Sun Jun 1 00:54:10 2008
@@ -51,6 +51,7 @@
'embed_stylesheet': False,
'cloak_email_addresses': True,
'pep_base_url': 'http://www.python.org/dev/peps/',
+ 'rfc_base_url': 'http://rfc.net/',
'input_encoding': 'utf-8',
'doctitle_xform': False,
'sectsubtitle_xform': False,
1
0
r63840 - in doctools/trunk: CHANGES sphinx/__init__.py sphinx/builder.py sphinx/environment.py sphinx/htmlhelp.py
by georg.brandl 31 May '08
by georg.brandl 31 May '08
31 May '08
Author: georg.brandl
Date: Sun Jun 1 00:52:42 2008
New Revision: 63840
Log:
More logical "next"/"previous" links.
Modified:
doctools/trunk/CHANGES
doctools/trunk/sphinx/__init__.py
doctools/trunk/sphinx/builder.py
doctools/trunk/sphinx/environment.py
doctools/trunk/sphinx/htmlhelp.py
Modified: doctools/trunk/CHANGES
==============================================================================
--- doctools/trunk/CHANGES (original)
+++ doctools/trunk/CHANGES Sun Jun 1 00:52:42 2008
@@ -33,6 +33,9 @@
* Add document metadata to the values in the default template context.
+* Let the "previous" and "next" to more logical documents, so that always
+ selecting "next" lets you visit every document in the tree.
+
Bugs fixed
----------
Modified: doctools/trunk/sphinx/__init__.py
==============================================================================
--- doctools/trunk/sphinx/__init__.py (original)
+++ doctools/trunk/sphinx/__init__.py Sun Jun 1 00:52:42 2008
@@ -135,6 +135,11 @@
app.builder.build_update()
except KeyboardInterrupt:
# catches BaseExceptions in 2.5 -- SystemExit, KeyboardInterrupt
+ if use_pdb:
+ import pdb
+ print >>sys.stderr, darkred('Interrupted while building, starting debugger:')
+ traceback.print_exc()
+ pdb.post_mortem(sys.exc_info()[2])
return 1
except SystemExit:
return 0
Modified: doctools/trunk/sphinx/builder.py
==============================================================================
--- doctools/trunk/sphinx/builder.py (original)
+++ doctools/trunk/sphinx/builder.py Sun Jun 1 00:52:42 2008
@@ -302,9 +302,6 @@
def prepare_writing(self, docnames):
from sphinx.search import IndexBuilder
- self.info(bold('creating index...'))
- self.env.create_index(self)
-
self.indexer = IndexBuilder()
self.load_indexer(docnames)
self.docwriter = HTMLWriter(self)
@@ -326,6 +323,8 @@
if not isinstance(self.config.html_use_opensearch, basestring):
self.warn('html_use_opensearch config value must now be a string')
+ self.relations = self.env.collect_relations()
+
self.globalcontext = dict(
project = self.config.project,
release = self.config.release,
@@ -350,28 +349,29 @@
# find out relations
prev = next = None
parents = []
- related = self.env.toctree_relations.get(docname)
+ related = self.relations.get(docname)
titles = self.env.titles
- if related:
+ if related and related[1]:
try:
prev = {'link': self.get_relative_uri(docname, related[1]),
'title': self.render_partial(titles[related[1]])['title']}
except KeyError:
# the relation is (somehow) not in the TOC tree, handle that gracefully
prev = None
+ if related and related[2]:
try:
next = {'link': self.get_relative_uri(docname, related[2]),
'title': self.render_partial(titles[related[2]])['title']}
except KeyError:
next = None
- while related:
+ while related and related[0]:
try:
parents.append(
{'link': self.get_relative_uri(docname, related[0]),
'title': self.render_partial(titles[related[0]])['title']})
except KeyError:
pass
- related = self.env.toctree_relations.get(related[0])
+ related = self.relations.get(related[0])
if parents:
parents.pop() # remove link to the master file; we have a generic
# "back to index" link already
@@ -420,13 +420,14 @@
if self.config.html_use_index:
# the total count of lines for each index letter, used to distribute
# the entries into two columns
+ genindex = self.env.create_index(self)
indexcounts = []
- for _, entries in self.env.index:
+ for _, entries in genindex:
indexcounts.append(sum(1 + len(subitems)
for _, (_, subitems) in entries))
genindexcontext = dict(
- genindexentries = self.env.index,
+ genindexentries = genindex,
genindexcounts = indexcounts,
)
self.info(' genindex', nonl=1)
Modified: doctools/trunk/sphinx/environment.py
==============================================================================
--- doctools/trunk/sphinx/environment.py (original)
+++ doctools/trunk/sphinx/environment.py Sun Jun 1 00:52:42 2008
@@ -15,10 +15,10 @@
import heapq
import types
import difflib
-import itertools
import cPickle as pickle
from os import path
from string import uppercase
+from itertools import izip, groupby
try:
import hashlib
md5 = hashlib.md5
@@ -58,7 +58,7 @@
# This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files.
-ENV_VERSION = 21
+ENV_VERSION = 22
default_substitutions = set([
@@ -225,8 +225,7 @@
self.toc_num_entries = {} # docname -> number of real entries
# used to determine when to show the TOC in a sidebar
# (don't show if it's only one item)
- self.toctree_relations = {} # docname -> ["parent", "previous", "next"] docname
- # for navigating in the toctree
+ self.toctree_includes = {} # docname -> list of toctree includefiles
self.files_to_rebuild = {} # docname -> set of files (containing its TOCs)
# to rebuild too
@@ -280,11 +279,14 @@
self.titles.pop(docname, None)
self.tocs.pop(docname, None)
self.toc_num_entries.pop(docname, None)
+ self.toctree_includes.pop(docname, None)
self.filemodules.pop(docname, None)
self.indexentries.pop(docname, None)
- for subfn, fnset in self.files_to_rebuild.iteritems():
+ for subfn, fnset in self.files_to_rebuild.items():
fnset.discard(docname)
+ if not fnset:
+ del self.files_to_rebuild[subfn]
for fullname, (fn, _) in self.descrefs.items():
if fn == docname:
del self.descrefs[fullname]
@@ -590,17 +592,11 @@
"""Note a TOC tree directive in a document and gather information about
file relations from it."""
includefiles = toctreenode['includefiles']
- includefiles_len = len(includefiles)
- for i, includefile in enumerate(includefiles):
- # the "previous" file for the first toctree item is the parent
- previous = i > 0 and includefiles[i-1] or docname
- # the "next" file for the last toctree item is the parent again
- next = i < includefiles_len-1 and includefiles[i+1] or docname
- self.toctree_relations[includefile] = [docname, previous, next]
+ for includefile in includefiles:
# note that if the included file is rebuilt, this one must be
# too (since the TOC of the included file could have changed)
self.files_to_rebuild.setdefault(includefile, set()).add(docname)
-
+ self.toctree_includes.setdefault(docname, []).extend(includefiles)
def build_toc_from(self, docname, document):
"""Build a TOC from the doctree and store it in the inventory."""
@@ -998,14 +994,49 @@
else:
# get all other symbols under one heading
return 'Symbols'
- self.index = [(key, list(group)) for (key, group) in
- itertools.groupby(newlist, keyfunc)]
+ return [(key, list(group)) for (key, group) in groupby(newlist, keyfunc)]
+
+ def collect_relations(self):
+ relations = {}
+ getinc = self.toctree_includes.get
+ def collect(parents, docname, previous, next):
+ includes = getinc(docname)
+ # previous
+ if not previous:
+ previous = parents[0][0]
+ else:
+ while 1:
+ previncs = getinc(previous)
+ if previncs:
+ previous = previncs[-1]
+ else:
+ break
+ # next
+ if includes:
+ next = includes[0]
+ elif next:
+ pass
+ else:
+ for parname, parindex in parents:
+ parincs = getinc(parname)
+ if parincs and parindex + 1 < len(parincs):
+ next = parincs[parindex+1]
+ break
+ # else it will stay None
+ # same for children
+ if includes:
+ for subindex, args in enumerate(izip(includes, [None] + includes,
+ includes[1:] + [None])):
+ collect([(docname, subindex)] + parents, *args)
+ relations[docname] = [parents[0][0], previous, next]
+ collect([(None, 0)], self.config.master_doc, None, None)
+ return relations
def check_consistency(self):
"""Do consistency checks."""
for docname in self.all_docs:
- if docname not in self.toctree_relations:
+ if docname not in self.files_to_rebuild:
if docname == self.config.master_doc:
# the master file is not included anywhere ;)
continue
Modified: doctools/trunk/sphinx/htmlhelp.py
==============================================================================
--- doctools/trunk/sphinx/htmlhelp.py (original)
+++ doctools/trunk/sphinx/htmlhelp.py Sun Jun 1 00:52:42 2008
@@ -184,6 +184,7 @@
f.close()
builder.info('writing index file...')
+ index = builder.env.create_index(builder)
f = open(path.join(outdir, outname+'.hhk'), 'w')
try:
f.write('<UL>\n')
@@ -199,7 +200,7 @@
for subitem in subitems:
write_index(subitem[0], subitem[1], [])
f.write('</UL>')
- for (key, group) in builder.env.index:
+ for (key, group) in index:
for title, (refs, subitems) in group:
write_index(title, refs, subitems)
f.write('</UL>\n')
1
0
The Buildbot has detected a new failure of x86 osx.5 trunk.
Full details are available at:
http://www.python.org/dev/buildbot/all/x86%20osx.5%20trunk/builds/369
Buildbot URL: http://www.python.org/dev/buildbot/all/
Buildslave for this Build: heller-x86-osx5
Build Reason:
Build Source Stamp: [branch trunk] HEAD
Blamelist: georg.brandl,gerhard.haering,mark.summerfield
BUILD FAILED: failed test
Excerpt from the test logfile:
1 test failed:
test_socket
make: *** [buildbottest] Error 1
sincerely,
-The Buildbot
1
0
r63839 - in python/trunk: Lib/sqlite3/test/dbapi.py Modules/_sqlite/cursor.c Modules/_sqlite/cursor.h
by gerhard.haering 31 May '08
by gerhard.haering 31 May '08
31 May '08
Author: gerhard.haering
Date: Sat May 31 23:33:27 2008
New Revision: 63839
Log:
Fixed rowcount for SELECT statements. They're -1 now (again), for better DB-API 2.0 compliance.
Modified:
python/trunk/Lib/sqlite3/test/dbapi.py
python/trunk/Modules/_sqlite/cursor.c
python/trunk/Modules/_sqlite/cursor.h
Modified: python/trunk/Lib/sqlite3/test/dbapi.py
==============================================================================
--- python/trunk/Lib/sqlite3/test/dbapi.py (original)
+++ python/trunk/Lib/sqlite3/test/dbapi.py Sat May 31 23:33:27 2008
@@ -297,6 +297,15 @@
self.cu.execute("update test set name='bar'")
self.failUnlessEqual(self.cu.rowcount, 2)
+ def CheckRowcountSelect(self):
+ """
+ pysqlite does not know the rowcount of SELECT statements, because we
+ don't fetch all rows after executing the select statement. The rowcount
+ has thus to be -1.
+ """
+ self.cu.execute("select 5 union select 6")
+ self.failUnlessEqual(self.cu.rowcount, -1)
+
def CheckRowcountExecutemany(self):
self.cu.execute("delete from test")
self.cu.executemany("insert into test(name) values (?)", [(1,), (2,), (3,)])
Modified: python/trunk/Modules/_sqlite/cursor.c
==============================================================================
--- python/trunk/Modules/_sqlite/cursor.c (original)
+++ python/trunk/Modules/_sqlite/cursor.c Sat May 31 23:33:27 2008
@@ -101,10 +101,7 @@
self->arraysize = 1;
- self->rowcount = PyInt_FromLong(-1L);
- if (!self->rowcount) {
- return -1;
- }
+ self->rowcount = -1L;
Py_INCREF(Py_None);
self->row_factory = Py_None;
@@ -130,7 +127,6 @@
Py_XDECREF(self->row_cast_map);
Py_XDECREF(self->description);
Py_XDECREF(self->lastrowid);
- Py_XDECREF(self->rowcount);
Py_XDECREF(self->row_factory);
Py_XDECREF(self->next_row);
@@ -427,12 +423,12 @@
int statement_type;
PyObject* descriptor;
PyObject* second_argument = NULL;
- long rowcount = 0;
int allow_8bit_chars;
if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) {
return NULL;
}
+
/* Make shooting yourself in the foot with not utf-8 decodable 8-bit-strings harder */
allow_8bit_chars = ((self->connection->text_factory != (PyObject*)&PyUnicode_Type) &&
(self->connection->text_factory != (PyObject*)&PyUnicode_Type && pysqlite_OptimizedUnicode));
@@ -514,10 +510,11 @@
operation_cstr = PyBytes_AsString(operation_bytestr);
}
- /* reset description */
+ /* reset description and rowcount */
Py_DECREF(self->description);
Py_INCREF(Py_None);
self->description = Py_None;
+ self->rowcount = -1L;
func_args = PyTuple_New(1);
if (!func_args) {
@@ -693,7 +690,10 @@
case STATEMENT_DELETE:
case STATEMENT_INSERT:
case STATEMENT_REPLACE:
- rowcount += (long)sqlite3_changes(self->connection->db);
+ if (self->rowcount == -1L) {
+ self->rowcount = 0L;
+ }
+ self->rowcount += (long)sqlite3_changes(self->connection->db);
}
Py_DECREF(self->lastrowid);
@@ -728,13 +728,9 @@
Py_XDECREF(parameters_list);
if (PyErr_Occurred()) {
- Py_DECREF(self->rowcount);
- self->rowcount = PyInt_FromLong(-1L);
+ self->rowcount = -1L;
return NULL;
} else {
- Py_DECREF(self->rowcount);
- self->rowcount = PyInt_FromLong(rowcount);
-
Py_INCREF(self);
return (PyObject*)self;
}
@@ -1028,7 +1024,7 @@
{"description", T_OBJECT, offsetof(pysqlite_Cursor, description), RO},
{"arraysize", T_INT, offsetof(pysqlite_Cursor, arraysize), 0},
{"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), RO},
- {"rowcount", T_OBJECT, offsetof(pysqlite_Cursor, rowcount), RO},
+ {"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), RO},
{"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0},
{NULL}
};
Modified: python/trunk/Modules/_sqlite/cursor.h
==============================================================================
--- python/trunk/Modules/_sqlite/cursor.h (original)
+++ python/trunk/Modules/_sqlite/cursor.h Sat May 31 23:33:27 2008
@@ -37,7 +37,7 @@
PyObject* row_cast_map;
int arraysize;
PyObject* lastrowid;
- PyObject* rowcount;
+ long rowcount;
PyObject* row_factory;
pysqlite_Statement* statement;
1
0
31 May '08
Author: georg.brandl
Date: Sat May 31 20:34:27 2008
New Revision: 63838
Log:
Backport r63776: tkinter fixes.
Modified:
python/branches/release25-maint/Lib/lib-tk/Tkinter.py
Modified: python/branches/release25-maint/Lib/lib-tk/Tkinter.py
==============================================================================
--- python/branches/release25-maint/Lib/lib-tk/Tkinter.py (original)
+++ python/branches/release25-maint/Lib/lib-tk/Tkinter.py Sat May 31 20:34:27 2008
@@ -1055,6 +1055,12 @@
if k[-1] == '_': k = k[:-1]
if callable(v):
v = self._register(v)
+ elif isinstance(v, (tuple, list)):
+ for item in v:
+ if not isinstance(item, (basestring, int)):
+ break
+ else:
+ v = ' '.join(map(str, v))
res = res + ('-'+k, v)
return res
def nametowidget(self, name):
@@ -1094,7 +1100,6 @@
if self._tclCommands is None:
self._tclCommands = []
self._tclCommands.append(name)
- #print '+ Tkinter created command', name
return name
register = _register
def _root(self):
@@ -1747,10 +1752,11 @@
after=widget - pack it after you have packed widget
anchor=NSEW (or subset) - position widget according to
given direction
- before=widget - pack it before you will pack widget
+ before=widget - pack it before you will pack widget
expand=bool - expand widget if parent size grows
fill=NONE or X or Y or BOTH - fill widget if widget grows
in=master - use master to contain this widget
+ in_=master - see 'in' option description
ipadx=amount - add internal padding in x direction
ipady=amount - add internal padding in y direction
padx=amount - add padding in x direction
@@ -1788,29 +1794,26 @@
Base class to use the methods place_* in every widget."""
def place_configure(self, cnf={}, **kw):
"""Place a widget in the parent widget. Use as options:
- in=master - master relative to which the widget is placed.
+ in=master - master relative to which the widget is placed
+ in_=master - see 'in' option description
x=amount - locate anchor of this widget at position x of master
y=amount - locate anchor of this widget at position y of master
relx=amount - locate anchor of this widget between 0.0 and 1.0
relative to width of master (1.0 is right edge)
- rely=amount - locate anchor of this widget between 0.0 and 1.0
+ rely=amount - locate anchor of this widget between 0.0 and 1.0
relative to height of master (1.0 is bottom edge)
- anchor=NSEW (or subset) - position anchor according to given direction
+ anchor=NSEW (or subset) - position anchor according to given direction
width=amount - width of this widget in pixel
height=amount - height of this widget in pixel
relwidth=amount - width of this widget between 0.0 and 1.0
relative to width of master (1.0 is the same width
- as the master)
- relheight=amount - height of this widget between 0.0 and 1.0
+ as the master)
+ relheight=amount - height of this widget between 0.0 and 1.0
relative to height of master (1.0 is the same
- height as the master)
- bordermode="inside" or "outside" - whether to take border width of master widget
- into account
- """
- for k in ['in_']:
- if kw.has_key(k):
- kw[k[:-1]] = kw[k]
- del kw[k]
+ height as the master)
+ bordermode="inside" or "outside" - whether to take border width of
+ master widget into account
+ """
self.tk.call(
('place', 'configure', self._w)
+ self._options(cnf, kw))
@@ -1845,6 +1848,7 @@
column=number - use cell identified with given column (starting with 0)
columnspan=number - this widget will span several columns
in=master - use master to contain this widget
+ in_=master - see 'in' option description
ipadx=amount - add internal padding in x direction
ipady=amount - add internal padding in y direction
padx=amount - add padding in x direction
1
0
Author: benjamin.peterson
Date: Sat May 31 20:25:52 2008
New Revision: 63837
Log:
make a branch for testing improvments
Added:
python/branches/benjaminp-testing/
- copied from r63836, /python/trunk/
1
0
The Buildbot has detected a new failure of amd64 gentoo trunk.
Full details are available at:
http://www.python.org/dev/buildbot/all/amd64%20gentoo%20trunk/builds/933
Buildbot URL: http://www.python.org/dev/buildbot/all/
Buildslave for this Build: norwitz-amd64
Build Reason: The web-page 'force build' button was pressed by 'Georg': Testing
Build Source Stamp: [branch release25-maint] HEAD
Blamelist:
BUILD FAILED: failed svn
sincerely,
-The Buildbot
1
0
r63836 - in doctools/trunk: CHANGES sphinx/directives/desc.py sphinx/ext/autodoc.py
by georg.brandl 31 May '08
by georg.brandl 31 May '08
31 May '08
Author: georg.brandl
Date: Sat May 31 18:58:22 2008
New Revision: 63836
Log:
Fix handling of autoclass directives' module names.
Modified:
doctools/trunk/CHANGES
doctools/trunk/sphinx/directives/desc.py
doctools/trunk/sphinx/ext/autodoc.py
Modified: doctools/trunk/CHANGES
==============================================================================
--- doctools/trunk/CHANGES (original)
+++ doctools/trunk/CHANGES Sat May 31 18:58:22 2008
@@ -61,6 +61,9 @@
* Provide the standard "class" directive as "cssclass"; else it is
shadowed by the Sphinx-defined directive.
+* Fix the handling of explicit module names given to autoclass directives.
+ They now show up with the correct module name in the generated docs.
+
Release 0.3 (May 6, 2008)
=========================
Modified: doctools/trunk/sphinx/directives/desc.py
==============================================================================
--- doctools/trunk/sphinx/directives/desc.py (original)
+++ doctools/trunk/sphinx/directives/desc.py Sat May 31 18:58:22 2008
@@ -20,41 +20,41 @@
# ------ information units ---------------------------------------------------------
-def desc_index_text(desctype, currmodule, name):
+def desc_index_text(desctype, module, name):
if desctype == 'function':
- if not currmodule:
+ if not module:
return '%s() (built-in function)' % name
- return '%s() (in module %s)' % (name, currmodule)
+ return '%s() (in module %s)' % (name, module)
elif desctype == 'data':
- if not currmodule:
+ if not module:
return '%s (built-in variable)' % name
- return '%s (in module %s)' % (name, currmodule)
+ return '%s (in module %s)' % (name, module)
elif desctype == 'class':
- return '%s (class in %s)' % (name, currmodule)
+ return '%s (class in %s)' % (name, module)
elif desctype == 'exception':
return name
elif desctype == 'method':
try:
clsname, methname = name.rsplit('.', 1)
except ValueError:
- if currmodule:
- return '%s() (in module %s)' % (name, currmodule)
+ if module:
+ return '%s() (in module %s)' % (name, module)
else:
return '%s()' % name
- if currmodule:
- return '%s() (%s.%s method)' % (methname, currmodule, clsname)
+ if module:
+ return '%s() (%s.%s method)' % (methname, module, clsname)
else:
return '%s() (%s method)' % (methname, clsname)
elif desctype == 'attribute':
try:
clsname, attrname = name.rsplit('.', 1)
except ValueError:
- if currmodule:
- return '%s (in module %s)' % (name, currmodule)
+ if module:
+ return '%s (in module %s)' % (name, module)
else:
return name
- if currmodule:
- return '%s (%s.%s attribute)' % (attrname, currmodule, clsname)
+ if module:
+ return '%s (%s.%s attribute)' % (attrname, module, clsname)
else:
return '%s (%s attribute)' % (attrname, clsname)
elif desctype == 'opcode':
@@ -82,7 +82,7 @@
py_paramlist_re = re.compile(r'([\[\],])') # split at '[', ']' and ','
-def parse_py_signature(signode, sig, desctype, env):
+def parse_py_signature(signode, sig, desctype, module, env):
"""
Transform a python signature into RST nodes.
Return (fully qualified name of the thing, classname if any).
@@ -118,8 +118,8 @@
# exceptions are a special case, since they are documented in the
# 'exceptions' module.
elif add_module and env.config.add_module_names and \
- env.currmodule and env.currmodule != 'exceptions':
- nodetext = env.currmodule + '.'
+ module and module != 'exceptions':
+ nodetext = module + '.'
signode += addnodes.desc_classname(nodetext, nodetext)
signode += addnodes.desc_name(name, name)
@@ -284,6 +284,7 @@
signatures = map(lambda s: s.strip().replace('\\', ''), arguments[0].split('\n'))
names = []
clsname = None
+ module = options.get('module', env.currmodule)
for i, sig in enumerate(signatures):
# add a signature node for each signature in the current unit
# and add a reference target for it
@@ -294,7 +295,7 @@
try:
if desctype in ('function', 'data', 'class', 'exception',
'method', 'attribute'):
- name, clsname = parse_py_signature(signode, sig, desctype, env)
+ name, clsname = parse_py_signature(signode, sig, desctype, module, env)
elif desctype in ('cfunction', 'cmember', 'cmacro', 'ctype', 'cvar'):
name = parse_c_signature(signode, sig, desctype)
elif desctype == 'opcode':
@@ -347,7 +348,7 @@
# only add target and index entry if this is the first description of the
# function name in this desc block
if not noindex and name not in names:
- fullname = (env.currmodule and env.currmodule + '.' or '') + name
+ fullname = (module and module + '.' or '') + name
# note target
if fullname not in state.document.ids:
signode['names'].append(fullname)
@@ -358,7 +359,7 @@
names.append(name)
env.note_index_entry('single',
- desc_index_text(desctype, env.currmodule, name),
+ desc_index_text(desctype, module, name),
fullname, fullname)
subnode = addnodes.desc_content()
@@ -382,7 +383,8 @@
desc_directive.content = 1
desc_directive.arguments = (1, 0, 1)
-desc_directive.options = {'noindex': directives.flag}
+desc_directive.options = {'noindex': directives.flag,
+ 'module': directives.unchanged}
desctypes = [
# the Python ones
Modified: doctools/trunk/sphinx/ext/autodoc.py
==============================================================================
--- doctools/trunk/sphinx/ext/autodoc.py (original)
+++ doctools/trunk/sphinx/ext/autodoc.py Sat May 31 18:58:22 2008
@@ -184,6 +184,10 @@
except Exception:
args = ''
result.append(indent + '.. %s:: %s%s' % (what, qualname, args), '<autodoc>')
+ if what != 'module':
+ # Be explicit about the module, this is necessary since .. class:: doesn't
+ # support a prepended module name
+ result.append(indent + ' :module: %s' % mod, '<autodoc>')
result.append('', '<autodoc>')
# the module directive doesn't have content
1
0