From: Jan Engelhardt Date: 2013-07-06 16:07:31.146616589 +0200 This patch was partially autogenerated: - copying python-bsddb3-6.0.0 sources into the python-2.7.5 tree - creating a diff -w against the unmodified python-2.7.5 - stripped all hunks that pertained to module renaming - manually added db6 searching to setup.py --- Lib/bsddb/test/test_all.py | 15 +++-- Lib/bsddb/test/test_misc.py | 5 + Lib/bsddb/test/test_replication.py | 25 +------- Modules/_bsddb.c | 108 +++++++++++++++++++++++++++++++++---- Modules/bsddb.h | 2 setup.py | 4 + 6 files changed, 118 insertions(+), 41 deletions(-) --- a/Lib/bsddb/test/test_all.py +++ b/Lib/bsddb/test/test_all.py @@ -74,8 +74,9 @@ if sys.version_info[0] >= 3 : key = key.decode(charset) return (key, value.decode(charset)) - def __next__(self) : - v = getattr(self._dbcursor, "next")() + def __next__(self, flags=0, dlen=-1, doff=-1) : + v = getattr(self._dbcursor, "next")(flags=flags, dlen=dlen, + doff=doff) return self._fix(v) next = __next__ @@ -128,8 +129,8 @@ if sys.version_info[0] >= 3 : v = self._dbcursor.current(flags=flags, dlen=dlen, doff=doff) return self._fix(v) - def first(self) : - v = self._dbcursor.first() + def first(self, flags=0, dlen=-1, doff=-1) : + v = self._dbcursor.first(flags=flags, dlen=dlen, doff=doff) return self._fix(v) def pget(self, key=None, data=None, flags=0) : @@ -489,7 +490,11 @@ def print_versions(): print 'py module: %s' % getattr(bsddb, "__file"+suffix) print 'extension module: %s' % getattr(bsddb, "__file"+suffix) - print 'python version: %s' % sys.version + print 'Test working dir: %s' % get_test_path_prefix() + import platform + print 'python version: %s %s' % \ + (sys.version.replace("\r", "").replace("\n", ""), \ + platform.architecture()[0]) print 'My pid: %s' % os.getpid() print '-=' * 38 --- a/Lib/bsddb/test/test_misc.py +++ b/Lib/bsddb/test/test_misc.py @@ -46,8 +46,9 @@ class MiscTestCase(unittest.TestCase): d[repr(i)] = repr(100*i) db.close() db = hashopen(self.filename) - rp = repr(db) - self.assertEqual(rp, repr(d)) + rp = repr(sorted(db.items())) + rd = repr(sorted(d.items())) + self.assertEqual(rp, rd) db.close() # http://sourceforge.net/tracker/index.php?func=detail&aid=1708868&group_id=13900&atid=313900 --- a/Lib/bsddb/test/test_replication.py +++ b/Lib/bsddb/test/test_replication.py @@ -165,21 +165,10 @@ class DBReplicationManager(DBReplication # is not generated if the master has no new transactions. # This is solved in BDB 4.6 (#15542). import time - timeout = time.time()+60 + timeout = time.time()+10 while (time.time()timeout: - import sys - print >> sys.stderr, ("XXX: timeout happened before" - "startup was confirmed - see issue 3892") - startup_timeout = True + self.assertTrue(time.time()=timeout and startup_timeout: - self.skipTest("replication test skipped due to random failure, " - "see issue 3892") self.assertLess(time.time(), timeout) self.assertEqual("123", v) @@ -375,7 +356,7 @@ class DBBaseReplication(DBReplication) : # is not generated if the master has no new transactions. # This is solved in BDB 4.6 (#15542). import time - timeout = time.time()+60 + timeout = time.time()+10 while (time.time()= 0x02050000) +#define NUMBER_FromUnsignedLong PyInt_FromSize_t +#endif #endif #ifdef WITH_THREAD @@ -853,6 +857,18 @@ static void _addIntToDict(PyObject* dict Py_XDECREF(v); } +#if (DBVER >= 60) && (PY_VERSION_HEX >= 0x02050000) +/* add an unsigned integer to a dictionary using the given name as a key */ +static void _addUnsignedIntToDict(PyObject* dict, char *name, unsigned int value) +{ + PyObject* v = NUMBER_FromUnsignedLong((unsigned long) value); + if (!v || PyDict_SetItemString(dict, name, v)) + PyErr_Clear(); + + Py_XDECREF(v); +} +#endif + /* The same, when the value is a time_t */ static void _addTimeTToDict(PyObject* dict, char *name, time_t value) { @@ -2677,13 +2693,21 @@ _default_cmp(const DBT *leftKey, static int _db_compareCallback(DB* db, const DBT *leftKey, - const DBT *rightKey) + const DBT *rightKey +#if (DBVER >= 60) + , size_t *locp +#endif + ) { int res = 0; PyObject *args; PyObject *result = NULL; DBObject *self = (DBObject *)db->app_private; +# if (DBVER >= 60) + locp = NULL; /* As required by documentation */ +#endif + if (self == NULL || self->btCompareCallback == NULL) { MYDB_BEGIN_BLOCK_THREADS; PyErr_SetString(PyExc_TypeError, @@ -2791,13 +2815,21 @@ DB_set_bt_compare(DBObject* self, PyObje static int _db_dupCompareCallback(DB* db, const DBT *leftKey, - const DBT *rightKey) + const DBT *rightKey +#if (DBVER >= 60) + , size_t *locp +#endif + ) { int res = 0; PyObject *args; PyObject *result = NULL; DBObject *self = (DBObject *)db->app_private; +#if (DBVER >= 60) + locp = NULL; /* As required by documentation */ +#endif + if (self == NULL || self->dupCompareCallback == NULL) { MYDB_BEGIN_BLOCK_THREADS; PyErr_SetString(PyExc_TypeError, @@ -3576,13 +3608,14 @@ Py_ssize_t DB_length(PyObject* _self) err = self->db->stat(self->db, /*txnid*/ NULL, &sp, 0); MYDB_END_ALLOW_THREADS; + if (makeDBError(err)) { + return -1; + } + /* All the stat structures have matching fields upto the ndata field, so we can use any of them for the type cast */ size = ((DB_BTREE_STAT*)sp)->bt_ndata; - if (err) - return -1; - free(sp); return size; } @@ -8420,12 +8453,22 @@ static PyObject* DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs) { int err, flags = 0; +#if (DBVER >= 60) + unsigned +#endif int delta = 1; db_seq_t value; PyObject *txnobj = NULL; DB_TXN *txn = NULL; static char* kwnames[] = {"delta", "txn", "flags", NULL }; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags)) + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, +#if (DBVER >=60) + "|IOi:get", +#else + "|iOi:get", +#endif + kwnames, &delta, &txnobj, &flags)) return NULL; CHECK_SEQUENCE_NOT_CLOSED(self) @@ -8555,8 +8598,19 @@ DBSequence_remove(DBSequenceObject* self static PyObject* DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args) { - int err, size; - if (!PyArg_ParseTuple(args,"i:set_cachesize", &size)) + int err; +#if (DBVER >= 60) + unsigned +#endif + int size; + + if (!PyArg_ParseTuple(args, +#if (DBVER >= 60) + "I:set_cachesize", +#else + "i:set_cachesize", +#endif + &size)) return NULL; CHECK_SEQUENCE_NOT_CLOSED(self) @@ -8571,7 +8625,11 @@ DBSequence_set_cachesize(DBSequenceObjec static PyObject* DBSequence_get_cachesize(DBSequenceObject* self) { - int err, size; + int err; +#if (DBVER >= 60) + unsigned +#endif + int size; CHECK_SEQUENCE_NOT_CLOSED(self) @@ -8700,6 +8758,9 @@ DBSequence_stat(DBSequenceObject* self, #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name) +#if (DBVER >= 60) && (PY_VERSION_HEX >= 0x02050000) +#define MAKE_UNSIGNED_INT_ENTRY(name) _addUnsignedIntToDict(dict_stat, #name, sp->st_##name) +#endif #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name) MAKE_INT_ENTRY(wait); @@ -8709,10 +8770,15 @@ DBSequence_stat(DBSequenceObject* self, MAKE_LONG_LONG_ENTRY(last_value); MAKE_LONG_LONG_ENTRY(min); MAKE_LONG_LONG_ENTRY(max); +#if (DBVER >= 60) && (PY_VERSION_HEX >= 0x02050000) + MAKE_UNSIGNED_INT_ENTRY(cache_size); +#else MAKE_INT_ENTRY(cache_size); +#endif MAKE_INT_ENTRY(flags); #undef MAKE_INT_ENTRY +#undef MAKE_UNSIGNED_INT_ENTRY #undef MAKE_LONG_LONG_ENTRY free(sp); @@ -9014,7 +9080,7 @@ static PyMethodDef DBEnv_methods[] = { {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS}, #if (DBVER < 48) {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server, - METH_VARARGS|METH_KEYWORDS}, + METH_VARARGS||METH_KEYWORDS}, #endif {"set_mp_max_openfd", (PyCFunction)DBEnv_set_mp_max_openfd, METH_VARARGS}, {"get_mp_max_openfd", (PyCFunction)DBEnv_get_mp_max_openfd, METH_NOARGS}, @@ -9986,6 +10052,10 @@ PyMODINIT_FUNC PyInit__bsddb(void) / ADD_INT(d, DB_LOG_ZERO); #endif +#if (DBVER >= 60) + ADD_INT(d, DB_LOG_BLOB); +#endif + #if (DBVER >= 44) ADD_INT(d, DB_DSYNC_DB); #endif @@ -10046,6 +10116,10 @@ PyMODINIT_FUNC PyInit__bsddb(void) / ADD_INT(d, DB_EVENT_REG_PANIC); #endif +#if (DBVER >= 60) + ADD_INT(d, DB_EVENT_REP_AUTOTAKEOVER_FAILED); +#endif + #if (DBVER >=52) ADD_INT(d, DB_EVENT_REP_SITE_ADDED); ADD_INT(d, DB_EVENT_REP_SITE_REMOVED); @@ -10150,6 +10224,20 @@ PyMODINIT_FUNC PyInit__bsddb(void) / ADD_INT(d, DB_REP_CONF_INMEM); #endif +#if (DBVER >= 60) + ADD_INT(d, DB_REPMGR_ISVIEW); +#endif + +#if (DBVER >= 60) + ADD_INT(d, DB_DBT_BLOB); +#endif + +#if (DBVER >= 60) + ADD_INT(d, DB_STREAM_READ); + ADD_INT(d, DB_STREAM_WRITE); + ADD_INT(d, DB_STREAM_SYNC_WRITE); +#endif + ADD_INT(d, DB_TIMEOUT); #if (DBVER >= 50) --- a/Modules/bsddb.h +++ b/Modules/bsddb.h @@ -110,7 +110,7 @@ #error "eek! DBVER can't handle minor versions > 9" #endif -#define PY_BSDDB_VERSION "5.3.0" +#define PY_BSDDB_VERSION "6.0.0" /* Python object definitions */ --- a/setup.py +++ b/setup.py @@ -951,7 +951,7 @@ class PyBuildExt(build_ext): # a release. Most open source OSes come with one or more # versions of BerkeleyDB already installed. - max_db_ver = (5, 3) + max_db_ver = (6, 0) min_db_ver = (4, 3) db_setup_debug = False # verbose debug prints from this script? @@ -991,6 +991,7 @@ class PyBuildExt(build_ext): # construct a list of paths to look for the header file in on # top of the normal inc_dirs. db_inc_paths = [ + '/usr/include/db6', '/usr/include/db4', '/usr/local/include/db4', '/opt/sfw/include/db4', @@ -1030,6 +1031,7 @@ class PyBuildExt(build_ext): for dn in inc_dirs: std_variants.append(os.path.join(dn, 'db3')) std_variants.append(os.path.join(dn, 'db4')) + std_variants.append(os.path.join(dn, 'db6')) for x in gen_db_minor_ver_nums(4): std_variants.append(os.path.join(dn, "db4%d"%x)) std_variants.append(os.path.join(dn, "db4.%d"%x))