Issue #5768: Change to Unicode output logic and test case for same.
[python.git] / Modules / _bsddb.c
blob149e43dc06e1e16a4fe4367e7870606f94357dc5
1 /*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33 ------------------------------------------------------------------------*/
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
38 * written to replace a SWIG-generated file. It has since been updated
39 * to compile with Berkeley DB versions 3.2 through 4.2.
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * Berkeley DB 2.7.x.
46 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
51 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
53 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
54 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
57 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
60 * http://pybsddb.sf.net
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
65 * http://www.python.org/peps/pep-0291.html
67 * This module contains 6 types:
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
74 * DBSequence (Sequence)
78 /* --------------------------------------------------------------------- */
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
86 * --Robin
89 /* --------------------------------------------------------------------- */
91 #include <stddef.h> /* for offsetof() */
92 #include <Python.h>
94 #define COMPILING_BSDDB_C
95 #include "bsddb.h"
96 #undef COMPILING_BSDDB_C
98 static char *rcs_id = "$Id$";
100 /* --------------------------------------------------------------------- */
101 /* Various macro definitions */
103 #if (PY_VERSION_HEX < 0x02050000)
104 typedef int Py_ssize_t;
105 #endif
107 #if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108 /* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
111 #define PyBytes_FromString PyString_FromString
112 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
113 #define PyBytes_Check PyString_Check
114 #define PyBytes_GET_SIZE PyString_GET_SIZE
115 #define PyBytes_AS_STRING PyString_AS_STRING
116 #endif
118 #if (PY_VERSION_HEX >= 0x03000000)
119 #define NUMBER_Check PyLong_Check
120 #define NUMBER_AsLong PyLong_AsLong
121 #define NUMBER_FromLong PyLong_FromLong
122 #else
123 #define NUMBER_Check PyInt_Check
124 #define NUMBER_AsLong PyInt_AsLong
125 #define NUMBER_FromLong PyInt_FromLong
126 #endif
128 #ifdef WITH_THREAD
130 /* These are for when calling Python --> C */
131 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
132 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
134 /* For 2.3, use the PyGILState_ calls */
135 #if (PY_VERSION_HEX >= 0x02030000)
136 #define MYDB_USE_GILSTATE
137 #endif
139 /* and these are for calling C --> Python */
140 #if defined(MYDB_USE_GILSTATE)
141 #define MYDB_BEGIN_BLOCK_THREADS \
142 PyGILState_STATE __savestate = PyGILState_Ensure();
143 #define MYDB_END_BLOCK_THREADS \
144 PyGILState_Release(__savestate);
145 #else /* MYDB_USE_GILSTATE */
146 /* Pre GILState API - do it the long old way */
147 static PyInterpreterState* _db_interpreterState = NULL;
148 #define MYDB_BEGIN_BLOCK_THREADS { \
149 PyThreadState* prevState; \
150 PyThreadState* newState; \
151 PyEval_AcquireLock(); \
152 newState = PyThreadState_New(_db_interpreterState); \
153 prevState = PyThreadState_Swap(newState);
155 #define MYDB_END_BLOCK_THREADS \
156 newState = PyThreadState_Swap(prevState); \
157 PyThreadState_Clear(newState); \
158 PyEval_ReleaseLock(); \
159 PyThreadState_Delete(newState); \
161 #endif /* MYDB_USE_GILSTATE */
163 #else
164 /* Compiled without threads - avoid all this cruft */
165 #define MYDB_BEGIN_ALLOW_THREADS
166 #define MYDB_END_ALLOW_THREADS
167 #define MYDB_BEGIN_BLOCK_THREADS
168 #define MYDB_END_BLOCK_THREADS
170 #endif
172 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
173 #define INCOMPLETE_IS_WARNING 1
175 /* --------------------------------------------------------------------- */
176 /* Exceptions */
178 static PyObject* DBError; /* Base class, all others derive from this */
179 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
180 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
181 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
182 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
183 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
184 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
185 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
186 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
187 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
188 static PyObject* DBNoServerError; /* DB_NOSERVER */
189 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
190 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
191 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
192 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
194 #if !INCOMPLETE_IS_WARNING
195 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
196 #endif
198 static PyObject* DBInvalidArgError; /* EINVAL */
199 static PyObject* DBAccessError; /* EACCES */
200 static PyObject* DBNoSpaceError; /* ENOSPC */
201 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
202 static PyObject* DBAgainError; /* EAGAIN */
203 static PyObject* DBBusyError; /* EBUSY */
204 static PyObject* DBFileExistsError; /* EEXIST */
205 static PyObject* DBNoSuchFileError; /* ENOENT */
206 static PyObject* DBPermissionsError; /* EPERM */
208 #if (DBVER >= 42)
209 static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
210 #endif
212 static PyObject* DBRepUnavailError; /* DB_REP_UNAVAIL */
214 #if (DBVER < 43)
215 #define DB_BUFFER_SMALL ENOMEM
216 #endif
219 /* --------------------------------------------------------------------- */
220 /* Structure definitions */
222 #if PYTHON_API_VERSION < 1010
223 #error "Python 2.1 or later required"
224 #endif
227 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
228 #define DEFAULT_GET_RETURNS_NONE 1
229 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
232 /* See comment in Python 2.6 "object.h" */
233 #ifndef staticforward
234 #define staticforward static
235 #endif
236 #ifndef statichere
237 #define statichere static
238 #endif
240 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type,
241 DBLock_Type;
242 #if (DBVER >= 43)
243 staticforward PyTypeObject DBSequence_Type;
244 #endif
246 #ifndef Py_TYPE
247 /* for compatibility with Python 2.5 and earlier */
248 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
249 #endif
251 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
252 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
253 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
254 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
255 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
256 #if (DBVER >= 43)
257 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
258 #endif
260 #if (DBVER < 46)
261 #define _DBC_close(dbc) dbc->c_close(dbc)
262 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
263 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
264 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
265 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
266 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
267 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
268 #else
269 #define _DBC_close(dbc) dbc->close(dbc)
270 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
271 #define _DBC_del(dbc,a) dbc->del(dbc,a)
272 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
273 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
274 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
275 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
276 #endif
279 /* --------------------------------------------------------------------- */
280 /* Utility macros and functions */
282 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
284 object->sibling_next=backlink; \
285 object->sibling_prev_p=&(backlink); \
286 backlink=object; \
287 if (object->sibling_next) { \
288 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
292 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
294 if (object->sibling_next) { \
295 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
297 *(object->sibling_prev_p)=object->sibling_next; \
300 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
302 if (object->sibling_next) { \
303 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
305 if (object->sibling_prev_p) { \
306 *(object->sibling_prev_p)=object->sibling_next; \
310 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
312 object->sibling_next_txn=backlink; \
313 object->sibling_prev_p_txn=&(backlink); \
314 backlink=object; \
315 if (object->sibling_next_txn) { \
316 object->sibling_next_txn->sibling_prev_p_txn= \
317 &(object->sibling_next_txn); \
321 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
323 if (object->sibling_next_txn) { \
324 object->sibling_next_txn->sibling_prev_p_txn= \
325 object->sibling_prev_p_txn; \
327 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
331 #define RETURN_IF_ERR() \
332 if (makeDBError(err)) { \
333 return NULL; \
336 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
338 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
339 if ((nonNull) == NULL) { \
340 PyObject *errTuple = NULL; \
341 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
342 if (errTuple) { \
343 PyErr_SetObject((pyErrObj), errTuple); \
344 Py_DECREF(errTuple); \
346 return NULL; \
349 #define CHECK_DB_NOT_CLOSED(dbobj) \
350 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
352 #define CHECK_ENV_NOT_CLOSED(env) \
353 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
355 #define CHECK_CURSOR_NOT_CLOSED(curs) \
356 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
358 #if (DBVER >= 43)
359 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
360 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
361 #endif
363 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
364 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
366 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
368 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
369 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
372 static int makeDBError(int err);
375 /* Return the access method type of the DBObject */
376 static int _DB_get_type(DBObject* self)
378 DBTYPE type;
379 int err;
381 err = self->db->get_type(self->db, &type);
382 if (makeDBError(err)) {
383 return -1;
385 return type;
389 /* Create a DBT structure (containing key and data values) from Python
390 strings. Returns 1 on success, 0 on an error. */
391 static int make_dbt(PyObject* obj, DBT* dbt)
393 CLEAR_DBT(*dbt);
394 if (obj == Py_None) {
395 /* no need to do anything, the structure has already been zeroed */
397 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
398 PyErr_SetString(PyExc_TypeError,
399 #if (PY_VERSION_HEX < 0x03000000)
400 "Data values must be of type string or None.");
401 #else
402 "Data values must be of type bytes or None.");
403 #endif
404 return 0;
406 return 1;
410 /* Recno and Queue DBs can have integer keys. This function figures out
411 what's been given, verifies that it's allowed, and then makes the DBT.
413 Caller MUST call FREE_DBT(key) when done. */
414 static int
415 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
417 db_recno_t recno;
418 int type;
420 CLEAR_DBT(*key);
421 if (keyobj == Py_None) {
422 type = _DB_get_type(self);
423 if (type == -1)
424 return 0;
425 if (type == DB_RECNO || type == DB_QUEUE) {
426 PyErr_SetString(
427 PyExc_TypeError,
428 "None keys not allowed for Recno and Queue DB's");
429 return 0;
431 /* no need to do anything, the structure has already been zeroed */
434 else if (PyBytes_Check(keyobj)) {
435 /* verify access method type */
436 type = _DB_get_type(self);
437 if (type == -1)
438 return 0;
439 if (type == DB_RECNO || type == DB_QUEUE) {
440 PyErr_SetString(
441 PyExc_TypeError,
442 #if (PY_VERSION_HEX < 0x03000000)
443 "String keys not allowed for Recno and Queue DB's");
444 #else
445 "Bytes keys not allowed for Recno and Queue DB's");
446 #endif
447 return 0;
451 * NOTE(gps): I don't like doing a data copy here, it seems
452 * wasteful. But without a clean way to tell FREE_DBT if it
453 * should free key->data or not we have to. Other places in
454 * the code check for DB_THREAD and forceably set DBT_MALLOC
455 * when we otherwise would leave flags 0 to indicate that.
457 key->data = malloc(PyBytes_GET_SIZE(keyobj));
458 if (key->data == NULL) {
459 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
460 return 0;
462 memcpy(key->data, PyBytes_AS_STRING(keyobj),
463 PyBytes_GET_SIZE(keyobj));
464 key->flags = DB_DBT_REALLOC;
465 key->size = PyBytes_GET_SIZE(keyobj);
468 else if (NUMBER_Check(keyobj)) {
469 /* verify access method type */
470 type = _DB_get_type(self);
471 if (type == -1)
472 return 0;
473 if (type == DB_BTREE && pflags != NULL) {
474 /* if BTREE then an Integer key is allowed with the
475 * DB_SET_RECNO flag */
476 *pflags |= DB_SET_RECNO;
478 else if (type != DB_RECNO && type != DB_QUEUE) {
479 PyErr_SetString(
480 PyExc_TypeError,
481 "Integer keys only allowed for Recno and Queue DB's");
482 return 0;
485 /* Make a key out of the requested recno, use allocated space so DB
486 * will be able to realloc room for the real key if needed. */
487 recno = NUMBER_AsLong(keyobj);
488 key->data = malloc(sizeof(db_recno_t));
489 if (key->data == NULL) {
490 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
491 return 0;
493 key->ulen = key->size = sizeof(db_recno_t);
494 memcpy(key->data, &recno, sizeof(db_recno_t));
495 key->flags = DB_DBT_REALLOC;
497 else {
498 PyErr_Format(PyExc_TypeError,
499 #if (PY_VERSION_HEX < 0x03000000)
500 "String or Integer object expected for key, %s found",
501 #else
502 "Bytes or Integer object expected for key, %s found",
503 #endif
504 Py_TYPE(keyobj)->tp_name);
505 return 0;
508 return 1;
512 /* Add partial record access to an existing DBT data struct.
513 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
514 and the data storage/retrieval will be done using dlen and doff. */
515 static int add_partial_dbt(DBT* d, int dlen, int doff) {
516 /* if neither were set we do nothing (-1 is the default value) */
517 if ((dlen == -1) && (doff == -1)) {
518 return 1;
521 if ((dlen < 0) || (doff < 0)) {
522 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
523 return 0;
526 d->flags = d->flags | DB_DBT_PARTIAL;
527 d->dlen = (unsigned int) dlen;
528 d->doff = (unsigned int) doff;
529 return 1;
532 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
533 /* TODO: make this use the native libc strlcpy() when available (BSD) */
534 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
536 unsigned int srclen, copylen;
538 srclen = strlen(src);
539 if (n <= 0)
540 return srclen;
541 copylen = (srclen > n-1) ? n-1 : srclen;
542 /* populate dest[0] thru dest[copylen-1] */
543 memcpy(dest, src, copylen);
544 /* guarantee null termination */
545 dest[copylen] = 0;
547 return srclen;
550 /* Callback used to save away more information about errors from the DB
551 * library. */
552 static char _db_errmsg[1024];
553 #if (DBVER <= 42)
554 static void _db_errorCallback(const char* prefix, char* msg)
555 #else
556 static void _db_errorCallback(const DB_ENV *db_env,
557 const char* prefix, const char* msg)
558 #endif
560 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
565 ** We need these functions because some results
566 ** are undefined if pointer is NULL. Some other
567 ** give None instead of "".
569 ** This functions are static and will be
570 ** -I hope- inlined.
572 static const char *DummyString = "This string is a simple placeholder";
573 static PyObject *Build_PyString(const char *p,int s)
575 if (!p) {
576 p=DummyString;
577 assert(s==0);
579 return PyBytes_FromStringAndSize(p,s);
582 static PyObject *BuildValue_S(const void *p,int s)
584 if (!p) {
585 p=DummyString;
586 assert(s==0);
588 return PyBytes_FromStringAndSize(p, s);
591 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
593 PyObject *a, *b, *r;
595 if (!p1) {
596 p1=DummyString;
597 assert(s1==0);
599 if (!p2) {
600 p2=DummyString;
601 assert(s2==0);
604 if (!(a = PyBytes_FromStringAndSize(p1, s1))) {
605 return NULL;
607 if (!(b = PyBytes_FromStringAndSize(p2, s2))) {
608 Py_DECREF(a);
609 return NULL;
612 #if (PY_VERSION_HEX >= 0x02040000)
613 r = PyTuple_Pack(2, a, b) ;
614 #else
615 r = Py_BuildValue("OO", a, b);
616 #endif
617 Py_DECREF(a);
618 Py_DECREF(b);
619 return r;
622 static PyObject *BuildValue_IS(int i,const void *p,int s)
624 PyObject *a, *r;
626 if (!p) {
627 p=DummyString;
628 assert(s==0);
631 if (!(a = PyBytes_FromStringAndSize(p, s))) {
632 return NULL;
635 r = Py_BuildValue("iO", i, a);
636 Py_DECREF(a);
637 return r;
640 static PyObject *BuildValue_LS(long l,const void *p,int s)
642 PyObject *a, *r;
644 if (!p) {
645 p=DummyString;
646 assert(s==0);
649 if (!(a = PyBytes_FromStringAndSize(p, s))) {
650 return NULL;
653 r = Py_BuildValue("lO", l, a);
654 Py_DECREF(a);
655 return r;
660 /* make a nice exception object to raise for errors. */
661 static int makeDBError(int err)
663 char errTxt[2048]; /* really big, just in case... */
664 PyObject *errObj = NULL;
665 PyObject *errTuple = NULL;
666 int exceptionRaised = 0;
667 unsigned int bytes_left;
669 switch (err) {
670 case 0: /* successful, no error */ break;
672 #if (DBVER < 41)
673 case DB_INCOMPLETE:
674 #if INCOMPLETE_IS_WARNING
675 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
676 /* Ensure that bytes_left never goes negative */
677 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
678 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
679 assert(bytes_left >= 0);
680 strcat(errTxt, " -- ");
681 strncat(errTxt, _db_errmsg, bytes_left);
683 _db_errmsg[0] = 0;
684 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
686 #else /* do an exception instead */
687 errObj = DBIncompleteError;
688 #endif
689 break;
690 #endif /* DBVER < 41 */
692 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
693 case DB_KEYEXIST: errObj = DBKeyExistError; break;
694 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
695 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
696 case DB_NOTFOUND: errObj = DBNotFoundError; break;
697 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
698 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
699 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
700 case DB_NOSERVER: errObj = DBNoServerError; break;
701 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
702 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
703 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
704 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
705 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
707 #if (DBVER >= 43)
708 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
709 case ENOMEM: errObj = PyExc_MemoryError; break;
710 #endif
711 case EINVAL: errObj = DBInvalidArgError; break;
712 case EACCES: errObj = DBAccessError; break;
713 case ENOSPC: errObj = DBNoSpaceError; break;
714 case EAGAIN: errObj = DBAgainError; break;
715 case EBUSY : errObj = DBBusyError; break;
716 case EEXIST: errObj = DBFileExistsError; break;
717 case ENOENT: errObj = DBNoSuchFileError; break;
718 case EPERM : errObj = DBPermissionsError; break;
720 #if (DBVER >= 42)
721 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
722 #endif
724 case DB_REP_UNAVAIL : errObj = DBRepUnavailError; break;
726 default: errObj = DBError; break;
729 if (errObj != NULL) {
730 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
731 /* Ensure that bytes_left never goes negative */
732 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
733 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
734 assert(bytes_left >= 0);
735 strcat(errTxt, " -- ");
736 strncat(errTxt, _db_errmsg, bytes_left);
738 _db_errmsg[0] = 0;
740 errTuple = Py_BuildValue("(is)", err, errTxt);
741 if (errTuple == NULL) {
742 Py_DECREF(errObj);
743 return !0;
745 PyErr_SetObject(errObj, errTuple);
746 Py_DECREF(errTuple);
749 return ((errObj != NULL) || exceptionRaised);
754 /* set a type exception */
755 static void makeTypeError(char* expected, PyObject* found)
757 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
758 expected, Py_TYPE(found)->tp_name);
762 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
763 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
765 if (txnobj == Py_None || txnobj == NULL) {
766 *txn = NULL;
767 return 1;
769 if (DBTxnObject_Check(txnobj)) {
770 *txn = ((DBTxnObject*)txnobj)->txn;
771 return 1;
773 else
774 makeTypeError("DBTxn", txnobj);
775 return 0;
779 /* Delete a key from a database
780 Returns 0 on success, -1 on an error. */
781 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
783 int err;
785 MYDB_BEGIN_ALLOW_THREADS;
786 err = self->db->del(self->db, txn, key, 0);
787 MYDB_END_ALLOW_THREADS;
788 if (makeDBError(err)) {
789 return -1;
791 self->haveStat = 0;
792 return 0;
796 /* Store a key into a database
797 Returns 0 on success, -1 on an error. */
798 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
800 int err;
802 MYDB_BEGIN_ALLOW_THREADS;
803 err = self->db->put(self->db, txn, key, data, flags);
804 MYDB_END_ALLOW_THREADS;
805 if (makeDBError(err)) {
806 return -1;
808 self->haveStat = 0;
809 return 0;
812 /* Get a key/data pair from a cursor */
813 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
814 PyObject *args, PyObject *kwargs, char *format)
816 int err;
817 PyObject* retval = NULL;
818 DBT key, data;
819 int dlen = -1;
820 int doff = -1;
821 int flags = 0;
822 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
824 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
825 &flags, &dlen, &doff))
826 return NULL;
828 CHECK_CURSOR_NOT_CLOSED(self);
830 flags |= extra_flags;
831 CLEAR_DBT(key);
832 CLEAR_DBT(data);
833 if (!add_partial_dbt(&data, dlen, doff))
834 return NULL;
836 MYDB_BEGIN_ALLOW_THREADS;
837 err = _DBC_get(self->dbc, &key, &data, flags);
838 MYDB_END_ALLOW_THREADS;
840 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
841 && self->mydb->moduleFlags.getReturnsNone) {
842 Py_INCREF(Py_None);
843 retval = Py_None;
845 else if (makeDBError(err)) {
846 retval = NULL;
848 else { /* otherwise, success! */
850 /* if Recno or Queue, return the key as an Int */
851 switch (_DB_get_type(self->mydb)) {
852 case -1:
853 retval = NULL;
854 break;
856 case DB_RECNO:
857 case DB_QUEUE:
858 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
859 break;
860 case DB_HASH:
861 case DB_BTREE:
862 default:
863 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
864 break;
867 return retval;
871 /* add an integer to a dictionary using the given name as a key */
872 static void _addIntToDict(PyObject* dict, char *name, int value)
874 PyObject* v = NUMBER_FromLong((long) value);
875 if (!v || PyDict_SetItemString(dict, name, v))
876 PyErr_Clear();
878 Py_XDECREF(v);
881 /* The same, when the value is a time_t */
882 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
884 PyObject* v;
885 /* if the value fits in regular int, use that. */
886 #ifdef PY_LONG_LONG
887 if (sizeof(time_t) > sizeof(long))
888 v = PyLong_FromLongLong((PY_LONG_LONG) value);
889 else
890 #endif
891 v = NUMBER_FromLong((long) value);
892 if (!v || PyDict_SetItemString(dict, name, v))
893 PyErr_Clear();
895 Py_XDECREF(v);
898 #if (DBVER >= 43)
899 /* add an db_seq_t to a dictionary using the given name as a key */
900 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
902 PyObject* v = PyLong_FromLongLong(value);
903 if (!v || PyDict_SetItemString(dict, name, v))
904 PyErr_Clear();
906 Py_XDECREF(v);
908 #endif
910 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
912 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
913 if (!v || PyDict_SetItemString(dict, name, v))
914 PyErr_Clear();
916 Py_XDECREF(v);
919 /* --------------------------------------------------------------------- */
920 /* Allocators and deallocators */
922 static DBObject*
923 newDBObject(DBEnvObject* arg, int flags)
925 DBObject* self;
926 DB_ENV* db_env = NULL;
927 int err;
929 self = PyObject_New(DBObject, &DB_Type);
930 if (self == NULL)
931 return NULL;
933 self->haveStat = 0;
934 self->flags = 0;
935 self->setflags = 0;
936 self->myenvobj = NULL;
937 self->db = NULL;
938 self->children_cursors = NULL;
939 #if (DBVER >=43)
940 self->children_sequences = NULL;
941 #endif
942 self->associateCallback = NULL;
943 self->btCompareCallback = NULL;
944 self->primaryDBType = 0;
945 Py_INCREF(Py_None);
946 self->private_obj = Py_None;
947 self->in_weakreflist = NULL;
949 /* keep a reference to our python DBEnv object */
950 if (arg) {
951 Py_INCREF(arg);
952 self->myenvobj = arg;
953 db_env = arg->db_env;
954 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
955 } else {
956 self->sibling_prev_p=NULL;
957 self->sibling_next=NULL;
959 self->txn=NULL;
960 self->sibling_prev_p_txn=NULL;
961 self->sibling_next_txn=NULL;
963 if (self->myenvobj)
964 self->moduleFlags = self->myenvobj->moduleFlags;
965 else
966 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
967 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
969 MYDB_BEGIN_ALLOW_THREADS;
970 err = db_create(&self->db, db_env, flags);
971 if (self->db != NULL) {
972 self->db->set_errcall(self->db, _db_errorCallback);
973 self->db->app_private = (void*)self;
975 MYDB_END_ALLOW_THREADS;
976 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
977 * list so that a DBEnv can refuse to close without aborting any open
978 * DBTxns and closing any open DBs first. */
979 if (makeDBError(err)) {
980 if (self->myenvobj) {
981 Py_DECREF(self->myenvobj);
982 self->myenvobj = NULL;
984 Py_DECREF(self);
985 self = NULL;
987 return self;
991 /* Forward declaration */
992 static PyObject *DB_close_internal(DBObject* self, int flags, int do_not_close);
994 static void
995 DB_dealloc(DBObject* self)
997 PyObject *dummy;
999 if (self->db != NULL) {
1000 dummy=DB_close_internal(self, 0, 0);
1002 ** Raising exceptions while doing
1003 ** garbage collection is a fatal error.
1005 if (dummy)
1006 Py_DECREF(dummy);
1007 else
1008 PyErr_Clear();
1010 if (self->in_weakreflist != NULL) {
1011 PyObject_ClearWeakRefs((PyObject *) self);
1013 if (self->myenvobj) {
1014 Py_DECREF(self->myenvobj);
1015 self->myenvobj = NULL;
1017 if (self->associateCallback != NULL) {
1018 Py_DECREF(self->associateCallback);
1019 self->associateCallback = NULL;
1021 if (self->btCompareCallback != NULL) {
1022 Py_DECREF(self->btCompareCallback);
1023 self->btCompareCallback = NULL;
1025 Py_DECREF(self->private_obj);
1026 PyObject_Del(self);
1029 static DBCursorObject*
1030 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
1032 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
1033 if (self == NULL)
1034 return NULL;
1036 self->dbc = dbc;
1037 self->mydb = db;
1039 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
1040 if (txn && ((PyObject *)txn!=Py_None)) {
1041 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
1042 self->txn=txn;
1043 } else {
1044 self->txn=NULL;
1047 self->in_weakreflist = NULL;
1048 Py_INCREF(self->mydb);
1049 return self;
1053 /* Forward declaration */
1054 static PyObject *DBC_close_internal(DBCursorObject* self);
1056 static void
1057 DBCursor_dealloc(DBCursorObject* self)
1059 PyObject *dummy;
1061 if (self->dbc != NULL) {
1062 dummy=DBC_close_internal(self);
1064 ** Raising exceptions while doing
1065 ** garbage collection is a fatal error.
1067 if (dummy)
1068 Py_DECREF(dummy);
1069 else
1070 PyErr_Clear();
1072 if (self->in_weakreflist != NULL) {
1073 PyObject_ClearWeakRefs((PyObject *) self);
1075 Py_DECREF(self->mydb);
1076 PyObject_Del(self);
1080 static DBEnvObject*
1081 newDBEnvObject(int flags)
1083 int err;
1084 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
1085 if (self == NULL)
1086 return NULL;
1088 self->db_env = NULL;
1089 self->closed = 1;
1090 self->flags = flags;
1091 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1092 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
1093 self->children_dbs = NULL;
1094 self->children_txns = NULL;
1095 Py_INCREF(Py_None);
1096 self->private_obj = Py_None;
1097 Py_INCREF(Py_None);
1098 self->rep_transport = Py_None;
1099 self->in_weakreflist = NULL;
1100 self->event_notifyCallback = NULL;
1102 MYDB_BEGIN_ALLOW_THREADS;
1103 err = db_env_create(&self->db_env, flags);
1104 MYDB_END_ALLOW_THREADS;
1105 if (makeDBError(err)) {
1106 Py_DECREF(self);
1107 self = NULL;
1109 else {
1110 self->db_env->set_errcall(self->db_env, _db_errorCallback);
1111 self->db_env->app_private = self;
1113 return self;
1116 /* Forward declaration */
1117 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
1119 static void
1120 DBEnv_dealloc(DBEnvObject* self)
1122 PyObject *dummy;
1124 if (self->db_env) {
1125 dummy=DBEnv_close_internal(self, 0);
1127 ** Raising exceptions while doing
1128 ** garbage collection is a fatal error.
1130 if (dummy)
1131 Py_DECREF(dummy);
1132 else
1133 PyErr_Clear();
1136 Py_XDECREF(self->event_notifyCallback);
1137 self->event_notifyCallback = NULL;
1139 if (self->in_weakreflist != NULL) {
1140 PyObject_ClearWeakRefs((PyObject *) self);
1142 Py_DECREF(self->private_obj);
1143 Py_DECREF(self->rep_transport);
1144 PyObject_Del(self);
1148 static DBTxnObject*
1149 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
1151 int err;
1152 DB_TXN *parent_txn = NULL;
1154 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
1155 if (self == NULL)
1156 return NULL;
1158 self->in_weakreflist = NULL;
1159 self->children_txns = NULL;
1160 self->children_dbs = NULL;
1161 self->children_cursors = NULL;
1162 self->children_sequences = NULL;
1163 self->flag_prepare = 0;
1164 self->parent_txn = NULL;
1165 self->env = NULL;
1167 if (parent && ((PyObject *)parent!=Py_None)) {
1168 parent_txn = parent->txn;
1171 if (txn) {
1172 self->txn = txn;
1173 } else {
1174 MYDB_BEGIN_ALLOW_THREADS;
1175 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1176 MYDB_END_ALLOW_THREADS;
1178 if (makeDBError(err)) {
1179 Py_DECREF(self);
1180 return NULL;
1184 /* Can't use 'parent' because could be 'parent==Py_None' */
1185 if (parent_txn) {
1186 self->parent_txn = parent;
1187 Py_INCREF(parent);
1188 self->env = NULL;
1189 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
1190 } else {
1191 self->parent_txn = NULL;
1192 Py_INCREF(myenv);
1193 self->env = myenv;
1194 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
1197 return self;
1200 /* Forward declaration */
1201 static PyObject *
1202 DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
1204 static void
1205 DBTxn_dealloc(DBTxnObject* self)
1207 PyObject *dummy;
1209 if (self->txn) {
1210 int flag_prepare = self->flag_prepare;
1212 dummy=DBTxn_abort_discard_internal(self,0);
1214 ** Raising exceptions while doing
1215 ** garbage collection is a fatal error.
1217 if (dummy)
1218 Py_DECREF(dummy);
1219 else
1220 PyErr_Clear();
1222 if (!flag_prepare) {
1223 PyErr_Warn(PyExc_RuntimeWarning,
1224 "DBTxn aborted in destructor. No prior commit() or abort().");
1228 if (self->in_weakreflist != NULL) {
1229 PyObject_ClearWeakRefs((PyObject *) self);
1232 if (self->env) {
1233 Py_DECREF(self->env);
1234 } else {
1235 Py_DECREF(self->parent_txn);
1237 PyObject_Del(self);
1241 static DBLockObject*
1242 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1243 db_lockmode_t lock_mode, int flags)
1245 int err;
1246 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1247 if (self == NULL)
1248 return NULL;
1249 self->in_weakreflist = NULL;
1251 MYDB_BEGIN_ALLOW_THREADS;
1252 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1253 &self->lock);
1254 MYDB_END_ALLOW_THREADS;
1255 if (makeDBError(err)) {
1256 Py_DECREF(self);
1257 self = NULL;
1260 return self;
1264 static void
1265 DBLock_dealloc(DBLockObject* self)
1267 if (self->in_weakreflist != NULL) {
1268 PyObject_ClearWeakRefs((PyObject *) self);
1270 /* TODO: is this lock held? should we release it? */
1272 PyObject_Del(self);
1276 #if (DBVER >= 43)
1277 static DBSequenceObject*
1278 newDBSequenceObject(DBObject* mydb, int flags)
1280 int err;
1281 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1282 if (self == NULL)
1283 return NULL;
1284 Py_INCREF(mydb);
1285 self->mydb = mydb;
1287 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1288 self->txn = NULL;
1290 self->in_weakreflist = NULL;
1292 MYDB_BEGIN_ALLOW_THREADS;
1293 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1294 MYDB_END_ALLOW_THREADS;
1295 if (makeDBError(err)) {
1296 Py_DECREF(self);
1297 self = NULL;
1300 return self;
1303 /* Forward declaration */
1304 static PyObject
1305 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
1307 static void
1308 DBSequence_dealloc(DBSequenceObject* self)
1310 PyObject *dummy;
1312 if (self->sequence != NULL) {
1313 dummy=DBSequence_close_internal(self,0,0);
1315 ** Raising exceptions while doing
1316 ** garbage collection is a fatal error.
1318 if (dummy)
1319 Py_DECREF(dummy);
1320 else
1321 PyErr_Clear();
1324 if (self->in_weakreflist != NULL) {
1325 PyObject_ClearWeakRefs((PyObject *) self);
1328 Py_DECREF(self->mydb);
1329 PyObject_Del(self);
1331 #endif
1333 /* --------------------------------------------------------------------- */
1334 /* DB methods */
1336 static PyObject*
1337 DB_append(DBObject* self, PyObject* args, PyObject* kwargs)
1339 PyObject* txnobj = NULL;
1340 PyObject* dataobj;
1341 db_recno_t recno;
1342 DBT key, data;
1343 DB_TXN *txn = NULL;
1344 static char* kwnames[] = { "data", "txn", NULL };
1346 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:append", kwnames,
1347 &dataobj, &txnobj))
1348 return NULL;
1350 CHECK_DB_NOT_CLOSED(self);
1352 /* make a dummy key out of a recno */
1353 recno = 0;
1354 CLEAR_DBT(key);
1355 key.data = &recno;
1356 key.size = sizeof(recno);
1357 key.ulen = key.size;
1358 key.flags = DB_DBT_USERMEM;
1360 if (!make_dbt(dataobj, &data)) return NULL;
1361 if (!checkTxnObj(txnobj, &txn)) return NULL;
1363 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1364 return NULL;
1366 return NUMBER_FromLong(recno);
1370 static int
1371 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1372 DBT* secKey)
1374 int retval = DB_DONOTINDEX;
1375 DBObject* secondaryDB = (DBObject*)db->app_private;
1376 PyObject* callback = secondaryDB->associateCallback;
1377 int type = secondaryDB->primaryDBType;
1378 PyObject* args;
1379 PyObject* result = NULL;
1382 if (callback != NULL) {
1383 MYDB_BEGIN_BLOCK_THREADS;
1385 if (type == DB_RECNO || type == DB_QUEUE)
1386 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
1387 else
1388 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
1389 if (args != NULL) {
1390 result = PyEval_CallObject(callback, args);
1392 if (args == NULL || result == NULL) {
1393 PyErr_Print();
1395 else if (result == Py_None) {
1396 retval = DB_DONOTINDEX;
1398 else if (NUMBER_Check(result)) {
1399 retval = NUMBER_AsLong(result);
1401 else if (PyBytes_Check(result)) {
1402 char* data;
1403 Py_ssize_t size;
1405 CLEAR_DBT(*secKey);
1406 PyBytes_AsStringAndSize(result, &data, &size);
1407 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1408 secKey->data = malloc(size); /* TODO, check this */
1409 if (secKey->data) {
1410 memcpy(secKey->data, data, size);
1411 secKey->size = size;
1412 retval = 0;
1414 else {
1415 PyErr_SetString(PyExc_MemoryError,
1416 "malloc failed in _db_associateCallback");
1417 PyErr_Print();
1420 else {
1421 PyErr_SetString(
1422 PyExc_TypeError,
1423 "DB associate callback should return DB_DONOTINDEX or string.");
1424 PyErr_Print();
1427 Py_XDECREF(args);
1428 Py_XDECREF(result);
1430 MYDB_END_BLOCK_THREADS;
1432 return retval;
1436 static PyObject*
1437 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1439 int err, flags=0;
1440 DBObject* secondaryDB;
1441 PyObject* callback;
1442 #if (DBVER >= 41)
1443 PyObject *txnobj = NULL;
1444 DB_TXN *txn = NULL;
1445 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1446 NULL};
1447 #else
1448 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1449 #endif
1451 #if (DBVER >= 41)
1452 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1453 &secondaryDB, &callback, &flags,
1454 &txnobj)) {
1455 #else
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1457 &secondaryDB, &callback, &flags)) {
1458 #endif
1459 return NULL;
1462 #if (DBVER >= 41)
1463 if (!checkTxnObj(txnobj, &txn)) return NULL;
1464 #endif
1466 CHECK_DB_NOT_CLOSED(self);
1467 if (!DBObject_Check(secondaryDB)) {
1468 makeTypeError("DB", (PyObject*)secondaryDB);
1469 return NULL;
1471 CHECK_DB_NOT_CLOSED(secondaryDB);
1472 if (callback == Py_None) {
1473 callback = NULL;
1475 else if (!PyCallable_Check(callback)) {
1476 makeTypeError("Callable", callback);
1477 return NULL;
1480 /* Save a reference to the callback in the secondary DB. */
1481 Py_XDECREF(secondaryDB->associateCallback);
1482 Py_XINCREF(callback);
1483 secondaryDB->associateCallback = callback;
1484 secondaryDB->primaryDBType = _DB_get_type(self);
1486 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1487 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1488 * The global interepreter lock is not initialized until the first
1489 * thread is created using thread.start_new_thread() or fork() is
1490 * called. that would cause the ALLOW_THREADS here to segfault due
1491 * to a null pointer reference if no threads or child processes
1492 * have been created. This works around that and is a no-op if
1493 * threads have already been initialized.
1494 * (see pybsddb-users mailing list post on 2002-08-07)
1496 #ifdef WITH_THREAD
1497 PyEval_InitThreads();
1498 #endif
1499 MYDB_BEGIN_ALLOW_THREADS;
1500 #if (DBVER >= 41)
1501 err = self->db->associate(self->db,
1502 txn,
1503 secondaryDB->db,
1504 _db_associateCallback,
1505 flags);
1506 #else
1507 err = self->db->associate(self->db,
1508 secondaryDB->db,
1509 _db_associateCallback,
1510 flags);
1511 #endif
1512 MYDB_END_ALLOW_THREADS;
1514 if (err) {
1515 Py_XDECREF(secondaryDB->associateCallback);
1516 secondaryDB->associateCallback = NULL;
1517 secondaryDB->primaryDBType = 0;
1520 RETURN_IF_ERR();
1521 RETURN_NONE();
1525 static PyObject*
1526 DB_close_internal(DBObject* self, int flags, int do_not_close)
1528 PyObject *dummy;
1529 int err = 0;
1531 if (self->db != NULL) {
1532 /* Can be NULL if db is not in an environment */
1533 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1535 if (self->txn) {
1536 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1537 self->txn=NULL;
1540 while(self->children_cursors) {
1541 dummy=DBC_close_internal(self->children_cursors);
1542 Py_XDECREF(dummy);
1545 #if (DBVER >= 43)
1546 while(self->children_sequences) {
1547 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1548 Py_XDECREF(dummy);
1550 #endif
1553 ** "do_not_close" is used to dispose all related objects in the
1554 ** tree, without actually releasing the "root" object.
1555 ** This is done, for example, because function calls like
1556 ** "DB.verify()" implicitly close the underlying handle. So
1557 ** the handle doesn't need to be closed, but related objects
1558 ** must be cleaned up.
1560 if (!do_not_close) {
1561 MYDB_BEGIN_ALLOW_THREADS;
1562 err = self->db->close(self->db, flags);
1563 MYDB_END_ALLOW_THREADS;
1564 self->db = NULL;
1566 RETURN_IF_ERR();
1568 RETURN_NONE();
1571 static PyObject*
1572 DB_close(DBObject* self, PyObject* args)
1574 int flags=0;
1575 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1576 return NULL;
1577 return DB_close_internal(self, flags, 0);
1581 static PyObject*
1582 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1584 int err, flags=0, type;
1585 PyObject* txnobj = NULL;
1586 PyObject* retval = NULL;
1587 DBT key, data;
1588 DB_TXN *txn = NULL;
1589 static char* kwnames[] = { "txn", "flags", NULL };
1591 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1592 &txnobj, &flags))
1593 return NULL;
1595 CHECK_DB_NOT_CLOSED(self);
1596 type = _DB_get_type(self);
1597 if (type == -1)
1598 return NULL;
1599 if (type != DB_QUEUE) {
1600 PyErr_SetString(PyExc_TypeError,
1601 "Consume methods only allowed for Queue DB's");
1602 return NULL;
1604 if (!checkTxnObj(txnobj, &txn))
1605 return NULL;
1607 CLEAR_DBT(key);
1608 CLEAR_DBT(data);
1609 if (CHECK_DBFLAG(self, DB_THREAD)) {
1610 /* Tell Berkeley DB to malloc the return value (thread safe) */
1611 data.flags = DB_DBT_MALLOC;
1612 key.flags = DB_DBT_MALLOC;
1615 MYDB_BEGIN_ALLOW_THREADS;
1616 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1617 MYDB_END_ALLOW_THREADS;
1619 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1620 && self->moduleFlags.getReturnsNone) {
1621 err = 0;
1622 Py_INCREF(Py_None);
1623 retval = Py_None;
1625 else if (!err) {
1626 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1627 FREE_DBT(key);
1628 FREE_DBT(data);
1631 RETURN_IF_ERR();
1632 return retval;
1635 static PyObject*
1636 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1638 return _DB_consume(self, args, kwargs, DB_CONSUME);
1641 static PyObject*
1642 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1643 int consume_flag)
1645 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1649 static PyObject*
1650 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1652 int err, flags=0;
1653 DBC* dbc;
1654 PyObject* txnobj = NULL;
1655 DB_TXN *txn = NULL;
1656 static char* kwnames[] = { "txn", "flags", NULL };
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1659 &txnobj, &flags))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!checkTxnObj(txnobj, &txn))
1663 return NULL;
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->cursor(self->db, txn, &dbc, flags);
1667 MYDB_END_ALLOW_THREADS;
1668 RETURN_IF_ERR();
1669 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
1673 static PyObject*
1674 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1676 PyObject* txnobj = NULL;
1677 int flags = 0;
1678 PyObject* keyobj;
1679 DBT key;
1680 DB_TXN *txn = NULL;
1681 static char* kwnames[] = { "key", "txn", "flags", NULL };
1683 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1684 &keyobj, &txnobj, &flags))
1685 return NULL;
1686 CHECK_DB_NOT_CLOSED(self);
1687 if (!make_key_dbt(self, keyobj, &key, NULL))
1688 return NULL;
1689 if (!checkTxnObj(txnobj, &txn)) {
1690 FREE_DBT(key);
1691 return NULL;
1694 if (-1 == _DB_delete(self, txn, &key, 0)) {
1695 FREE_DBT(key);
1696 return NULL;
1699 FREE_DBT(key);
1700 RETURN_NONE();
1704 static PyObject*
1705 DB_fd(DBObject* self)
1707 int err, the_fd;
1709 CHECK_DB_NOT_CLOSED(self);
1711 MYDB_BEGIN_ALLOW_THREADS;
1712 err = self->db->fd(self->db, &the_fd);
1713 MYDB_END_ALLOW_THREADS;
1714 RETURN_IF_ERR();
1715 return NUMBER_FromLong(the_fd);
1719 static PyObject*
1720 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1722 int err, flags=0;
1723 PyObject* txnobj = NULL;
1724 PyObject* keyobj;
1725 PyObject* dfltobj = NULL;
1726 PyObject* retval = NULL;
1727 int dlen = -1;
1728 int doff = -1;
1729 DBT key, data;
1730 DB_TXN *txn = NULL;
1731 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1732 "doff", NULL};
1734 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1735 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1736 &doff))
1737 return NULL;
1739 CHECK_DB_NOT_CLOSED(self);
1740 if (!make_key_dbt(self, keyobj, &key, &flags))
1741 return NULL;
1742 if (!checkTxnObj(txnobj, &txn)) {
1743 FREE_DBT(key);
1744 return NULL;
1747 CLEAR_DBT(data);
1748 if (CHECK_DBFLAG(self, DB_THREAD)) {
1749 /* Tell Berkeley DB to malloc the return value (thread safe) */
1750 data.flags = DB_DBT_MALLOC;
1752 if (!add_partial_dbt(&data, dlen, doff)) {
1753 FREE_DBT(key);
1754 return NULL;
1757 MYDB_BEGIN_ALLOW_THREADS;
1758 err = self->db->get(self->db, txn, &key, &data, flags);
1759 MYDB_END_ALLOW_THREADS;
1761 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1762 err = 0;
1763 Py_INCREF(dfltobj);
1764 retval = dfltobj;
1766 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1767 && self->moduleFlags.getReturnsNone) {
1768 err = 0;
1769 Py_INCREF(Py_None);
1770 retval = Py_None;
1772 else if (!err) {
1773 if (flags & DB_SET_RECNO) /* return both key and data */
1774 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1775 else /* return just the data */
1776 retval = Build_PyString(data.data, data.size);
1777 FREE_DBT(data);
1779 FREE_DBT(key);
1781 RETURN_IF_ERR();
1782 return retval;
1785 static PyObject*
1786 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1788 int err, flags=0;
1789 PyObject* txnobj = NULL;
1790 PyObject* keyobj;
1791 PyObject* dfltobj = NULL;
1792 PyObject* retval = NULL;
1793 int dlen = -1;
1794 int doff = -1;
1795 DBT key, pkey, data;
1796 DB_TXN *txn = NULL;
1797 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1798 "doff", NULL};
1800 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1801 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1802 &doff))
1803 return NULL;
1805 CHECK_DB_NOT_CLOSED(self);
1806 if (!make_key_dbt(self, keyobj, &key, &flags))
1807 return NULL;
1808 if (!checkTxnObj(txnobj, &txn)) {
1809 FREE_DBT(key);
1810 return NULL;
1813 CLEAR_DBT(data);
1814 if (CHECK_DBFLAG(self, DB_THREAD)) {
1815 /* Tell Berkeley DB to malloc the return value (thread safe) */
1816 data.flags = DB_DBT_MALLOC;
1818 if (!add_partial_dbt(&data, dlen, doff)) {
1819 FREE_DBT(key);
1820 return NULL;
1823 CLEAR_DBT(pkey);
1824 pkey.flags = DB_DBT_MALLOC;
1826 MYDB_BEGIN_ALLOW_THREADS;
1827 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1828 MYDB_END_ALLOW_THREADS;
1830 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1831 err = 0;
1832 Py_INCREF(dfltobj);
1833 retval = dfltobj;
1835 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1836 && self->moduleFlags.getReturnsNone) {
1837 err = 0;
1838 Py_INCREF(Py_None);
1839 retval = Py_None;
1841 else if (!err) {
1842 PyObject *pkeyObj;
1843 PyObject *dataObj;
1844 dataObj = Build_PyString(data.data, data.size);
1846 if (self->primaryDBType == DB_RECNO ||
1847 self->primaryDBType == DB_QUEUE)
1848 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
1849 else
1850 pkeyObj = Build_PyString(pkey.data, pkey.size);
1852 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1854 PyObject *keyObj;
1855 int type = _DB_get_type(self);
1856 if (type == DB_RECNO || type == DB_QUEUE)
1857 keyObj = NUMBER_FromLong(*(int *)key.data);
1858 else
1859 keyObj = Build_PyString(key.data, key.size);
1860 #if (PY_VERSION_HEX >= 0x02040000)
1861 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1862 #else
1863 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1864 #endif
1865 Py_DECREF(keyObj);
1867 else /* return just the pkey and data */
1869 #if (PY_VERSION_HEX >= 0x02040000)
1870 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1871 #else
1872 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1873 #endif
1875 Py_DECREF(dataObj);
1876 Py_DECREF(pkeyObj);
1877 FREE_DBT(pkey);
1878 FREE_DBT(data);
1880 FREE_DBT(key);
1882 RETURN_IF_ERR();
1883 return retval;
1887 /* Return size of entry */
1888 static PyObject*
1889 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1891 int err, flags=0;
1892 PyObject* txnobj = NULL;
1893 PyObject* keyobj;
1894 PyObject* retval = NULL;
1895 DBT key, data;
1896 DB_TXN *txn = NULL;
1897 static char* kwnames[] = { "key", "txn", NULL };
1899 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1900 &keyobj, &txnobj))
1901 return NULL;
1902 CHECK_DB_NOT_CLOSED(self);
1903 if (!make_key_dbt(self, keyobj, &key, &flags))
1904 return NULL;
1905 if (!checkTxnObj(txnobj, &txn)) {
1906 FREE_DBT(key);
1907 return NULL;
1909 CLEAR_DBT(data);
1911 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1912 thus getting the record size. */
1913 data.flags = DB_DBT_USERMEM;
1914 data.ulen = 0;
1915 MYDB_BEGIN_ALLOW_THREADS;
1916 err = self->db->get(self->db, txn, &key, &data, flags);
1917 MYDB_END_ALLOW_THREADS;
1918 if (err == DB_BUFFER_SMALL) {
1919 retval = NUMBER_FromLong((long)data.size);
1920 err = 0;
1923 FREE_DBT(key);
1924 FREE_DBT(data);
1925 RETURN_IF_ERR();
1926 return retval;
1930 static PyObject*
1931 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1933 int err, flags=0;
1934 PyObject* txnobj = NULL;
1935 PyObject* keyobj;
1936 PyObject* dataobj;
1937 PyObject* retval = NULL;
1938 DBT key, data;
1939 void *orig_data;
1940 DB_TXN *txn = NULL;
1941 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1943 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1944 &keyobj, &dataobj, &txnobj, &flags))
1945 return NULL;
1947 CHECK_DB_NOT_CLOSED(self);
1948 if (!make_key_dbt(self, keyobj, &key, NULL))
1949 return NULL;
1950 if ( !make_dbt(dataobj, &data) ||
1951 !checkTxnObj(txnobj, &txn) )
1953 FREE_DBT(key);
1954 return NULL;
1957 flags |= DB_GET_BOTH;
1958 orig_data = data.data;
1960 if (CHECK_DBFLAG(self, DB_THREAD)) {
1961 /* Tell Berkeley DB to malloc the return value (thread safe) */
1962 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1963 data.flags = DB_DBT_MALLOC;
1966 MYDB_BEGIN_ALLOW_THREADS;
1967 err = self->db->get(self->db, txn, &key, &data, flags);
1968 MYDB_END_ALLOW_THREADS;
1970 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1971 && self->moduleFlags.getReturnsNone) {
1972 err = 0;
1973 Py_INCREF(Py_None);
1974 retval = Py_None;
1976 else if (!err) {
1977 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1978 retval = Build_PyString(data.data, data.size);
1980 /* Even though the flags require DB_DBT_MALLOC, data is not always
1981 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1982 if (data.data != orig_data)
1983 FREE_DBT(data);
1986 FREE_DBT(key);
1987 RETURN_IF_ERR();
1988 return retval;
1992 static PyObject*
1993 DB_get_byteswapped(DBObject* self)
1995 int err = 0;
1996 int retval = -1;
1998 CHECK_DB_NOT_CLOSED(self);
2000 MYDB_BEGIN_ALLOW_THREADS;
2001 err = self->db->get_byteswapped(self->db, &retval);
2002 MYDB_END_ALLOW_THREADS;
2003 RETURN_IF_ERR();
2004 return NUMBER_FromLong(retval);
2008 static PyObject*
2009 DB_get_type(DBObject* self)
2011 int type;
2013 CHECK_DB_NOT_CLOSED(self);
2015 type = _DB_get_type(self);
2016 if (type == -1)
2017 return NULL;
2018 return NUMBER_FromLong(type);
2022 static PyObject*
2023 DB_join(DBObject* self, PyObject* args)
2025 int err, flags=0;
2026 int length, x;
2027 PyObject* cursorsObj;
2028 DBC** cursors;
2029 DBC* dbc;
2031 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
2032 return NULL;
2034 CHECK_DB_NOT_CLOSED(self);
2036 if (!PySequence_Check(cursorsObj)) {
2037 PyErr_SetString(PyExc_TypeError,
2038 "Sequence of DBCursor objects expected");
2039 return NULL;
2042 length = PyObject_Length(cursorsObj);
2043 cursors = malloc((length+1) * sizeof(DBC*));
2044 if (!cursors) {
2045 PyErr_NoMemory();
2046 return NULL;
2049 cursors[length] = NULL;
2050 for (x=0; x<length; x++) {
2051 PyObject* item = PySequence_GetItem(cursorsObj, x);
2052 if (item == NULL) {
2053 free(cursors);
2054 return NULL;
2056 if (!DBCursorObject_Check(item)) {
2057 PyErr_SetString(PyExc_TypeError,
2058 "Sequence of DBCursor objects expected");
2059 free(cursors);
2060 return NULL;
2062 cursors[x] = ((DBCursorObject*)item)->dbc;
2063 Py_DECREF(item);
2066 MYDB_BEGIN_ALLOW_THREADS;
2067 err = self->db->join(self->db, cursors, &dbc, flags);
2068 MYDB_END_ALLOW_THREADS;
2069 free(cursors);
2070 RETURN_IF_ERR();
2072 /* FIXME: this is a buggy interface. The returned cursor
2073 contains internal references to the passed in cursors
2074 but does not hold python references to them or prevent
2075 them from being closed prematurely. This can cause
2076 python to crash when things are done in the wrong order. */
2077 return (PyObject*) newDBCursorObject(dbc, NULL, self);
2081 static PyObject*
2082 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
2084 int err, flags=0;
2085 PyObject* txnobj = NULL;
2086 PyObject* keyobj;
2087 DBT key;
2088 DB_TXN *txn = NULL;
2089 DB_KEY_RANGE range;
2090 static char* kwnames[] = { "key", "txn", "flags", NULL };
2092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2093 &keyobj, &txnobj, &flags))
2094 return NULL;
2095 CHECK_DB_NOT_CLOSED(self);
2096 if (!make_dbt(keyobj, &key))
2097 /* BTree only, don't need to allow for an int key */
2098 return NULL;
2099 if (!checkTxnObj(txnobj, &txn))
2100 return NULL;
2102 MYDB_BEGIN_ALLOW_THREADS;
2103 err = self->db->key_range(self->db, txn, &key, &range, flags);
2104 MYDB_END_ALLOW_THREADS;
2106 RETURN_IF_ERR();
2107 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2111 static PyObject*
2112 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2114 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2115 char* filename = NULL;
2116 char* dbname = NULL;
2117 #if (DBVER >= 41)
2118 PyObject *txnobj = NULL;
2119 DB_TXN *txn = NULL;
2120 /* with dbname */
2121 static char* kwnames[] = {
2122 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2123 /* without dbname */
2124 static char* kwnames_basic[] = {
2125 "filename", "dbtype", "flags", "mode", "txn", NULL};
2126 #else
2127 /* with dbname */
2128 static char* kwnames[] = {
2129 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2130 /* without dbname */
2131 static char* kwnames_basic[] = {
2132 "filename", "dbtype", "flags", "mode", NULL};
2133 #endif
2135 #if (DBVER >= 41)
2136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2137 &filename, &dbname, &type, &flags, &mode,
2138 &txnobj))
2139 #else
2140 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
2141 &filename, &dbname, &type, &flags,
2142 &mode))
2143 #endif
2145 PyErr_Clear();
2146 type = DB_UNKNOWN; flags = 0; mode = 0660;
2147 filename = NULL; dbname = NULL;
2148 #if (DBVER >= 41)
2149 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2150 kwnames_basic,
2151 &filename, &type, &flags, &mode,
2152 &txnobj))
2153 return NULL;
2154 #else
2155 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2156 kwnames_basic,
2157 &filename, &type, &flags, &mode))
2158 return NULL;
2159 #endif
2162 #if (DBVER >= 41)
2163 if (!checkTxnObj(txnobj, &txn)) return NULL;
2164 #endif
2166 if (NULL == self->db) {
2167 PyObject *t = Py_BuildValue("(is)", 0,
2168 "Cannot call open() twice for DB object");
2169 if (t) {
2170 PyErr_SetObject(DBError, t);
2171 Py_DECREF(t);
2173 return NULL;
2176 #if (DBVER >= 41)
2177 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2178 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2179 self->txn=(DBTxnObject *)txnobj;
2180 } else {
2181 self->txn=NULL;
2183 #else
2184 self->txn=NULL;
2185 #endif
2187 MYDB_BEGIN_ALLOW_THREADS;
2188 #if (DBVER >= 41)
2189 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2190 #else
2191 err = self->db->open(self->db, filename, dbname, type, flags, mode);
2192 #endif
2193 MYDB_END_ALLOW_THREADS;
2194 if (makeDBError(err)) {
2195 PyObject *dummy;
2197 dummy=DB_close_internal(self, 0, 0);
2198 Py_XDECREF(dummy);
2199 return NULL;
2202 #if (DBVER >= 42)
2203 self->db->get_flags(self->db, &self->setflags);
2204 #endif
2206 self->flags = flags;
2208 RETURN_NONE();
2212 static PyObject*
2213 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2215 int flags=0;
2216 PyObject* txnobj = NULL;
2217 int dlen = -1;
2218 int doff = -1;
2219 PyObject* keyobj, *dataobj, *retval;
2220 DBT key, data;
2221 DB_TXN *txn = NULL;
2222 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
2223 "doff", NULL };
2225 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2226 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2227 return NULL;
2229 CHECK_DB_NOT_CLOSED(self);
2230 if (!make_key_dbt(self, keyobj, &key, NULL))
2231 return NULL;
2232 if ( !make_dbt(dataobj, &data) ||
2233 !add_partial_dbt(&data, dlen, doff) ||
2234 !checkTxnObj(txnobj, &txn) )
2236 FREE_DBT(key);
2237 return NULL;
2240 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2241 FREE_DBT(key);
2242 return NULL;
2245 if (flags & DB_APPEND)
2246 retval = NUMBER_FromLong(*((db_recno_t*)key.data));
2247 else {
2248 retval = Py_None;
2249 Py_INCREF(retval);
2251 FREE_DBT(key);
2252 return retval;
2257 static PyObject*
2258 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2260 char* filename;
2261 char* database = NULL;
2262 int err, flags=0;
2263 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2266 &filename, &database, &flags))
2267 return NULL;
2268 CHECK_DB_NOT_CLOSED(self);
2270 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
2272 MYDB_BEGIN_ALLOW_THREADS;
2273 err = self->db->remove(self->db, filename, database, flags);
2274 MYDB_END_ALLOW_THREADS;
2276 self->db = NULL;
2277 RETURN_IF_ERR();
2278 RETURN_NONE();
2283 static PyObject*
2284 DB_rename(DBObject* self, PyObject* args)
2286 char* filename;
2287 char* database;
2288 char* newname;
2289 int err, flags=0;
2291 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2292 &flags))
2293 return NULL;
2294 CHECK_DB_NOT_CLOSED(self);
2296 MYDB_BEGIN_ALLOW_THREADS;
2297 err = self->db->rename(self->db, filename, database, newname, flags);
2298 MYDB_END_ALLOW_THREADS;
2299 RETURN_IF_ERR();
2300 RETURN_NONE();
2304 static PyObject*
2305 DB_get_private(DBObject* self)
2307 /* We can give out the private field even if db is closed */
2308 Py_INCREF(self->private_obj);
2309 return self->private_obj;
2312 static PyObject*
2313 DB_set_private(DBObject* self, PyObject* private_obj)
2315 /* We can set the private field even if db is closed */
2316 Py_DECREF(self->private_obj);
2317 Py_INCREF(private_obj);
2318 self->private_obj = private_obj;
2319 RETURN_NONE();
2323 static PyObject*
2324 DB_set_bt_minkey(DBObject* self, PyObject* args)
2326 int err, minkey;
2328 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2329 return NULL;
2330 CHECK_DB_NOT_CLOSED(self);
2332 MYDB_BEGIN_ALLOW_THREADS;
2333 err = self->db->set_bt_minkey(self->db, minkey);
2334 MYDB_END_ALLOW_THREADS;
2335 RETURN_IF_ERR();
2336 RETURN_NONE();
2339 static int
2340 _default_cmp(const DBT *leftKey,
2341 const DBT *rightKey)
2343 int res;
2344 int lsize = leftKey->size, rsize = rightKey->size;
2346 res = memcmp(leftKey->data, rightKey->data,
2347 lsize < rsize ? lsize : rsize);
2349 if (res == 0) {
2350 if (lsize < rsize) {
2351 res = -1;
2353 else if (lsize > rsize) {
2354 res = 1;
2357 return res;
2360 static int
2361 _db_compareCallback(DB* db,
2362 const DBT *leftKey,
2363 const DBT *rightKey)
2365 int res = 0;
2366 PyObject *args;
2367 PyObject *result = NULL;
2368 DBObject *self = (DBObject *)db->app_private;
2370 if (self == NULL || self->btCompareCallback == NULL) {
2371 MYDB_BEGIN_BLOCK_THREADS;
2372 PyErr_SetString(PyExc_TypeError,
2373 (self == 0
2374 ? "DB_bt_compare db is NULL."
2375 : "DB_bt_compare callback is NULL."));
2376 /* we're in a callback within the DB code, we can't raise */
2377 PyErr_Print();
2378 res = _default_cmp(leftKey, rightKey);
2379 MYDB_END_BLOCK_THREADS;
2380 } else {
2381 MYDB_BEGIN_BLOCK_THREADS;
2383 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
2384 if (args != NULL) {
2385 /* XXX(twouters) I highly doubt this INCREF is correct */
2386 Py_INCREF(self);
2387 result = PyEval_CallObject(self->btCompareCallback, args);
2389 if (args == NULL || result == NULL) {
2390 /* we're in a callback within the DB code, we can't raise */
2391 PyErr_Print();
2392 res = _default_cmp(leftKey, rightKey);
2393 } else if (NUMBER_Check(result)) {
2394 res = NUMBER_AsLong(result);
2395 } else {
2396 PyErr_SetString(PyExc_TypeError,
2397 "DB_bt_compare callback MUST return an int.");
2398 /* we're in a callback within the DB code, we can't raise */
2399 PyErr_Print();
2400 res = _default_cmp(leftKey, rightKey);
2403 Py_XDECREF(args);
2404 Py_XDECREF(result);
2406 MYDB_END_BLOCK_THREADS;
2408 return res;
2411 static PyObject*
2412 DB_set_bt_compare(DBObject* self, PyObject* comparator)
2414 int err;
2415 PyObject *tuple, *result;
2417 CHECK_DB_NOT_CLOSED(self);
2419 if (!PyCallable_Check(comparator)) {
2420 makeTypeError("Callable", comparator);
2421 return NULL;
2425 * Perform a test call of the comparator function with two empty
2426 * string objects here. verify that it returns an int (0).
2427 * err if not.
2429 tuple = Py_BuildValue("(ss)", "", "");
2430 result = PyEval_CallObject(comparator, tuple);
2431 Py_DECREF(tuple);
2432 if (result == NULL)
2433 return NULL;
2434 if (!NUMBER_Check(result)) {
2435 PyErr_SetString(PyExc_TypeError,
2436 "callback MUST return an int");
2437 return NULL;
2438 } else if (NUMBER_AsLong(result) != 0) {
2439 PyErr_SetString(PyExc_TypeError,
2440 "callback failed to return 0 on two empty strings");
2441 return NULL;
2443 Py_DECREF(result);
2445 /* We don't accept multiple set_bt_compare operations, in order to
2446 * simplify the code. This would have no real use, as one cannot
2447 * change the function once the db is opened anyway */
2448 if (self->btCompareCallback != NULL) {
2449 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2450 return NULL;
2453 Py_INCREF(comparator);
2454 self->btCompareCallback = comparator;
2456 /* This is to workaround a problem with un-initialized threads (see
2457 comment in DB_associate) */
2458 #ifdef WITH_THREAD
2459 PyEval_InitThreads();
2460 #endif
2462 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2464 if (err) {
2465 /* restore the old state in case of error */
2466 Py_DECREF(comparator);
2467 self->btCompareCallback = NULL;
2470 RETURN_IF_ERR();
2471 RETURN_NONE();
2475 static PyObject*
2476 DB_set_cachesize(DBObject* self, PyObject* args)
2478 int err;
2479 int gbytes = 0, bytes = 0, ncache = 0;
2481 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2482 &gbytes,&bytes,&ncache))
2483 return NULL;
2484 CHECK_DB_NOT_CLOSED(self);
2486 MYDB_BEGIN_ALLOW_THREADS;
2487 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2488 MYDB_END_ALLOW_THREADS;
2489 RETURN_IF_ERR();
2490 RETURN_NONE();
2494 static PyObject*
2495 DB_set_flags(DBObject* self, PyObject* args)
2497 int err, flags;
2499 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2500 return NULL;
2501 CHECK_DB_NOT_CLOSED(self);
2503 MYDB_BEGIN_ALLOW_THREADS;
2504 err = self->db->set_flags(self->db, flags);
2505 MYDB_END_ALLOW_THREADS;
2506 RETURN_IF_ERR();
2508 self->setflags |= flags;
2509 RETURN_NONE();
2513 static PyObject*
2514 DB_set_h_ffactor(DBObject* self, PyObject* args)
2516 int err, ffactor;
2518 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2519 return NULL;
2520 CHECK_DB_NOT_CLOSED(self);
2522 MYDB_BEGIN_ALLOW_THREADS;
2523 err = self->db->set_h_ffactor(self->db, ffactor);
2524 MYDB_END_ALLOW_THREADS;
2525 RETURN_IF_ERR();
2526 RETURN_NONE();
2530 static PyObject*
2531 DB_set_h_nelem(DBObject* self, PyObject* args)
2533 int err, nelem;
2535 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2536 return NULL;
2537 CHECK_DB_NOT_CLOSED(self);
2539 MYDB_BEGIN_ALLOW_THREADS;
2540 err = self->db->set_h_nelem(self->db, nelem);
2541 MYDB_END_ALLOW_THREADS;
2542 RETURN_IF_ERR();
2543 RETURN_NONE();
2547 static PyObject*
2548 DB_set_lorder(DBObject* self, PyObject* args)
2550 int err, lorder;
2552 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2553 return NULL;
2554 CHECK_DB_NOT_CLOSED(self);
2556 MYDB_BEGIN_ALLOW_THREADS;
2557 err = self->db->set_lorder(self->db, lorder);
2558 MYDB_END_ALLOW_THREADS;
2559 RETURN_IF_ERR();
2560 RETURN_NONE();
2564 static PyObject*
2565 DB_set_pagesize(DBObject* self, PyObject* args)
2567 int err, pagesize;
2569 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2570 return NULL;
2571 CHECK_DB_NOT_CLOSED(self);
2573 MYDB_BEGIN_ALLOW_THREADS;
2574 err = self->db->set_pagesize(self->db, pagesize);
2575 MYDB_END_ALLOW_THREADS;
2576 RETURN_IF_ERR();
2577 RETURN_NONE();
2581 static PyObject*
2582 DB_set_re_delim(DBObject* self, PyObject* args)
2584 int err;
2585 char delim;
2587 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2588 PyErr_Clear();
2589 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2590 return NULL;
2593 CHECK_DB_NOT_CLOSED(self);
2595 MYDB_BEGIN_ALLOW_THREADS;
2596 err = self->db->set_re_delim(self->db, delim);
2597 MYDB_END_ALLOW_THREADS;
2598 RETURN_IF_ERR();
2599 RETURN_NONE();
2602 static PyObject*
2603 DB_set_re_len(DBObject* self, PyObject* args)
2605 int err, len;
2607 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2608 return NULL;
2609 CHECK_DB_NOT_CLOSED(self);
2611 MYDB_BEGIN_ALLOW_THREADS;
2612 err = self->db->set_re_len(self->db, len);
2613 MYDB_END_ALLOW_THREADS;
2614 RETURN_IF_ERR();
2615 RETURN_NONE();
2619 static PyObject*
2620 DB_set_re_pad(DBObject* self, PyObject* args)
2622 int err;
2623 char pad;
2625 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2626 PyErr_Clear();
2627 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2628 return NULL;
2630 CHECK_DB_NOT_CLOSED(self);
2632 MYDB_BEGIN_ALLOW_THREADS;
2633 err = self->db->set_re_pad(self->db, pad);
2634 MYDB_END_ALLOW_THREADS;
2635 RETURN_IF_ERR();
2636 RETURN_NONE();
2640 static PyObject*
2641 DB_set_re_source(DBObject* self, PyObject* args)
2643 int err;
2644 char *re_source;
2646 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2647 return NULL;
2648 CHECK_DB_NOT_CLOSED(self);
2650 MYDB_BEGIN_ALLOW_THREADS;
2651 err = self->db->set_re_source(self->db, re_source);
2652 MYDB_END_ALLOW_THREADS;
2653 RETURN_IF_ERR();
2654 RETURN_NONE();
2658 static PyObject*
2659 DB_set_q_extentsize(DBObject* self, PyObject* args)
2661 int err;
2662 int extentsize;
2664 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2665 return NULL;
2666 CHECK_DB_NOT_CLOSED(self);
2668 MYDB_BEGIN_ALLOW_THREADS;
2669 err = self->db->set_q_extentsize(self->db, extentsize);
2670 MYDB_END_ALLOW_THREADS;
2671 RETURN_IF_ERR();
2672 RETURN_NONE();
2675 static PyObject*
2676 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2678 int err, flags = 0, type;
2679 void* sp;
2680 PyObject* d;
2681 #if (DBVER >= 43)
2682 PyObject* txnobj = NULL;
2683 DB_TXN *txn = NULL;
2684 static char* kwnames[] = { "flags", "txn", NULL };
2685 #else
2686 static char* kwnames[] = { "flags", NULL };
2687 #endif
2689 #if (DBVER >= 43)
2690 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2691 &flags, &txnobj))
2692 return NULL;
2693 if (!checkTxnObj(txnobj, &txn))
2694 return NULL;
2695 #else
2696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2697 return NULL;
2698 #endif
2699 CHECK_DB_NOT_CLOSED(self);
2701 MYDB_BEGIN_ALLOW_THREADS;
2702 #if (DBVER >= 43)
2703 err = self->db->stat(self->db, txn, &sp, flags);
2704 #else
2705 err = self->db->stat(self->db, &sp, flags);
2706 #endif
2707 MYDB_END_ALLOW_THREADS;
2708 RETURN_IF_ERR();
2710 self->haveStat = 1;
2712 /* Turn the stat structure into a dictionary */
2713 type = _DB_get_type(self);
2714 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2715 free(sp);
2716 return NULL;
2719 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2720 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2721 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2723 switch (type) {
2724 case DB_HASH:
2725 MAKE_HASH_ENTRY(magic);
2726 MAKE_HASH_ENTRY(version);
2727 MAKE_HASH_ENTRY(nkeys);
2728 MAKE_HASH_ENTRY(ndata);
2729 #if (DBVER >= 46)
2730 MAKE_HASH_ENTRY(pagecnt);
2731 #endif
2732 MAKE_HASH_ENTRY(pagesize);
2733 #if (DBVER < 41)
2734 MAKE_HASH_ENTRY(nelem);
2735 #endif
2736 MAKE_HASH_ENTRY(ffactor);
2737 MAKE_HASH_ENTRY(buckets);
2738 MAKE_HASH_ENTRY(free);
2739 MAKE_HASH_ENTRY(bfree);
2740 MAKE_HASH_ENTRY(bigpages);
2741 MAKE_HASH_ENTRY(big_bfree);
2742 MAKE_HASH_ENTRY(overflows);
2743 MAKE_HASH_ENTRY(ovfl_free);
2744 MAKE_HASH_ENTRY(dup);
2745 MAKE_HASH_ENTRY(dup_free);
2746 break;
2748 case DB_BTREE:
2749 case DB_RECNO:
2750 MAKE_BT_ENTRY(magic);
2751 MAKE_BT_ENTRY(version);
2752 MAKE_BT_ENTRY(nkeys);
2753 MAKE_BT_ENTRY(ndata);
2754 #if (DBVER >= 46)
2755 MAKE_BT_ENTRY(pagecnt);
2756 #endif
2757 MAKE_BT_ENTRY(pagesize);
2758 MAKE_BT_ENTRY(minkey);
2759 MAKE_BT_ENTRY(re_len);
2760 MAKE_BT_ENTRY(re_pad);
2761 MAKE_BT_ENTRY(levels);
2762 MAKE_BT_ENTRY(int_pg);
2763 MAKE_BT_ENTRY(leaf_pg);
2764 MAKE_BT_ENTRY(dup_pg);
2765 MAKE_BT_ENTRY(over_pg);
2766 #if (DBVER >= 43)
2767 MAKE_BT_ENTRY(empty_pg);
2768 #endif
2769 MAKE_BT_ENTRY(free);
2770 MAKE_BT_ENTRY(int_pgfree);
2771 MAKE_BT_ENTRY(leaf_pgfree);
2772 MAKE_BT_ENTRY(dup_pgfree);
2773 MAKE_BT_ENTRY(over_pgfree);
2774 break;
2776 case DB_QUEUE:
2777 MAKE_QUEUE_ENTRY(magic);
2778 MAKE_QUEUE_ENTRY(version);
2779 MAKE_QUEUE_ENTRY(nkeys);
2780 MAKE_QUEUE_ENTRY(ndata);
2781 MAKE_QUEUE_ENTRY(pagesize);
2782 #if (DBVER >= 41)
2783 MAKE_QUEUE_ENTRY(extentsize);
2784 #endif
2785 MAKE_QUEUE_ENTRY(pages);
2786 MAKE_QUEUE_ENTRY(re_len);
2787 MAKE_QUEUE_ENTRY(re_pad);
2788 MAKE_QUEUE_ENTRY(pgfree);
2789 #if (DBVER == 31)
2790 MAKE_QUEUE_ENTRY(start);
2791 #endif
2792 MAKE_QUEUE_ENTRY(first_recno);
2793 MAKE_QUEUE_ENTRY(cur_recno);
2794 break;
2796 default:
2797 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2798 Py_DECREF(d);
2799 d = NULL;
2802 #undef MAKE_HASH_ENTRY
2803 #undef MAKE_BT_ENTRY
2804 #undef MAKE_QUEUE_ENTRY
2806 free(sp);
2807 return d;
2810 static PyObject*
2811 DB_sync(DBObject* self, PyObject* args)
2813 int err;
2814 int flags = 0;
2816 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2817 return NULL;
2818 CHECK_DB_NOT_CLOSED(self);
2820 MYDB_BEGIN_ALLOW_THREADS;
2821 err = self->db->sync(self->db, flags);
2822 MYDB_END_ALLOW_THREADS;
2823 RETURN_IF_ERR();
2824 RETURN_NONE();
2828 static PyObject*
2829 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2831 int err, flags=0;
2832 u_int32_t count=0;
2833 PyObject* txnobj = NULL;
2834 DB_TXN *txn = NULL;
2835 static char* kwnames[] = { "txn", "flags", NULL };
2837 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2838 &txnobj, &flags))
2839 return NULL;
2840 CHECK_DB_NOT_CLOSED(self);
2841 if (!checkTxnObj(txnobj, &txn))
2842 return NULL;
2844 MYDB_BEGIN_ALLOW_THREADS;
2845 err = self->db->truncate(self->db, txn, &count, flags);
2846 MYDB_END_ALLOW_THREADS;
2847 RETURN_IF_ERR();
2848 return NUMBER_FromLong(count);
2852 static PyObject*
2853 DB_upgrade(DBObject* self, PyObject* args)
2855 int err, flags=0;
2856 char *filename;
2858 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2859 return NULL;
2860 CHECK_DB_NOT_CLOSED(self);
2862 MYDB_BEGIN_ALLOW_THREADS;
2863 err = self->db->upgrade(self->db, filename, flags);
2864 MYDB_END_ALLOW_THREADS;
2865 RETURN_IF_ERR();
2866 RETURN_NONE();
2870 static PyObject*
2871 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2873 int err, flags=0;
2874 char* fileName;
2875 char* dbName=NULL;
2876 char* outFileName=NULL;
2877 FILE* outFile=NULL;
2878 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2879 NULL };
2881 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2882 &fileName, &dbName, &outFileName, &flags))
2883 return NULL;
2885 CHECK_DB_NOT_CLOSED(self);
2886 if (outFileName)
2887 outFile = fopen(outFileName, "w");
2888 /* XXX(nnorwitz): it should probably be an exception if outFile
2889 can't be opened. */
2891 { /* DB.verify acts as a DB handle destructor (like close) */
2892 PyObject *error;
2894 error=DB_close_internal(self, 0, 1);
2895 if (error ) {
2896 return error;
2900 MYDB_BEGIN_ALLOW_THREADS;
2901 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2902 MYDB_END_ALLOW_THREADS;
2904 self->db = NULL; /* Implicit close; related objects already released */
2906 if (outFile)
2907 fclose(outFile);
2909 RETURN_IF_ERR();
2910 RETURN_NONE();
2914 static PyObject*
2915 DB_set_get_returns_none(DBObject* self, PyObject* args)
2917 int flags=0;
2918 int oldValue=0;
2920 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2921 return NULL;
2922 CHECK_DB_NOT_CLOSED(self);
2924 if (self->moduleFlags.getReturnsNone)
2925 ++oldValue;
2926 if (self->moduleFlags.cursorSetReturnsNone)
2927 ++oldValue;
2928 self->moduleFlags.getReturnsNone = (flags >= 1);
2929 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2930 return NUMBER_FromLong(oldValue);
2933 #if (DBVER >= 41)
2934 static PyObject*
2935 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2937 int err;
2938 u_int32_t flags=0;
2939 char *passwd = NULL;
2940 static char* kwnames[] = { "passwd", "flags", NULL };
2942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2943 &passwd, &flags)) {
2944 return NULL;
2947 MYDB_BEGIN_ALLOW_THREADS;
2948 err = self->db->set_encrypt(self->db, passwd, flags);
2949 MYDB_END_ALLOW_THREADS;
2951 RETURN_IF_ERR();
2952 RETURN_NONE();
2954 #endif /* DBVER >= 41 */
2957 /*-------------------------------------------------------------- */
2958 /* Mapping and Dictionary-like access routines */
2960 Py_ssize_t DB_length(PyObject* _self)
2962 int err;
2963 Py_ssize_t size = 0;
2964 int flags = 0;
2965 void* sp;
2966 DBObject* self = (DBObject*)_self;
2968 if (self->db == NULL) {
2969 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2970 if (t) {
2971 PyErr_SetObject(DBError, t);
2972 Py_DECREF(t);
2974 return -1;
2977 if (self->haveStat) { /* Has the stat function been called recently? If
2978 so, we can use the cached value. */
2979 flags = DB_FAST_STAT;
2982 MYDB_BEGIN_ALLOW_THREADS;
2983 redo_stat_for_length:
2984 #if (DBVER >= 43)
2985 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2986 #else
2987 err = self->db->stat(self->db, &sp, flags);
2988 #endif
2990 /* All the stat structures have matching fields upto the ndata field,
2991 so we can use any of them for the type cast */
2992 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2994 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
2995 * redo a full stat to make sure.
2996 * Fixes SF python bug 1493322, pybsddb bug 1184012
2998 if (size == 0 && (flags & DB_FAST_STAT)) {
2999 flags = 0;
3000 if (!err)
3001 free(sp);
3002 goto redo_stat_for_length;
3005 MYDB_END_ALLOW_THREADS;
3007 if (err)
3008 return -1;
3010 self->haveStat = 1;
3012 free(sp);
3013 return size;
3017 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
3019 int err;
3020 PyObject* retval;
3021 DBT key;
3022 DBT data;
3024 CHECK_DB_NOT_CLOSED(self);
3025 if (!make_key_dbt(self, keyobj, &key, NULL))
3026 return NULL;
3028 CLEAR_DBT(data);
3029 if (CHECK_DBFLAG(self, DB_THREAD)) {
3030 /* Tell Berkeley DB to malloc the return value (thread safe) */
3031 data.flags = DB_DBT_MALLOC;
3033 MYDB_BEGIN_ALLOW_THREADS;
3034 err = self->db->get(self->db, NULL, &key, &data, 0);
3035 MYDB_END_ALLOW_THREADS;
3036 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3037 PyErr_SetObject(PyExc_KeyError, keyobj);
3038 retval = NULL;
3040 else if (makeDBError(err)) {
3041 retval = NULL;
3043 else {
3044 retval = Build_PyString(data.data, data.size);
3045 FREE_DBT(data);
3048 FREE_DBT(key);
3049 return retval;
3053 static int
3054 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
3056 DBT key, data;
3057 int retval;
3058 int flags = 0;
3060 if (self->db == NULL) {
3061 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
3062 if (t) {
3063 PyErr_SetObject(DBError, t);
3064 Py_DECREF(t);
3066 return -1;
3069 if (!make_key_dbt(self, keyobj, &key, NULL))
3070 return -1;
3072 if (dataobj != NULL) {
3073 if (!make_dbt(dataobj, &data))
3074 retval = -1;
3075 else {
3076 if (self->setflags & (DB_DUP|DB_DUPSORT))
3077 /* dictionaries shouldn't have duplicate keys */
3078 flags = DB_NOOVERWRITE;
3079 retval = _DB_put(self, NULL, &key, &data, flags);
3081 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
3082 /* try deleting any old record that matches and then PUT it
3083 * again... */
3084 _DB_delete(self, NULL, &key, 0);
3085 PyErr_Clear();
3086 retval = _DB_put(self, NULL, &key, &data, flags);
3090 else {
3091 /* dataobj == NULL, so delete the key */
3092 retval = _DB_delete(self, NULL, &key, 0);
3094 FREE_DBT(key);
3095 return retval;
3099 static PyObject*
3100 DB_has_key(DBObject* self, PyObject* args, PyObject* kwargs)
3102 int err;
3103 PyObject* keyobj;
3104 DBT key, data;
3105 PyObject* txnobj = NULL;
3106 DB_TXN *txn = NULL;
3107 static char* kwnames[] = {"key","txn", NULL};
3109 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:has_key", kwnames,
3110 &keyobj, &txnobj))
3111 return NULL;
3113 CHECK_DB_NOT_CLOSED(self);
3114 if (!make_key_dbt(self, keyobj, &key, NULL))
3115 return NULL;
3116 if (!checkTxnObj(txnobj, &txn)) {
3117 FREE_DBT(key);
3118 return NULL;
3121 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
3122 it has a record but can't allocate a buffer for the data. This saves
3123 having to deal with data we won't be using.
3125 CLEAR_DBT(data);
3126 data.flags = DB_DBT_USERMEM;
3128 MYDB_BEGIN_ALLOW_THREADS;
3129 err = self->db->get(self->db, txn, &key, &data, 0);
3130 MYDB_END_ALLOW_THREADS;
3131 FREE_DBT(key);
3133 if (err == DB_BUFFER_SMALL || err == 0) {
3134 return NUMBER_FromLong(1);
3135 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3136 return NUMBER_FromLong(0);
3139 makeDBError(err);
3140 return NULL;
3144 #define _KEYS_LIST 1
3145 #define _VALUES_LIST 2
3146 #define _ITEMS_LIST 3
3148 static PyObject*
3149 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
3151 int err, dbtype;
3152 DBT key;
3153 DBT data;
3154 DBC *cursor;
3155 PyObject* list;
3156 PyObject* item = NULL;
3158 CHECK_DB_NOT_CLOSED(self);
3159 CLEAR_DBT(key);
3160 CLEAR_DBT(data);
3162 dbtype = _DB_get_type(self);
3163 if (dbtype == -1)
3164 return NULL;
3166 list = PyList_New(0);
3167 if (list == NULL)
3168 return NULL;
3170 /* get a cursor */
3171 MYDB_BEGIN_ALLOW_THREADS;
3172 err = self->db->cursor(self->db, txn, &cursor, 0);
3173 MYDB_END_ALLOW_THREADS;
3174 if (makeDBError(err)) {
3175 Py_DECREF(list);
3176 return NULL;
3179 while (1) { /* use the cursor to traverse the DB, collecting items */
3180 MYDB_BEGIN_ALLOW_THREADS;
3181 err = _DBC_get(cursor, &key, &data, DB_NEXT);
3182 MYDB_END_ALLOW_THREADS;
3184 if (err) {
3185 /* for any error, break out of the loop */
3186 break;
3189 switch (type) {
3190 case _KEYS_LIST:
3191 switch(dbtype) {
3192 case DB_BTREE:
3193 case DB_HASH:
3194 default:
3195 item = Build_PyString(key.data, key.size);
3196 break;
3197 case DB_RECNO:
3198 case DB_QUEUE:
3199 item = NUMBER_FromLong(*((db_recno_t*)key.data));
3200 break;
3202 break;
3204 case _VALUES_LIST:
3205 item = Build_PyString(data.data, data.size);
3206 break;
3208 case _ITEMS_LIST:
3209 switch(dbtype) {
3210 case DB_BTREE:
3211 case DB_HASH:
3212 default:
3213 item = BuildValue_SS(key.data, key.size, data.data, data.size);
3214 break;
3215 case DB_RECNO:
3216 case DB_QUEUE:
3217 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3218 break;
3220 break;
3221 default:
3222 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3223 item = NULL;
3224 break;
3226 if (item == NULL) {
3227 Py_DECREF(list);
3228 list = NULL;
3229 goto done;
3231 if (PyList_Append(list, item)) {
3232 Py_DECREF(list);
3233 Py_DECREF(item);
3234 list = NULL;
3235 goto done;
3237 Py_DECREF(item);
3240 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3241 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
3242 Py_DECREF(list);
3243 list = NULL;
3246 done:
3247 MYDB_BEGIN_ALLOW_THREADS;
3248 _DBC_close(cursor);
3249 MYDB_END_ALLOW_THREADS;
3250 return list;
3254 static PyObject*
3255 DB_keys(DBObject* self, PyObject* args)
3257 PyObject* txnobj = NULL;
3258 DB_TXN *txn = NULL;
3260 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
3261 return NULL;
3262 if (!checkTxnObj(txnobj, &txn))
3263 return NULL;
3264 return _DB_make_list(self, txn, _KEYS_LIST);
3268 static PyObject*
3269 DB_items(DBObject* self, PyObject* args)
3271 PyObject* txnobj = NULL;
3272 DB_TXN *txn = NULL;
3274 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3275 return NULL;
3276 if (!checkTxnObj(txnobj, &txn))
3277 return NULL;
3278 return _DB_make_list(self, txn, _ITEMS_LIST);
3282 static PyObject*
3283 DB_values(DBObject* self, PyObject* args)
3285 PyObject* txnobj = NULL;
3286 DB_TXN *txn = NULL;
3288 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3289 return NULL;
3290 if (!checkTxnObj(txnobj, &txn))
3291 return NULL;
3292 return _DB_make_list(self, txn, _VALUES_LIST);
3295 /* --------------------------------------------------------------------- */
3296 /* DBCursor methods */
3299 static PyObject*
3300 DBC_close_internal(DBCursorObject* self)
3302 int err = 0;
3304 if (self->dbc != NULL) {
3305 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3306 if (self->txn) {
3307 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3308 self->txn=NULL;
3311 MYDB_BEGIN_ALLOW_THREADS;
3312 err = _DBC_close(self->dbc);
3313 MYDB_END_ALLOW_THREADS;
3314 self->dbc = NULL;
3316 RETURN_IF_ERR();
3317 RETURN_NONE();
3320 static PyObject*
3321 DBC_close(DBCursorObject* self)
3323 return DBC_close_internal(self);
3327 static PyObject*
3328 DBC_count(DBCursorObject* self, PyObject* args)
3330 int err = 0;
3331 db_recno_t count;
3332 int flags = 0;
3334 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3335 return NULL;
3337 CHECK_CURSOR_NOT_CLOSED(self);
3339 MYDB_BEGIN_ALLOW_THREADS;
3340 err = _DBC_count(self->dbc, &count, flags);
3341 MYDB_END_ALLOW_THREADS;
3342 RETURN_IF_ERR();
3344 return NUMBER_FromLong(count);
3348 static PyObject*
3349 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3351 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3355 static PyObject*
3356 DBC_delete(DBCursorObject* self, PyObject* args)
3358 int err, flags=0;
3360 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3361 return NULL;
3363 CHECK_CURSOR_NOT_CLOSED(self);
3365 MYDB_BEGIN_ALLOW_THREADS;
3366 err = _DBC_del(self->dbc, flags);
3367 MYDB_END_ALLOW_THREADS;
3368 RETURN_IF_ERR();
3370 self->mydb->haveStat = 0;
3371 RETURN_NONE();
3375 static PyObject*
3376 DBC_dup(DBCursorObject* self, PyObject* args)
3378 int err, flags =0;
3379 DBC* dbc = NULL;
3381 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3382 return NULL;
3384 CHECK_CURSOR_NOT_CLOSED(self);
3386 MYDB_BEGIN_ALLOW_THREADS;
3387 err = _DBC_dup(self->dbc, &dbc, flags);
3388 MYDB_END_ALLOW_THREADS;
3389 RETURN_IF_ERR();
3391 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
3394 static PyObject*
3395 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3397 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3401 static PyObject*
3402 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3404 int err, flags=0;
3405 PyObject* keyobj = NULL;
3406 PyObject* dataobj = NULL;
3407 PyObject* retval = NULL;
3408 int dlen = -1;
3409 int doff = -1;
3410 DBT key, data;
3411 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3412 NULL };
3414 CLEAR_DBT(key);
3415 CLEAR_DBT(data);
3416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3417 &flags, &dlen, &doff))
3419 PyErr_Clear();
3420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3421 &kwnames[1],
3422 &keyobj, &flags, &dlen, &doff))
3424 PyErr_Clear();
3425 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3426 kwnames, &keyobj, &dataobj,
3427 &flags, &dlen, &doff))
3429 return NULL;
3434 CHECK_CURSOR_NOT_CLOSED(self);
3436 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3437 return NULL;
3438 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3439 (!add_partial_dbt(&data, dlen, doff)) )
3441 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3442 return NULL;
3445 MYDB_BEGIN_ALLOW_THREADS;
3446 err = _DBC_get(self->dbc, &key, &data, flags);
3447 MYDB_END_ALLOW_THREADS;
3449 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3450 && self->mydb->moduleFlags.getReturnsNone) {
3451 Py_INCREF(Py_None);
3452 retval = Py_None;
3454 else if (makeDBError(err)) {
3455 retval = NULL;
3457 else {
3458 switch (_DB_get_type(self->mydb)) {
3459 case -1:
3460 retval = NULL;
3461 break;
3462 case DB_BTREE:
3463 case DB_HASH:
3464 default:
3465 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3466 break;
3467 case DB_RECNO:
3468 case DB_QUEUE:
3469 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3470 break;
3473 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3474 return retval;
3477 static PyObject*
3478 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3480 int err, flags=0;
3481 PyObject* keyobj = NULL;
3482 PyObject* dataobj = NULL;
3483 PyObject* retval = NULL;
3484 int dlen = -1;
3485 int doff = -1;
3486 DBT key, pkey, data;
3487 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3488 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3490 CLEAR_DBT(key);
3491 CLEAR_DBT(data);
3492 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3493 &flags, &dlen, &doff))
3495 PyErr_Clear();
3496 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3497 kwnames_keyOnly,
3498 &keyobj, &flags, &dlen, &doff))
3500 PyErr_Clear();
3501 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3502 kwnames, &keyobj, &dataobj,
3503 &flags, &dlen, &doff))
3505 return NULL;
3510 CHECK_CURSOR_NOT_CLOSED(self);
3512 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3513 return NULL;
3514 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3515 (!add_partial_dbt(&data, dlen, doff)) ) {
3516 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3517 return NULL;
3520 CLEAR_DBT(pkey);
3521 pkey.flags = DB_DBT_MALLOC;
3523 MYDB_BEGIN_ALLOW_THREADS;
3524 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
3525 MYDB_END_ALLOW_THREADS;
3527 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3528 && self->mydb->moduleFlags.getReturnsNone) {
3529 Py_INCREF(Py_None);
3530 retval = Py_None;
3532 else if (makeDBError(err)) {
3533 retval = NULL;
3535 else {
3536 PyObject *pkeyObj;
3537 PyObject *dataObj;
3538 dataObj = Build_PyString(data.data, data.size);
3540 if (self->mydb->primaryDBType == DB_RECNO ||
3541 self->mydb->primaryDBType == DB_QUEUE)
3542 pkeyObj = NUMBER_FromLong(*(int *)pkey.data);
3543 else
3544 pkeyObj = Build_PyString(pkey.data, pkey.size);
3546 if (key.data && key.size) /* return key, pkey and data */
3548 PyObject *keyObj;
3549 int type = _DB_get_type(self->mydb);
3550 if (type == DB_RECNO || type == DB_QUEUE)
3551 keyObj = NUMBER_FromLong(*(int *)key.data);
3552 else
3553 keyObj = Build_PyString(key.data, key.size);
3554 #if (PY_VERSION_HEX >= 0x02040000)
3555 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3556 #else
3557 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3558 #endif
3559 Py_DECREF(keyObj);
3560 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3562 else /* return just the pkey and data */
3564 #if (PY_VERSION_HEX >= 0x02040000)
3565 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3566 #else
3567 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3568 #endif
3570 Py_DECREF(dataObj);
3571 Py_DECREF(pkeyObj);
3572 FREE_DBT(pkey);
3574 /* the only time REALLOC should be set is if we used an integer
3575 * key that make_key_dbt malloc'd for us. always free these. */
3576 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
3577 FREE_DBT(key);
3579 return retval;
3583 static PyObject*
3584 DBC_get_recno(DBCursorObject* self)
3586 int err;
3587 db_recno_t recno;
3588 DBT key;
3589 DBT data;
3591 CHECK_CURSOR_NOT_CLOSED(self);
3593 CLEAR_DBT(key);
3594 CLEAR_DBT(data);
3596 MYDB_BEGIN_ALLOW_THREADS;
3597 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
3598 MYDB_END_ALLOW_THREADS;
3599 RETURN_IF_ERR();
3601 recno = *((db_recno_t*)data.data);
3602 return NUMBER_FromLong(recno);
3606 static PyObject*
3607 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3609 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3613 static PyObject*
3614 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3616 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3620 static PyObject*
3621 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3623 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3627 static PyObject*
3628 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3630 int err, flags = 0;
3631 PyObject* keyobj, *dataobj;
3632 DBT key, data;
3633 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3634 NULL };
3635 int dlen = -1;
3636 int doff = -1;
3638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3639 &keyobj, &dataobj, &flags, &dlen, &doff))
3640 return NULL;
3642 CHECK_CURSOR_NOT_CLOSED(self);
3644 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3645 return NULL;
3646 if (!make_dbt(dataobj, &data) ||
3647 !add_partial_dbt(&data, dlen, doff) )
3649 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3650 return NULL;
3653 MYDB_BEGIN_ALLOW_THREADS;
3654 err = _DBC_put(self->dbc, &key, &data, flags);
3655 MYDB_END_ALLOW_THREADS;
3656 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3657 RETURN_IF_ERR();
3658 self->mydb->haveStat = 0;
3659 RETURN_NONE();
3663 static PyObject*
3664 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3666 int err, flags = 0;
3667 DBT key, data;
3668 PyObject* retval, *keyobj;
3669 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3670 int dlen = -1;
3671 int doff = -1;
3673 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3674 &keyobj, &flags, &dlen, &doff))
3675 return NULL;
3677 CHECK_CURSOR_NOT_CLOSED(self);
3679 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3680 return NULL;
3682 CLEAR_DBT(data);
3683 if (!add_partial_dbt(&data, dlen, doff)) {
3684 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3685 return NULL;
3688 MYDB_BEGIN_ALLOW_THREADS;
3689 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
3690 MYDB_END_ALLOW_THREADS;
3691 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3692 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3693 Py_INCREF(Py_None);
3694 retval = Py_None;
3696 else if (makeDBError(err)) {
3697 retval = NULL;
3699 else {
3700 switch (_DB_get_type(self->mydb)) {
3701 case -1:
3702 retval = NULL;
3703 break;
3704 case DB_BTREE:
3705 case DB_HASH:
3706 default:
3707 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3708 break;
3709 case DB_RECNO:
3710 case DB_QUEUE:
3711 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3712 break;
3714 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3716 /* the only time REALLOC should be set is if we used an integer
3717 * key that make_key_dbt malloc'd for us. always free these. */
3718 if (key.flags & DB_DBT_REALLOC) {
3719 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3722 return retval;
3726 static PyObject*
3727 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3729 int err, flags = 0;
3730 DBT key, data;
3731 PyObject* retval, *keyobj;
3732 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3733 int dlen = -1;
3734 int doff = -1;
3736 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3737 &keyobj, &flags, &dlen, &doff))
3738 return NULL;
3740 CHECK_CURSOR_NOT_CLOSED(self);
3742 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3743 return NULL;
3745 CLEAR_DBT(data);
3746 if (!add_partial_dbt(&data, dlen, doff)) {
3747 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3748 return NULL;
3750 MYDB_BEGIN_ALLOW_THREADS;
3751 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3752 MYDB_END_ALLOW_THREADS;
3753 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3754 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3755 Py_INCREF(Py_None);
3756 retval = Py_None;
3758 else if (makeDBError(err)) {
3759 retval = NULL;
3761 else {
3762 switch (_DB_get_type(self->mydb)) {
3763 case -1:
3764 retval = NULL;
3765 break;
3766 case DB_BTREE:
3767 case DB_HASH:
3768 default:
3769 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3770 break;
3771 case DB_RECNO:
3772 case DB_QUEUE:
3773 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3774 break;
3776 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3778 /* the only time REALLOC should be set is if we used an integer
3779 * key that make_key_dbt malloc'd for us. always free these. */
3780 if (key.flags & DB_DBT_REALLOC) {
3781 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3784 return retval;
3787 static PyObject*
3788 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3789 int flags, unsigned int returnsNone)
3791 int err;
3792 DBT key, data;
3793 PyObject* retval;
3795 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3796 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3797 return NULL;
3798 if (!make_dbt(dataobj, &data)) {
3799 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3800 return NULL;
3803 MYDB_BEGIN_ALLOW_THREADS;
3804 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3805 MYDB_END_ALLOW_THREADS;
3806 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3807 Py_INCREF(Py_None);
3808 retval = Py_None;
3810 else if (makeDBError(err)) {
3811 retval = NULL;
3813 else {
3814 switch (_DB_get_type(self->mydb)) {
3815 case -1:
3816 retval = NULL;
3817 break;
3818 case DB_BTREE:
3819 case DB_HASH:
3820 default:
3821 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3822 break;
3823 case DB_RECNO:
3824 case DB_QUEUE:
3825 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3826 break;
3830 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3831 return retval;
3834 static PyObject*
3835 DBC_get_both(DBCursorObject* self, PyObject* args)
3837 int flags=0;
3838 PyObject *keyobj, *dataobj;
3840 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3841 return NULL;
3843 /* if the cursor is closed, self->mydb may be invalid */
3844 CHECK_CURSOR_NOT_CLOSED(self);
3846 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3847 self->mydb->moduleFlags.getReturnsNone);
3850 /* Return size of entry */
3851 static PyObject*
3852 DBC_get_current_size(DBCursorObject* self)
3854 int err, flags=DB_CURRENT;
3855 PyObject* retval = NULL;
3856 DBT key, data;
3858 CHECK_CURSOR_NOT_CLOSED(self);
3859 CLEAR_DBT(key);
3860 CLEAR_DBT(data);
3862 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3863 getting the record size. */
3864 data.flags = DB_DBT_USERMEM;
3865 data.ulen = 0;
3866 MYDB_BEGIN_ALLOW_THREADS;
3867 err = _DBC_get(self->dbc, &key, &data, flags);
3868 MYDB_END_ALLOW_THREADS;
3869 if (err == DB_BUFFER_SMALL || !err) {
3870 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3871 retval = NUMBER_FromLong((long)data.size);
3872 err = 0;
3875 RETURN_IF_ERR();
3876 return retval;
3879 static PyObject*
3880 DBC_set_both(DBCursorObject* self, PyObject* args)
3882 int flags=0;
3883 PyObject *keyobj, *dataobj;
3885 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3886 return NULL;
3888 /* if the cursor is closed, self->mydb may be invalid */
3889 CHECK_CURSOR_NOT_CLOSED(self);
3891 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3892 self->mydb->moduleFlags.cursorSetReturnsNone);
3896 static PyObject*
3897 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3899 int err, irecno, flags=0;
3900 db_recno_t recno;
3901 DBT key, data;
3902 PyObject* retval;
3903 int dlen = -1;
3904 int doff = -1;
3905 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3908 &irecno, &flags, &dlen, &doff))
3909 return NULL;
3911 CHECK_CURSOR_NOT_CLOSED(self);
3913 CLEAR_DBT(key);
3914 recno = (db_recno_t) irecno;
3915 /* use allocated space so DB will be able to realloc room for the real
3916 * key */
3917 key.data = malloc(sizeof(db_recno_t));
3918 if (key.data == NULL) {
3919 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3920 return NULL;
3922 key.size = sizeof(db_recno_t);
3923 key.ulen = key.size;
3924 memcpy(key.data, &recno, sizeof(db_recno_t));
3925 key.flags = DB_DBT_REALLOC;
3927 CLEAR_DBT(data);
3928 if (!add_partial_dbt(&data, dlen, doff)) {
3929 FREE_DBT(key);
3930 return NULL;
3933 MYDB_BEGIN_ALLOW_THREADS;
3934 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3935 MYDB_END_ALLOW_THREADS;
3936 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3937 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3938 Py_INCREF(Py_None);
3939 retval = Py_None;
3941 else if (makeDBError(err)) {
3942 retval = NULL;
3944 else { /* Can only be used for BTrees, so no need to return int key */
3945 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3947 FREE_DBT(key);
3949 return retval;
3953 static PyObject*
3954 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3956 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3960 static PyObject*
3961 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3963 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3967 static PyObject*
3968 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3970 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3974 static PyObject*
3975 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3977 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3981 static PyObject*
3982 DBC_join_item(DBCursorObject* self, PyObject* args)
3984 int err, flags=0;
3985 DBT key, data;
3986 PyObject* retval;
3988 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3989 return NULL;
3991 CHECK_CURSOR_NOT_CLOSED(self);
3993 CLEAR_DBT(key);
3994 CLEAR_DBT(data);
3996 MYDB_BEGIN_ALLOW_THREADS;
3997 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3998 MYDB_END_ALLOW_THREADS;
3999 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
4000 && self->mydb->moduleFlags.getReturnsNone) {
4001 Py_INCREF(Py_None);
4002 retval = Py_None;
4004 else if (makeDBError(err)) {
4005 retval = NULL;
4007 else {
4008 retval = BuildValue_S(key.data, key.size);
4011 return retval;
4016 /* --------------------------------------------------------------------- */
4017 /* DBEnv methods */
4020 static PyObject*
4021 DBEnv_close_internal(DBEnvObject* self, int flags)
4023 PyObject *dummy;
4024 int err;
4026 if (!self->closed) { /* Don't close more than once */
4027 while(self->children_txns) {
4028 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
4029 Py_XDECREF(dummy);
4031 while(self->children_dbs) {
4032 dummy=DB_close_internal(self->children_dbs, 0, 0);
4033 Py_XDECREF(dummy);
4037 self->closed = 1;
4038 if (self->db_env) {
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->close(self->db_env, flags);
4041 MYDB_END_ALLOW_THREADS;
4042 /* after calling DBEnv->close, regardless of error, this DBEnv
4043 * may not be accessed again (Berkeley DB docs). */
4044 self->db_env = NULL;
4045 RETURN_IF_ERR();
4047 RETURN_NONE();
4050 static PyObject*
4051 DBEnv_close(DBEnvObject* self, PyObject* args)
4053 int flags = 0;
4055 if (!PyArg_ParseTuple(args, "|i:close", &flags))
4056 return NULL;
4057 return DBEnv_close_internal(self, flags);
4061 static PyObject*
4062 DBEnv_open(DBEnvObject* self, PyObject* args)
4064 int err, flags=0, mode=0660;
4065 char *db_home;
4067 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
4068 return NULL;
4070 CHECK_ENV_NOT_CLOSED(self);
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->open(self->db_env, db_home, flags, mode);
4074 MYDB_END_ALLOW_THREADS;
4075 RETURN_IF_ERR();
4076 self->closed = 0;
4077 self->flags = flags;
4078 RETURN_NONE();
4082 static PyObject*
4083 DBEnv_remove(DBEnvObject* self, PyObject* args)
4085 int err, flags=0;
4086 char *db_home;
4088 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
4089 return NULL;
4090 CHECK_ENV_NOT_CLOSED(self);
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->remove(self->db_env, db_home, flags);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4098 #if (DBVER >= 41)
4099 static PyObject*
4100 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4102 int err;
4103 u_int32_t flags=0;
4104 char *file = NULL;
4105 char *database = NULL;
4106 PyObject *txnobj = NULL;
4107 DB_TXN *txn = NULL;
4108 static char* kwnames[] = { "file", "database", "txn", "flags",
4109 NULL };
4111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
4112 &file, &database, &txnobj, &flags)) {
4113 return NULL;
4115 if (!checkTxnObj(txnobj, &txn)) {
4116 return NULL;
4118 CHECK_ENV_NOT_CLOSED(self);
4119 MYDB_BEGIN_ALLOW_THREADS;
4120 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4121 MYDB_END_ALLOW_THREADS;
4122 RETURN_IF_ERR();
4123 RETURN_NONE();
4126 static PyObject*
4127 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4129 int err;
4130 u_int32_t flags=0;
4131 char *file = NULL;
4132 char *database = NULL;
4133 char *newname = NULL;
4134 PyObject *txnobj = NULL;
4135 DB_TXN *txn = NULL;
4136 static char* kwnames[] = { "file", "database", "newname", "txn",
4137 "flags", NULL };
4139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
4140 &file, &database, &newname, &txnobj, &flags)) {
4141 return NULL;
4143 if (!checkTxnObj(txnobj, &txn)) {
4144 return NULL;
4146 CHECK_ENV_NOT_CLOSED(self);
4147 MYDB_BEGIN_ALLOW_THREADS;
4148 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4149 flags);
4150 MYDB_END_ALLOW_THREADS;
4151 RETURN_IF_ERR();
4152 RETURN_NONE();
4155 static PyObject*
4156 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4158 int err;
4159 u_int32_t flags=0;
4160 char *passwd = NULL;
4161 static char* kwnames[] = { "passwd", "flags", NULL };
4163 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4164 &passwd, &flags)) {
4165 return NULL;
4168 MYDB_BEGIN_ALLOW_THREADS;
4169 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4170 MYDB_END_ALLOW_THREADS;
4172 RETURN_IF_ERR();
4173 RETURN_NONE();
4175 #endif /* DBVER >= 41 */
4177 static PyObject*
4178 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4180 int err;
4181 u_int32_t flags=0;
4182 u_int32_t timeout = 0;
4183 static char* kwnames[] = { "timeout", "flags", NULL };
4185 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4186 &timeout, &flags)) {
4187 return NULL;
4190 MYDB_BEGIN_ALLOW_THREADS;
4191 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4192 MYDB_END_ALLOW_THREADS;
4194 RETURN_IF_ERR();
4195 RETURN_NONE();
4198 static PyObject*
4199 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4201 int err;
4202 long shm_key = 0;
4204 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4205 return NULL;
4206 CHECK_ENV_NOT_CLOSED(self);
4208 err = self->db_env->set_shm_key(self->db_env, shm_key);
4209 RETURN_IF_ERR();
4210 RETURN_NONE();
4213 static PyObject*
4214 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4216 int err, gbytes=0, bytes=0, ncache=0;
4218 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4219 &gbytes, &bytes, &ncache))
4220 return NULL;
4221 CHECK_ENV_NOT_CLOSED(self);
4223 MYDB_BEGIN_ALLOW_THREADS;
4224 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4225 MYDB_END_ALLOW_THREADS;
4226 RETURN_IF_ERR();
4227 RETURN_NONE();
4231 static PyObject*
4232 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4234 int err, flags=0, onoff=0;
4236 if (!PyArg_ParseTuple(args, "ii:set_flags",
4237 &flags, &onoff))
4238 return NULL;
4239 CHECK_ENV_NOT_CLOSED(self);
4241 MYDB_BEGIN_ALLOW_THREADS;
4242 err = self->db_env->set_flags(self->db_env, flags, onoff);
4243 MYDB_END_ALLOW_THREADS;
4244 RETURN_IF_ERR();
4245 RETURN_NONE();
4249 #if (DBVER >= 47)
4250 static PyObject*
4251 DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4253 int err, flags, onoff;
4255 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4256 &flags, &onoff))
4257 return NULL;
4258 CHECK_ENV_NOT_CLOSED(self);
4260 MYDB_BEGIN_ALLOW_THREADS;
4261 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4262 MYDB_END_ALLOW_THREADS;
4263 RETURN_IF_ERR();
4264 RETURN_NONE();
4266 #endif /* DBVER >= 47 */
4269 static PyObject*
4270 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4272 int err;
4273 char *dir;
4275 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4276 return NULL;
4277 CHECK_ENV_NOT_CLOSED(self);
4279 MYDB_BEGIN_ALLOW_THREADS;
4280 err = self->db_env->set_data_dir(self->db_env, dir);
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4287 static PyObject*
4288 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4290 int err, lg_bsize;
4292 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4293 return NULL;
4294 CHECK_ENV_NOT_CLOSED(self);
4296 MYDB_BEGIN_ALLOW_THREADS;
4297 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4298 MYDB_END_ALLOW_THREADS;
4299 RETURN_IF_ERR();
4300 RETURN_NONE();
4304 static PyObject*
4305 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4307 int err;
4308 char *dir;
4310 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4311 return NULL;
4312 CHECK_ENV_NOT_CLOSED(self);
4314 MYDB_BEGIN_ALLOW_THREADS;
4315 err = self->db_env->set_lg_dir(self->db_env, dir);
4316 MYDB_END_ALLOW_THREADS;
4317 RETURN_IF_ERR();
4318 RETURN_NONE();
4321 static PyObject*
4322 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4324 int err, lg_max;
4326 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4327 return NULL;
4328 CHECK_ENV_NOT_CLOSED(self);
4330 MYDB_BEGIN_ALLOW_THREADS;
4331 err = self->db_env->set_lg_max(self->db_env, lg_max);
4332 MYDB_END_ALLOW_THREADS;
4333 RETURN_IF_ERR();
4334 RETURN_NONE();
4337 #if (DBVER >= 42)
4338 static PyObject*
4339 DBEnv_get_lg_max(DBEnvObject* self)
4341 int err;
4342 u_int32_t lg_max;
4344 CHECK_ENV_NOT_CLOSED(self);
4346 MYDB_BEGIN_ALLOW_THREADS;
4347 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4348 MYDB_END_ALLOW_THREADS;
4349 RETURN_IF_ERR();
4350 return NUMBER_FromLong(lg_max);
4352 #endif
4355 static PyObject*
4356 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4358 int err, lg_max;
4360 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4361 return NULL;
4362 CHECK_ENV_NOT_CLOSED(self);
4364 MYDB_BEGIN_ALLOW_THREADS;
4365 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4366 MYDB_END_ALLOW_THREADS;
4367 RETURN_IF_ERR();
4368 RETURN_NONE();
4372 static PyObject*
4373 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4375 int err, lk_detect;
4377 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4378 return NULL;
4379 CHECK_ENV_NOT_CLOSED(self);
4381 MYDB_BEGIN_ALLOW_THREADS;
4382 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4383 MYDB_END_ALLOW_THREADS;
4384 RETURN_IF_ERR();
4385 RETURN_NONE();
4389 #if (DBVER < 45)
4390 static PyObject*
4391 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4393 int err, max;
4395 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4396 return NULL;
4397 CHECK_ENV_NOT_CLOSED(self);
4399 MYDB_BEGIN_ALLOW_THREADS;
4400 err = self->db_env->set_lk_max(self->db_env, max);
4401 MYDB_END_ALLOW_THREADS;
4402 RETURN_IF_ERR();
4403 RETURN_NONE();
4405 #endif
4409 static PyObject*
4410 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4412 int err, max;
4414 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4415 return NULL;
4416 CHECK_ENV_NOT_CLOSED(self);
4418 MYDB_BEGIN_ALLOW_THREADS;
4419 err = self->db_env->set_lk_max_locks(self->db_env, max);
4420 MYDB_END_ALLOW_THREADS;
4421 RETURN_IF_ERR();
4422 RETURN_NONE();
4426 static PyObject*
4427 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4429 int err, max;
4431 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4432 return NULL;
4433 CHECK_ENV_NOT_CLOSED(self);
4435 MYDB_BEGIN_ALLOW_THREADS;
4436 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4437 MYDB_END_ALLOW_THREADS;
4438 RETURN_IF_ERR();
4439 RETURN_NONE();
4443 static PyObject*
4444 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4446 int err, max;
4448 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4449 return NULL;
4450 CHECK_ENV_NOT_CLOSED(self);
4452 MYDB_BEGIN_ALLOW_THREADS;
4453 err = self->db_env->set_lk_max_objects(self->db_env, max);
4454 MYDB_END_ALLOW_THREADS;
4455 RETURN_IF_ERR();
4456 RETURN_NONE();
4460 static PyObject*
4461 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4463 int err, mp_mmapsize;
4465 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4466 return NULL;
4467 CHECK_ENV_NOT_CLOSED(self);
4469 MYDB_BEGIN_ALLOW_THREADS;
4470 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4471 MYDB_END_ALLOW_THREADS;
4472 RETURN_IF_ERR();
4473 RETURN_NONE();
4477 static PyObject*
4478 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4480 int err;
4481 char *dir;
4483 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4484 return NULL;
4485 CHECK_ENV_NOT_CLOSED(self);
4487 MYDB_BEGIN_ALLOW_THREADS;
4488 err = self->db_env->set_tmp_dir(self->db_env, dir);
4489 MYDB_END_ALLOW_THREADS;
4490 RETURN_IF_ERR();
4491 RETURN_NONE();
4495 static PyObject*
4496 DBEnv_txn_recover(DBEnvObject* self)
4498 int flags = DB_FIRST;
4499 int err, i;
4500 PyObject *list, *tuple, *gid;
4501 DBTxnObject *txn;
4502 #define PREPLIST_LEN 16
4503 DB_PREPLIST preplist[PREPLIST_LEN];
4504 long retp;
4506 CHECK_ENV_NOT_CLOSED(self);
4508 list=PyList_New(0);
4509 if (!list)
4510 return NULL;
4511 while (!0) {
4512 MYDB_BEGIN_ALLOW_THREADS
4513 err=self->db_env->txn_recover(self->db_env,
4514 preplist, PREPLIST_LEN, &retp, flags);
4515 #undef PREPLIST_LEN
4516 MYDB_END_ALLOW_THREADS
4517 if (err) {
4518 Py_DECREF(list);
4519 RETURN_IF_ERR();
4521 if (!retp) break;
4522 flags=DB_NEXT; /* Prepare for next loop pass */
4523 for (i=0; i<retp; i++) {
4524 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
4525 DB_XIDDATASIZE);
4526 if (!gid) {
4527 Py_DECREF(list);
4528 return NULL;
4530 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4531 if (!txn) {
4532 Py_DECREF(list);
4533 Py_DECREF(gid);
4534 return NULL;
4536 txn->flag_prepare=1; /* Recover state */
4537 tuple=PyTuple_New(2);
4538 if (!tuple) {
4539 Py_DECREF(list);
4540 Py_DECREF(gid);
4541 Py_DECREF(txn);
4542 return NULL;
4544 if (PyTuple_SetItem(tuple, 0, gid)) {
4545 Py_DECREF(list);
4546 Py_DECREF(gid);
4547 Py_DECREF(txn);
4548 Py_DECREF(tuple);
4549 return NULL;
4551 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4552 Py_DECREF(list);
4553 Py_DECREF(txn);
4554 Py_DECREF(tuple); /* This delete the "gid" also */
4555 return NULL;
4557 if (PyList_Append(list, tuple)) {
4558 Py_DECREF(list);
4559 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4560 return NULL;
4562 Py_DECREF(tuple);
4565 return list;
4568 static PyObject*
4569 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4571 int flags = 0;
4572 PyObject* txnobj = NULL;
4573 DB_TXN *txn = NULL;
4574 static char* kwnames[] = { "parent", "flags", NULL };
4576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4577 &txnobj, &flags))
4578 return NULL;
4580 if (!checkTxnObj(txnobj, &txn))
4581 return NULL;
4582 CHECK_ENV_NOT_CLOSED(self);
4584 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
4588 static PyObject*
4589 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4591 int err, kbyte=0, min=0, flags=0;
4593 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4594 return NULL;
4595 CHECK_ENV_NOT_CLOSED(self);
4597 MYDB_BEGIN_ALLOW_THREADS;
4598 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4599 MYDB_END_ALLOW_THREADS;
4600 RETURN_IF_ERR();
4601 RETURN_NONE();
4605 static PyObject*
4606 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4608 int err, max;
4610 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4611 return NULL;
4612 CHECK_ENV_NOT_CLOSED(self);
4614 err = self->db_env->set_tx_max(self->db_env, max);
4615 RETURN_IF_ERR();
4616 RETURN_NONE();
4620 static PyObject*
4621 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4623 int err;
4624 long stamp;
4625 time_t timestamp;
4627 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4628 return NULL;
4629 CHECK_ENV_NOT_CLOSED(self);
4630 timestamp = (time_t)stamp;
4631 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4632 RETURN_IF_ERR();
4633 RETURN_NONE();
4637 static PyObject*
4638 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4640 int err, atype, flags=0;
4641 int aborted = 0;
4643 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4644 return NULL;
4645 CHECK_ENV_NOT_CLOSED(self);
4647 MYDB_BEGIN_ALLOW_THREADS;
4648 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4649 MYDB_END_ALLOW_THREADS;
4650 RETURN_IF_ERR();
4651 return NUMBER_FromLong(aborted);
4655 static PyObject*
4656 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4658 int flags=0;
4659 int locker, lock_mode;
4660 DBT obj;
4661 PyObject* objobj;
4663 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4664 return NULL;
4667 if (!make_dbt(objobj, &obj))
4668 return NULL;
4670 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4674 static PyObject*
4675 DBEnv_lock_id(DBEnvObject* self)
4677 int err;
4678 u_int32_t theID;
4680 CHECK_ENV_NOT_CLOSED(self);
4681 MYDB_BEGIN_ALLOW_THREADS;
4682 err = self->db_env->lock_id(self->db_env, &theID);
4683 MYDB_END_ALLOW_THREADS;
4684 RETURN_IF_ERR();
4686 return NUMBER_FromLong((long)theID);
4689 static PyObject*
4690 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4692 int err;
4693 u_int32_t theID;
4695 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4696 return NULL;
4698 CHECK_ENV_NOT_CLOSED(self);
4699 MYDB_BEGIN_ALLOW_THREADS;
4700 err = self->db_env->lock_id_free(self->db_env, theID);
4701 MYDB_END_ALLOW_THREADS;
4702 RETURN_IF_ERR();
4703 RETURN_NONE();
4706 static PyObject*
4707 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4709 int err;
4710 DBLockObject* dblockobj;
4712 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4713 return NULL;
4715 CHECK_ENV_NOT_CLOSED(self);
4716 MYDB_BEGIN_ALLOW_THREADS;
4717 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4718 MYDB_END_ALLOW_THREADS;
4719 RETURN_IF_ERR();
4720 RETURN_NONE();
4723 #if (DBVER >= 44)
4724 static PyObject*
4725 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4727 int err;
4728 char *file;
4729 u_int32_t flags = 0;
4730 static char* kwnames[] = { "file", "flags", NULL};
4732 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4733 &file, &flags))
4734 return NULL;
4735 CHECK_ENV_NOT_CLOSED(self);
4737 MYDB_BEGIN_ALLOW_THREADS;
4738 err = self->db_env->lsn_reset(self->db_env, file, flags);
4739 MYDB_END_ALLOW_THREADS;
4740 RETURN_IF_ERR();
4741 RETURN_NONE();
4743 #endif /* DBVER >= 4.4 */
4745 static PyObject*
4746 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4748 int err;
4749 DB_LOG_STAT* statp = NULL;
4750 PyObject* d = NULL;
4751 u_int32_t flags = 0;
4753 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4754 return NULL;
4755 CHECK_ENV_NOT_CLOSED(self);
4757 MYDB_BEGIN_ALLOW_THREADS;
4758 err = self->db_env->log_stat(self->db_env, &statp, flags);
4759 MYDB_END_ALLOW_THREADS;
4760 RETURN_IF_ERR();
4762 /* Turn the stat structure into a dictionary */
4763 d = PyDict_New();
4764 if (d == NULL) {
4765 if (statp)
4766 free(statp);
4767 return NULL;
4770 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4772 MAKE_ENTRY(magic);
4773 MAKE_ENTRY(version);
4774 MAKE_ENTRY(mode);
4775 MAKE_ENTRY(lg_bsize);
4776 #if (DBVER >= 44)
4777 MAKE_ENTRY(lg_size);
4778 MAKE_ENTRY(record);
4779 #endif
4780 #if (DBVER < 41)
4781 MAKE_ENTRY(lg_max);
4782 #endif
4783 MAKE_ENTRY(w_mbytes);
4784 MAKE_ENTRY(w_bytes);
4785 MAKE_ENTRY(wc_mbytes);
4786 MAKE_ENTRY(wc_bytes);
4787 MAKE_ENTRY(wcount);
4788 MAKE_ENTRY(wcount_fill);
4789 #if (DBVER >= 44)
4790 MAKE_ENTRY(rcount);
4791 #endif
4792 MAKE_ENTRY(scount);
4793 MAKE_ENTRY(cur_file);
4794 MAKE_ENTRY(cur_offset);
4795 MAKE_ENTRY(disk_file);
4796 MAKE_ENTRY(disk_offset);
4797 MAKE_ENTRY(maxcommitperflush);
4798 MAKE_ENTRY(mincommitperflush);
4799 MAKE_ENTRY(regsize);
4800 MAKE_ENTRY(region_wait);
4801 MAKE_ENTRY(region_nowait);
4803 #undef MAKE_ENTRY
4804 free(statp);
4805 return d;
4806 } /* DBEnv_log_stat */
4809 static PyObject*
4810 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4812 int err;
4813 DB_LOCK_STAT* sp;
4814 PyObject* d = NULL;
4815 u_int32_t flags = 0;
4817 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4818 return NULL;
4819 CHECK_ENV_NOT_CLOSED(self);
4821 MYDB_BEGIN_ALLOW_THREADS;
4822 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4823 MYDB_END_ALLOW_THREADS;
4824 RETURN_IF_ERR();
4826 /* Turn the stat structure into a dictionary */
4827 d = PyDict_New();
4828 if (d == NULL) {
4829 free(sp);
4830 return NULL;
4833 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4835 #if (DBVER < 41)
4836 MAKE_ENTRY(lastid);
4837 #endif
4838 #if (DBVER >=41)
4839 MAKE_ENTRY(id);
4840 MAKE_ENTRY(cur_maxid);
4841 #endif
4842 MAKE_ENTRY(nmodes);
4843 MAKE_ENTRY(maxlocks);
4844 MAKE_ENTRY(maxlockers);
4845 MAKE_ENTRY(maxobjects);
4846 MAKE_ENTRY(nlocks);
4847 MAKE_ENTRY(maxnlocks);
4848 MAKE_ENTRY(nlockers);
4849 MAKE_ENTRY(maxnlockers);
4850 MAKE_ENTRY(nobjects);
4851 MAKE_ENTRY(maxnobjects);
4852 MAKE_ENTRY(nrequests);
4853 MAKE_ENTRY(nreleases);
4854 #if (DBVER >= 44)
4855 MAKE_ENTRY(nupgrade);
4856 MAKE_ENTRY(ndowngrade);
4857 #endif
4858 #if (DBVER < 44)
4859 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4860 MAKE_ENTRY(nconflicts);
4861 #else
4862 MAKE_ENTRY(lock_nowait);
4863 MAKE_ENTRY(lock_wait);
4864 #endif
4865 MAKE_ENTRY(ndeadlocks);
4866 #if (DBVER >= 41)
4867 MAKE_ENTRY(locktimeout);
4868 MAKE_ENTRY(txntimeout);
4869 #endif
4870 MAKE_ENTRY(nlocktimeouts);
4871 MAKE_ENTRY(ntxntimeouts);
4872 #if (DBVER >= 46)
4873 MAKE_ENTRY(objs_wait);
4874 MAKE_ENTRY(objs_nowait);
4875 MAKE_ENTRY(lockers_wait);
4876 MAKE_ENTRY(lockers_nowait);
4877 #if (DBVER >= 47)
4878 MAKE_ENTRY(lock_wait);
4879 MAKE_ENTRY(lock_nowait);
4880 #else
4881 MAKE_ENTRY(locks_wait);
4882 MAKE_ENTRY(locks_nowait);
4883 #endif
4884 MAKE_ENTRY(hash_len);
4885 #endif
4886 MAKE_ENTRY(regsize);
4887 MAKE_ENTRY(region_wait);
4888 MAKE_ENTRY(region_nowait);
4890 #undef MAKE_ENTRY
4891 free(sp);
4892 return d;
4895 static PyObject*
4896 DBEnv_log_flush(DBEnvObject* self)
4898 int err;
4900 CHECK_ENV_NOT_CLOSED(self);
4902 MYDB_BEGIN_ALLOW_THREADS
4903 err = self->db_env->log_flush(self->db_env, NULL);
4904 MYDB_END_ALLOW_THREADS
4906 RETURN_IF_ERR();
4907 RETURN_NONE();
4910 static PyObject*
4911 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4913 int flags=0;
4914 int err;
4915 char **log_list = NULL;
4916 PyObject* list;
4917 PyObject* item = NULL;
4919 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4920 return NULL;
4922 CHECK_ENV_NOT_CLOSED(self);
4923 MYDB_BEGIN_ALLOW_THREADS;
4924 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4925 MYDB_END_ALLOW_THREADS;
4926 RETURN_IF_ERR();
4928 list = PyList_New(0);
4929 if (list == NULL) {
4930 if (log_list)
4931 free(log_list);
4932 return NULL;
4935 if (log_list) {
4936 char **log_list_start;
4937 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4938 item = PyBytes_FromString (*log_list);
4939 if (item == NULL) {
4940 Py_DECREF(list);
4941 list = NULL;
4942 break;
4944 if (PyList_Append(list, item)) {
4945 Py_DECREF(list);
4946 list = NULL;
4947 Py_DECREF(item);
4948 break;
4950 Py_DECREF(item);
4952 free(log_list_start);
4954 return list;
4958 static PyObject*
4959 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4961 int err;
4962 DB_TXN_STAT* sp;
4963 PyObject* d = NULL;
4964 u_int32_t flags=0;
4966 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4967 return NULL;
4968 CHECK_ENV_NOT_CLOSED(self);
4970 MYDB_BEGIN_ALLOW_THREADS;
4971 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4972 MYDB_END_ALLOW_THREADS;
4973 RETURN_IF_ERR();
4975 /* Turn the stat structure into a dictionary */
4976 d = PyDict_New();
4977 if (d == NULL) {
4978 free(sp);
4979 return NULL;
4982 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4983 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4984 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
4986 MAKE_DB_LSN_ENTRY(last_ckp);
4987 MAKE_TIME_T_ENTRY(time_ckp);
4988 MAKE_ENTRY(last_txnid);
4989 MAKE_ENTRY(maxtxns);
4990 MAKE_ENTRY(nactive);
4991 MAKE_ENTRY(maxnactive);
4992 #if (DBVER >= 45)
4993 MAKE_ENTRY(nsnapshot);
4994 MAKE_ENTRY(maxnsnapshot);
4995 #endif
4996 MAKE_ENTRY(nbegins);
4997 MAKE_ENTRY(naborts);
4998 MAKE_ENTRY(ncommits);
4999 MAKE_ENTRY(nrestores);
5000 MAKE_ENTRY(regsize);
5001 MAKE_ENTRY(region_wait);
5002 MAKE_ENTRY(region_nowait);
5004 #undef MAKE_DB_LSN_ENTRY
5005 #undef MAKE_ENTRY
5006 #undef MAKE_TIME_T_ENTRY
5007 free(sp);
5008 return d;
5012 static PyObject*
5013 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
5015 int flags=0;
5016 int oldValue=0;
5018 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
5019 return NULL;
5020 CHECK_ENV_NOT_CLOSED(self);
5022 if (self->moduleFlags.getReturnsNone)
5023 ++oldValue;
5024 if (self->moduleFlags.cursorSetReturnsNone)
5025 ++oldValue;
5026 self->moduleFlags.getReturnsNone = (flags >= 1);
5027 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
5028 return NUMBER_FromLong(oldValue);
5031 static PyObject*
5032 DBEnv_get_private(DBEnvObject* self)
5034 /* We can give out the private field even if dbenv is closed */
5035 Py_INCREF(self->private_obj);
5036 return self->private_obj;
5039 static PyObject*
5040 DBEnv_set_private(DBEnvObject* self, PyObject* private_obj)
5042 /* We can set the private field even if dbenv is closed */
5043 Py_DECREF(self->private_obj);
5044 Py_INCREF(private_obj);
5045 self->private_obj = private_obj;
5046 RETURN_NONE();
5050 static PyObject*
5051 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5053 int err;
5054 char *host;
5055 long cl_timeout=0, sv_timeout=0;
5057 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
5059 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
5060 &host, &cl_timeout, &sv_timeout))
5061 return NULL;
5062 CHECK_ENV_NOT_CLOSED(self);
5064 MYDB_BEGIN_ALLOW_THREADS;
5065 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
5066 sv_timeout, 0);
5067 MYDB_END_ALLOW_THREADS;
5068 RETURN_IF_ERR();
5069 RETURN_NONE();
5072 static PyObject*
5073 DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5075 int err;
5076 int which, onoff;
5078 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5079 return NULL;
5081 CHECK_ENV_NOT_CLOSED(self);
5082 MYDB_BEGIN_ALLOW_THREADS;
5083 err = self->db_env->set_verbose(self->db_env, which, onoff);
5084 MYDB_END_ALLOW_THREADS;
5085 RETURN_IF_ERR();
5086 RETURN_NONE();
5089 #if (DBVER >= 42)
5090 static PyObject*
5091 DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5093 int err;
5094 int which;
5095 int verbose;
5097 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5098 return NULL;
5100 CHECK_ENV_NOT_CLOSED(self);
5101 MYDB_BEGIN_ALLOW_THREADS;
5102 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5103 MYDB_END_ALLOW_THREADS;
5104 RETURN_IF_ERR();
5105 return PyBool_FromLong(verbose);
5107 #endif
5109 #if (DBVER >= 45)
5110 static void
5111 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5113 DBEnvObject *dbenv;
5114 PyObject* callback;
5115 PyObject* args;
5116 PyObject* result = NULL;
5118 MYDB_BEGIN_BLOCK_THREADS;
5119 dbenv = (DBEnvObject *)db_env->app_private;
5120 callback = dbenv->event_notifyCallback;
5121 if (callback) {
5122 if (event == DB_EVENT_REP_NEWMASTER) {
5123 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5124 } else {
5125 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5127 if (args) {
5128 result = PyEval_CallObject(callback, args);
5130 if ((!args) || (!result)) {
5131 PyErr_Print();
5133 Py_XDECREF(args);
5134 Py_XDECREF(result);
5136 MYDB_END_BLOCK_THREADS;
5138 #endif
5140 #if (DBVER >= 45)
5141 static PyObject*
5142 DBEnv_set_event_notify(DBEnvObject* self, PyObject* notifyFunc)
5144 int err;
5146 CHECK_ENV_NOT_CLOSED(self);
5148 if (!PyCallable_Check(notifyFunc)) {
5149 makeTypeError("Callable", notifyFunc);
5150 return NULL;
5153 Py_XDECREF(self->event_notifyCallback);
5154 Py_INCREF(notifyFunc);
5155 self->event_notifyCallback = notifyFunc;
5157 /* This is to workaround a problem with un-initialized threads (see
5158 comment in DB_associate) */
5159 #ifdef WITH_THREAD
5160 PyEval_InitThreads();
5161 #endif
5163 MYDB_BEGIN_ALLOW_THREADS;
5164 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5165 MYDB_END_ALLOW_THREADS;
5167 if (err) {
5168 Py_DECREF(notifyFunc);
5169 self->event_notifyCallback = NULL;
5172 RETURN_IF_ERR();
5173 RETURN_NONE();
5175 #endif
5178 /* --------------------------------------------------------------------- */
5179 /* REPLICATION METHODS: Base Replication */
5182 static PyObject*
5183 DBEnv_rep_process_message(DBEnvObject* self, PyObject* args)
5185 int err;
5186 PyObject *control_py, *rec_py;
5187 DBT control, rec;
5188 int envid;
5189 #if (DBVER >= 42)
5190 DB_LSN lsn;
5191 #endif
5193 if (!PyArg_ParseTuple(args, "OOi:rep_process_message", &control_py,
5194 &rec_py, &envid))
5195 return NULL;
5196 CHECK_ENV_NOT_CLOSED(self);
5198 if (!make_dbt(control_py, &control))
5199 return NULL;
5200 if (!make_dbt(rec_py, &rec))
5201 return NULL;
5203 MYDB_BEGIN_ALLOW_THREADS;
5204 #if (DBVER >= 46)
5205 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5206 envid, &lsn);
5207 #else
5208 #if (DBVER >= 42)
5209 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5210 &envid, &lsn);
5211 #else
5212 err = self->db_env->rep_process_message(self->db_env, &control, &rec,
5213 &envid);
5214 #endif
5215 #endif
5216 MYDB_END_ALLOW_THREADS;
5217 switch (err) {
5218 case DB_REP_NEWMASTER :
5219 return Py_BuildValue("(iO)", envid, Py_None);
5220 break;
5222 case DB_REP_DUPMASTER :
5223 case DB_REP_HOLDELECTION :
5224 #if (DBVER >= 44)
5225 case DB_REP_IGNORE :
5226 case DB_REP_JOIN_FAILURE :
5227 #endif
5228 return Py_BuildValue("(iO)", err, Py_None);
5229 break;
5230 case DB_REP_NEWSITE :
5232 PyObject *tmp, *r;
5234 if (!(tmp = PyBytes_FromStringAndSize(rec.data, rec.size))) {
5235 return NULL;
5238 r = Py_BuildValue("(iO)", err, tmp);
5239 Py_DECREF(tmp);
5240 return r;
5241 break;
5243 #if (DBVER >= 42)
5244 case DB_REP_NOTPERM :
5245 case DB_REP_ISPERM :
5246 return Py_BuildValue("(i(ll))", err, lsn.file, lsn.offset);
5247 break;
5248 #endif
5250 RETURN_IF_ERR();
5251 return Py_BuildValue("(OO)", Py_None, Py_None);
5254 static int
5255 _DBEnv_rep_transportCallback(DB_ENV* db_env, const DBT* control, const DBT* rec,
5256 const DB_LSN *lsn, int envid, u_int32_t flags)
5258 DBEnvObject *dbenv;
5259 PyObject* rep_transport;
5260 PyObject* args;
5261 PyObject *a, *b;
5262 PyObject* result = NULL;
5263 int ret=0;
5265 MYDB_BEGIN_BLOCK_THREADS;
5266 dbenv = (DBEnvObject *)db_env->app_private;
5267 rep_transport = dbenv->rep_transport;
5270 ** The errors in 'a' or 'b' are detected in "Py_BuildValue".
5272 a = PyBytes_FromStringAndSize(control->data, control->size);
5273 b = PyBytes_FromStringAndSize(rec->data, rec->size);
5275 args = Py_BuildValue(
5276 #if (PY_VERSION_HEX >= 0x02040000)
5277 "(OOO(ll)iI)",
5278 #else
5279 "(OOO(ll)ii)",
5280 #endif
5281 dbenv,
5282 a, b,
5283 lsn->file, lsn->offset, envid, flags);
5284 if (args) {
5285 result = PyEval_CallObject(rep_transport, args);
5288 if ((!args) || (!result)) {
5289 PyErr_Print();
5290 ret = -1;
5292 Py_XDECREF(a);
5293 Py_XDECREF(b);
5294 Py_XDECREF(args);
5295 Py_XDECREF(result);
5296 MYDB_END_BLOCK_THREADS;
5297 return ret;
5300 #if (DBVER <= 41)
5301 static int
5302 _DBEnv_rep_transportCallbackOLD(DB_ENV* db_env, const DBT* control, const DBT* rec,
5303 int envid, u_int32_t flags)
5305 DB_LSN lsn;
5307 lsn.file = -1; /* Dummy values */
5308 lsn.offset = -1;
5309 return _DBEnv_rep_transportCallback(db_env, control, rec, &lsn, envid,
5310 flags);
5312 #endif
5314 static PyObject*
5315 DBEnv_rep_set_transport(DBEnvObject* self, PyObject* args)
5317 int err;
5318 int envid;
5319 PyObject *rep_transport;
5321 if (!PyArg_ParseTuple(args, "iO:rep_set_transport", &envid, &rep_transport))
5322 return NULL;
5323 CHECK_ENV_NOT_CLOSED(self);
5324 if (!PyCallable_Check(rep_transport)) {
5325 makeTypeError("Callable", rep_transport);
5326 return NULL;
5329 MYDB_BEGIN_ALLOW_THREADS;
5330 #if (DBVER >=45)
5331 err = self->db_env->rep_set_transport(self->db_env, envid,
5332 &_DBEnv_rep_transportCallback);
5333 #else
5334 #if (DBVER >= 42)
5335 err = self->db_env->set_rep_transport(self->db_env, envid,
5336 &_DBEnv_rep_transportCallback);
5337 #else
5338 err = self->db_env->set_rep_transport(self->db_env, envid,
5339 &_DBEnv_rep_transportCallbackOLD);
5340 #endif
5341 #endif
5342 MYDB_END_ALLOW_THREADS;
5343 RETURN_IF_ERR();
5345 Py_DECREF(self->rep_transport);
5346 Py_INCREF(rep_transport);
5347 self->rep_transport = rep_transport;
5348 RETURN_NONE();
5351 #if (DBVER >= 47)
5352 static PyObject*
5353 DBEnv_rep_set_request(DBEnvObject* self, PyObject* args)
5355 int err;
5356 unsigned int minimum, maximum;
5358 if (!PyArg_ParseTuple(args,"II:rep_set_request", &minimum, &maximum))
5359 return NULL;
5360 CHECK_ENV_NOT_CLOSED(self);
5362 MYDB_BEGIN_ALLOW_THREADS;
5363 err = self->db_env->rep_set_request(self->db_env, minimum, maximum);
5364 MYDB_END_ALLOW_THREADS;
5365 RETURN_IF_ERR();
5366 RETURN_NONE();
5369 static PyObject*
5370 DBEnv_rep_get_request(DBEnvObject* self)
5372 int err;
5373 u_int32_t minimum, maximum;
5375 CHECK_ENV_NOT_CLOSED(self);
5376 MYDB_BEGIN_ALLOW_THREADS;
5377 err = self->db_env->rep_get_request(self->db_env, &minimum, &maximum);
5378 MYDB_END_ALLOW_THREADS;
5379 RETURN_IF_ERR();
5380 #if (PY_VERSION_HEX >= 0x02040000)
5381 return Py_BuildValue("II", minimum, maximum);
5382 #else
5383 return Py_BuildValue("ii", minimum, maximum);
5384 #endif
5386 #endif
5388 #if (DBVER >= 45)
5389 static PyObject*
5390 DBEnv_rep_set_limit(DBEnvObject* self, PyObject* args)
5392 int err;
5393 int limit;
5395 if (!PyArg_ParseTuple(args,"i:rep_set_limit", &limit))
5396 return NULL;
5397 CHECK_ENV_NOT_CLOSED(self);
5399 MYDB_BEGIN_ALLOW_THREADS;
5400 err = self->db_env->rep_set_limit(self->db_env, 0, limit);
5401 MYDB_END_ALLOW_THREADS;
5402 RETURN_IF_ERR();
5403 RETURN_NONE();
5406 static PyObject*
5407 DBEnv_rep_get_limit(DBEnvObject* self)
5409 int err;
5410 u_int32_t gbytes, bytes;
5412 CHECK_ENV_NOT_CLOSED(self);
5413 MYDB_BEGIN_ALLOW_THREADS;
5414 err = self->db_env->rep_get_limit(self->db_env, &gbytes, &bytes);
5415 MYDB_END_ALLOW_THREADS;
5416 RETURN_IF_ERR();
5417 return NUMBER_FromLong(bytes);
5419 #endif
5421 #if (DBVER >= 44)
5422 static PyObject*
5423 DBEnv_rep_set_config(DBEnvObject* self, PyObject* args)
5425 int err;
5426 int which;
5427 int onoff;
5429 if (!PyArg_ParseTuple(args,"ii:rep_set_config", &which, &onoff))
5430 return NULL;
5431 CHECK_ENV_NOT_CLOSED(self);
5433 MYDB_BEGIN_ALLOW_THREADS;
5434 err = self->db_env->rep_set_config(self->db_env, which, onoff);
5435 MYDB_END_ALLOW_THREADS;
5436 RETURN_IF_ERR();
5437 RETURN_NONE();
5440 static PyObject*
5441 DBEnv_rep_get_config(DBEnvObject* self, PyObject* args)
5443 int err;
5444 int which;
5445 int onoff;
5447 if (!PyArg_ParseTuple(args, "i:rep_get_config", &which)) {
5448 return NULL;
5450 CHECK_ENV_NOT_CLOSED(self);
5451 MYDB_BEGIN_ALLOW_THREADS;
5452 err = self->db_env->rep_get_config(self->db_env, which, &onoff);
5453 MYDB_END_ALLOW_THREADS;
5454 RETURN_IF_ERR();
5455 return PyBool_FromLong(onoff);
5457 #endif
5459 #if (DBVER >= 46)
5460 static PyObject*
5461 DBEnv_rep_elect(DBEnvObject* self, PyObject* args)
5463 int err;
5464 u_int32_t nsites, nvotes;
5466 if (!PyArg_ParseTuple(args, "II:rep_elect", &nsites, &nvotes)) {
5467 return NULL;
5469 CHECK_ENV_NOT_CLOSED(self);
5470 MYDB_BEGIN_ALLOW_THREADS;
5471 err = self->db_env->rep_elect(self->db_env, nvotes, nvotes, 0);
5472 MYDB_END_ALLOW_THREADS;
5473 RETURN_IF_ERR();
5474 RETURN_NONE();
5476 #endif
5478 static PyObject*
5479 DBEnv_rep_start(DBEnvObject* self, PyObject* args, PyObject* kwargs)
5481 int err;
5482 PyObject *cdata_py = Py_None;
5483 DBT cdata;
5484 int flags;
5485 static char* kwnames[] = {"flags","cdata", NULL};
5487 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5488 "i|O:rep_start", kwnames, &flags, &cdata_py))
5490 return NULL;
5492 CHECK_ENV_NOT_CLOSED(self);
5494 if (!make_dbt(cdata_py, &cdata))
5495 return NULL;
5497 MYDB_BEGIN_ALLOW_THREADS;
5498 err = self->db_env->rep_start(self->db_env, cdata.size ? &cdata : NULL,
5499 flags);
5500 MYDB_END_ALLOW_THREADS;
5501 RETURN_IF_ERR();
5502 RETURN_NONE();
5505 #if (DBVER >= 44)
5506 static PyObject*
5507 DBEnv_rep_sync(DBEnvObject* self)
5509 int err;
5511 CHECK_ENV_NOT_CLOSED(self);
5512 MYDB_BEGIN_ALLOW_THREADS;
5513 err = self->db_env->rep_sync(self->db_env, 0);
5514 MYDB_END_ALLOW_THREADS;
5515 RETURN_IF_ERR();
5516 RETURN_NONE();
5518 #endif
5521 #if (DBVER >= 45)
5522 static PyObject*
5523 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5525 int err;
5526 int nsites;
5528 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5529 return NULL;
5531 CHECK_ENV_NOT_CLOSED(self);
5532 MYDB_BEGIN_ALLOW_THREADS;
5533 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5534 MYDB_END_ALLOW_THREADS;
5535 RETURN_IF_ERR();
5536 RETURN_NONE();
5539 static PyObject*
5540 DBEnv_rep_get_nsites(DBEnvObject* self)
5542 int err;
5543 #if (DBVER >= 47)
5544 u_int32_t nsites;
5545 #else
5546 int nsites;
5547 #endif
5549 CHECK_ENV_NOT_CLOSED(self);
5550 MYDB_BEGIN_ALLOW_THREADS;
5551 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5552 MYDB_END_ALLOW_THREADS;
5553 RETURN_IF_ERR();
5554 return NUMBER_FromLong(nsites);
5557 static PyObject*
5558 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5560 int err;
5561 int priority;
5563 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5564 return NULL;
5566 CHECK_ENV_NOT_CLOSED(self);
5567 MYDB_BEGIN_ALLOW_THREADS;
5568 err = self->db_env->rep_set_priority(self->db_env, priority);
5569 MYDB_END_ALLOW_THREADS;
5570 RETURN_IF_ERR();
5571 RETURN_NONE();
5574 static PyObject*
5575 DBEnv_rep_get_priority(DBEnvObject* self)
5577 int err;
5578 #if (DBVER >= 47)
5579 u_int32_t priority;
5580 #else
5581 int priority;
5582 #endif
5584 CHECK_ENV_NOT_CLOSED(self);
5585 MYDB_BEGIN_ALLOW_THREADS;
5586 err = self->db_env->rep_get_priority(self->db_env, &priority);
5587 MYDB_END_ALLOW_THREADS;
5588 RETURN_IF_ERR();
5589 return NUMBER_FromLong(priority);
5592 static PyObject*
5593 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5595 int err;
5596 int which, timeout;
5598 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5599 return NULL;
5601 CHECK_ENV_NOT_CLOSED(self);
5602 MYDB_BEGIN_ALLOW_THREADS;
5603 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5604 MYDB_END_ALLOW_THREADS;
5605 RETURN_IF_ERR();
5606 RETURN_NONE();
5609 static PyObject*
5610 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5612 int err;
5613 int which;
5614 u_int32_t timeout;
5616 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5617 return NULL;
5619 CHECK_ENV_NOT_CLOSED(self);
5620 MYDB_BEGIN_ALLOW_THREADS;
5621 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5622 MYDB_END_ALLOW_THREADS;
5623 RETURN_IF_ERR();
5624 return NUMBER_FromLong(timeout);
5626 #endif
5628 /* --------------------------------------------------------------------- */
5629 /* REPLICATION METHODS: Replication Manager */
5631 #if (DBVER >= 45)
5632 static PyObject*
5633 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5634 kwargs)
5636 int err;
5637 int nthreads, flags;
5638 static char* kwnames[] = {"nthreads","flags", NULL};
5640 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5641 "ii:repmgr_start", kwnames, &nthreads, &flags))
5643 return NULL;
5645 CHECK_ENV_NOT_CLOSED(self);
5646 MYDB_BEGIN_ALLOW_THREADS;
5647 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5648 MYDB_END_ALLOW_THREADS;
5649 RETURN_IF_ERR();
5650 RETURN_NONE();
5653 static PyObject*
5654 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5655 kwargs)
5657 int err;
5658 char *host;
5659 int port;
5660 int flags = 0;
5661 static char* kwnames[] = {"host", "port", "flags", NULL};
5663 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5664 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5666 return NULL;
5668 CHECK_ENV_NOT_CLOSED(self);
5669 MYDB_BEGIN_ALLOW_THREADS;
5670 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5671 MYDB_END_ALLOW_THREADS;
5672 RETURN_IF_ERR();
5673 RETURN_NONE();
5676 static PyObject*
5677 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5678 kwargs)
5680 int err;
5681 char *host;
5682 int port;
5683 int flags = 0;
5684 int eidp;
5685 static char* kwnames[] = {"host", "port", "flags", NULL};
5687 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5688 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5690 return NULL;
5692 CHECK_ENV_NOT_CLOSED(self);
5693 MYDB_BEGIN_ALLOW_THREADS;
5694 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5695 MYDB_END_ALLOW_THREADS;
5696 RETURN_IF_ERR();
5697 return NUMBER_FromLong(eidp);
5700 static PyObject*
5701 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5703 int err;
5704 int ack_policy;
5706 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5708 return NULL;
5710 CHECK_ENV_NOT_CLOSED(self);
5711 MYDB_BEGIN_ALLOW_THREADS;
5712 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5713 MYDB_END_ALLOW_THREADS;
5714 RETURN_IF_ERR();
5715 RETURN_NONE();
5718 static PyObject*
5719 DBEnv_repmgr_get_ack_policy(DBEnvObject* self)
5721 int err;
5722 int ack_policy;
5724 CHECK_ENV_NOT_CLOSED(self);
5725 MYDB_BEGIN_ALLOW_THREADS;
5726 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5727 MYDB_END_ALLOW_THREADS;
5728 RETURN_IF_ERR();
5729 return NUMBER_FromLong(ack_policy);
5732 static PyObject*
5733 DBEnv_repmgr_site_list(DBEnvObject* self)
5735 int err;
5736 unsigned int countp;
5737 DB_REPMGR_SITE *listp;
5738 PyObject *stats, *key, *tuple;
5740 CHECK_ENV_NOT_CLOSED(self);
5741 MYDB_BEGIN_ALLOW_THREADS;
5742 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5743 MYDB_END_ALLOW_THREADS;
5744 RETURN_IF_ERR();
5746 stats=PyDict_New();
5747 if (stats == NULL) {
5748 free(listp);
5749 return NULL;
5752 for(;countp--;) {
5753 key=NUMBER_FromLong(listp[countp].eid);
5754 if(!key) {
5755 Py_DECREF(stats);
5756 free(listp);
5757 return NULL;
5759 #if (PY_VERSION_HEX >= 0x02040000)
5760 tuple=Py_BuildValue("(sII)", listp[countp].host,
5761 listp[countp].port, listp[countp].status);
5762 #else
5763 tuple=Py_BuildValue("(sii)", listp[countp].host,
5764 listp[countp].port, listp[countp].status);
5765 #endif
5766 if(!tuple) {
5767 Py_DECREF(key);
5768 Py_DECREF(stats);
5769 free(listp);
5770 return NULL;
5772 if(PyDict_SetItem(stats, key, tuple)) {
5773 Py_DECREF(key);
5774 Py_DECREF(tuple);
5775 Py_DECREF(stats);
5776 free(listp);
5777 return NULL;
5780 free(listp);
5781 return stats;
5783 #endif
5785 #if (DBVER >= 46)
5786 static PyObject*
5787 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5789 int err;
5790 int flags=0;
5791 static char* kwnames[] = { "flags", NULL };
5793 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5794 kwnames, &flags))
5796 return NULL;
5798 CHECK_ENV_NOT_CLOSED(self);
5799 MYDB_BEGIN_ALLOW_THREADS;
5800 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5801 MYDB_END_ALLOW_THREADS;
5802 RETURN_IF_ERR();
5803 RETURN_NONE();
5806 static PyObject*
5807 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5809 int err;
5810 int flags=0;
5811 DB_REPMGR_STAT *statp;
5812 PyObject *stats;
5813 static char* kwnames[] = { "flags", NULL };
5815 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5816 kwnames, &flags))
5818 return NULL;
5820 CHECK_ENV_NOT_CLOSED(self);
5821 MYDB_BEGIN_ALLOW_THREADS;
5822 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5823 MYDB_END_ALLOW_THREADS;
5824 RETURN_IF_ERR();
5826 stats=PyDict_New();
5827 if (stats == NULL) {
5828 free(statp);
5829 return NULL;
5832 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5834 MAKE_ENTRY(perm_failed);
5835 MAKE_ENTRY(msgs_queued);
5836 MAKE_ENTRY(msgs_dropped);
5837 MAKE_ENTRY(connection_drop);
5838 MAKE_ENTRY(connect_fail);
5840 #undef MAKE_ENTRY
5842 free(statp);
5843 return stats;
5845 #endif
5848 /* --------------------------------------------------------------------- */
5849 /* DBTxn methods */
5852 static void _close_transaction_cursors(DBTxnObject* txn)
5854 PyObject *dummy;
5856 while(txn->children_cursors) {
5857 PyErr_Warn(PyExc_RuntimeWarning,
5858 "Must close cursors before resolving a transaction.");
5859 dummy=DBC_close_internal(txn->children_cursors);
5860 Py_XDECREF(dummy);
5864 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5866 DBObject *db;
5867 #if (DBVER >= 43)
5868 DBSequenceObject *dbs;
5869 #endif
5871 while (txn->children_dbs) {
5872 db=txn->children_dbs;
5873 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5874 if (txn->parent_txn) {
5875 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5876 db->txn=txn->parent_txn;
5877 } else {
5878 /* The db is already linked to its environment,
5879 ** so nothing to do.
5881 db->txn=NULL;
5885 #if (DBVER >= 43)
5886 while (txn->children_sequences) {
5887 dbs=txn->children_sequences;
5888 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5889 if (txn->parent_txn) {
5890 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5891 dbs->txn=txn->parent_txn;
5892 } else {
5893 /* The sequence is already linked to its
5894 ** parent db. Nothing to do.
5896 dbs->txn=NULL;
5899 #endif
5903 static PyObject*
5904 DBTxn_commit(DBTxnObject* self, PyObject* args)
5906 int flags=0, err;
5907 DB_TXN *txn;
5909 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5910 return NULL;
5912 _close_transaction_cursors(self);
5914 if (!self->txn) {
5915 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5916 "after txn_commit, txn_abort "
5917 "or txn_discard");
5918 if (t) {
5919 PyErr_SetObject(DBError, t);
5920 Py_DECREF(t);
5922 return NULL;
5924 self->flag_prepare=0;
5925 txn = self->txn;
5926 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
5928 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5930 MYDB_BEGIN_ALLOW_THREADS;
5931 err = txn->commit(txn, flags);
5932 MYDB_END_ALLOW_THREADS;
5934 _promote_transaction_dbs_and_sequences(self);
5936 RETURN_IF_ERR();
5937 RETURN_NONE();
5940 static PyObject*
5941 DBTxn_prepare(DBTxnObject* self, PyObject* args)
5943 int err;
5944 char* gid=NULL;
5945 int gid_size=0;
5947 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5948 return NULL;
5950 if (gid_size != DB_XIDDATASIZE) {
5951 PyErr_SetString(PyExc_TypeError,
5952 "gid must be DB_XIDDATASIZE bytes long");
5953 return NULL;
5956 if (!self->txn) {
5957 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
5958 "after txn_commit, txn_abort "
5959 "or txn_discard");
5960 if (t) {
5961 PyErr_SetObject(DBError, t);
5962 Py_DECREF(t);
5964 return NULL;
5966 self->flag_prepare=1; /* Prepare state */
5967 MYDB_BEGIN_ALLOW_THREADS;
5968 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5969 MYDB_END_ALLOW_THREADS;
5970 RETURN_IF_ERR();
5971 RETURN_NONE();
5975 static PyObject*
5976 DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
5978 PyObject *dummy;
5979 int err=0;
5980 DB_TXN *txn;
5982 if (!self->txn) {
5983 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5984 "after txn_commit, txn_abort "
5985 "or txn_discard");
5986 if (t) {
5987 PyErr_SetObject(DBError, t);
5988 Py_DECREF(t);
5990 return NULL;
5992 txn = self->txn;
5993 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
5995 _close_transaction_cursors(self);
5996 #if (DBVER >= 43)
5997 while (self->children_sequences) {
5998 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5999 Py_XDECREF(dummy);
6001 #endif
6002 while (self->children_dbs) {
6003 dummy=DB_close_internal(self->children_dbs, 0, 0);
6004 Py_XDECREF(dummy);
6007 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6009 MYDB_BEGIN_ALLOW_THREADS;
6010 if (discard) {
6011 assert(!self->flag_prepare);
6012 err = txn->discard(txn,0);
6013 } else {
6015 ** If the transaction is in the "prepare" or "recover" state,
6016 ** we better do not implicitly abort it.
6018 if (!self->flag_prepare) {
6019 err = txn->abort(txn);
6022 MYDB_END_ALLOW_THREADS;
6023 RETURN_IF_ERR();
6024 RETURN_NONE();
6027 static PyObject*
6028 DBTxn_abort(DBTxnObject* self)
6030 self->flag_prepare=0;
6031 _close_transaction_cursors(self);
6033 return DBTxn_abort_discard_internal(self,0);
6036 static PyObject*
6037 DBTxn_discard(DBTxnObject* self)
6039 self->flag_prepare=0;
6040 _close_transaction_cursors(self);
6042 return DBTxn_abort_discard_internal(self,1);
6046 static PyObject*
6047 DBTxn_id(DBTxnObject* self)
6049 int id;
6051 if (!self->txn) {
6052 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
6053 "after txn_commit, txn_abort "
6054 "or txn_discard");
6055 if (t) {
6056 PyErr_SetObject(DBError, t);
6057 Py_DECREF(t);
6059 return NULL;
6061 MYDB_BEGIN_ALLOW_THREADS;
6062 id = self->txn->id(self->txn);
6063 MYDB_END_ALLOW_THREADS;
6064 return NUMBER_FromLong(id);
6067 #if (DBVER >= 43)
6068 /* --------------------------------------------------------------------- */
6069 /* DBSequence methods */
6072 static PyObject*
6073 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
6075 int err=0;
6077 if (self->sequence!=NULL) {
6078 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
6079 if (self->txn) {
6080 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
6081 self->txn=NULL;
6085 ** "do_not_close" is used to dispose all related objects in the
6086 ** tree, without actually releasing the "root" object.
6087 ** This is done, for example, because function calls like
6088 ** "DBSequence.remove()" implicitly close the underlying handle. So
6089 ** the handle doesn't need to be closed, but related objects
6090 ** must be cleaned up.
6092 if (!do_not_close) {
6093 MYDB_BEGIN_ALLOW_THREADS
6094 err = self->sequence->close(self->sequence, flags);
6095 MYDB_END_ALLOW_THREADS
6097 self->sequence = NULL;
6099 RETURN_IF_ERR();
6102 RETURN_NONE();
6105 static PyObject*
6106 DBSequence_close(DBSequenceObject* self, PyObject* args)
6108 int flags=0;
6109 if (!PyArg_ParseTuple(args,"|i:close", &flags))
6110 return NULL;
6112 return DBSequence_close_internal(self,flags,0);
6115 static PyObject*
6116 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6118 int err, flags = 0;
6119 int delta = 1;
6120 db_seq_t value;
6121 PyObject *txnobj = NULL;
6122 DB_TXN *txn = NULL;
6123 static char* kwnames[] = {"delta", "txn", "flags", NULL };
6124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
6125 return NULL;
6126 CHECK_SEQUENCE_NOT_CLOSED(self)
6128 if (!checkTxnObj(txnobj, &txn))
6129 return NULL;
6131 MYDB_BEGIN_ALLOW_THREADS
6132 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
6133 MYDB_END_ALLOW_THREADS
6135 RETURN_IF_ERR();
6136 return PyLong_FromLongLong(value);
6139 static PyObject*
6140 DBSequence_get_dbp(DBSequenceObject* self)
6142 CHECK_SEQUENCE_NOT_CLOSED(self)
6143 Py_INCREF(self->mydb);
6144 return (PyObject* )self->mydb;
6147 static PyObject*
6148 DBSequence_get_key(DBSequenceObject* self)
6150 int err;
6151 DBT key;
6152 PyObject *retval = NULL;
6154 key.flags = DB_DBT_MALLOC;
6155 CHECK_SEQUENCE_NOT_CLOSED(self)
6156 MYDB_BEGIN_ALLOW_THREADS
6157 err = self->sequence->get_key(self->sequence, &key);
6158 MYDB_END_ALLOW_THREADS
6160 if (!err)
6161 retval = Build_PyString(key.data, key.size);
6163 FREE_DBT(key);
6164 RETURN_IF_ERR();
6166 return retval;
6169 static PyObject*
6170 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
6172 int err;
6173 PY_LONG_LONG value;
6174 db_seq_t value2;
6175 if (!PyArg_ParseTuple(args,"L:init_value", &value))
6176 return NULL;
6177 CHECK_SEQUENCE_NOT_CLOSED(self)
6179 value2=value; /* If truncation, compiler should show a warning */
6180 MYDB_BEGIN_ALLOW_THREADS
6181 err = self->sequence->initial_value(self->sequence, value2);
6182 MYDB_END_ALLOW_THREADS
6184 RETURN_IF_ERR();
6186 RETURN_NONE();
6189 static PyObject*
6190 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6192 int err, flags = 0;
6193 PyObject* keyobj;
6194 PyObject *txnobj = NULL;
6195 DB_TXN *txn = NULL;
6196 DBT key;
6198 static char* kwnames[] = {"key", "txn", "flags", NULL };
6199 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
6200 return NULL;
6202 if (!checkTxnObj(txnobj, &txn))
6203 return NULL;
6205 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
6206 return NULL;
6208 MYDB_BEGIN_ALLOW_THREADS
6209 err = self->sequence->open(self->sequence, txn, &key, flags);
6210 MYDB_END_ALLOW_THREADS
6212 FREE_DBT(key);
6213 RETURN_IF_ERR();
6215 if (txn) {
6216 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
6217 self->txn=(DBTxnObject *)txnobj;
6220 RETURN_NONE();
6223 static PyObject*
6224 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6226 PyObject *dummy;
6227 int err, flags = 0;
6228 PyObject *txnobj = NULL;
6229 DB_TXN *txn = NULL;
6231 static char* kwnames[] = {"txn", "flags", NULL };
6232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
6233 return NULL;
6235 if (!checkTxnObj(txnobj, &txn))
6236 return NULL;
6238 CHECK_SEQUENCE_NOT_CLOSED(self)
6240 MYDB_BEGIN_ALLOW_THREADS
6241 err = self->sequence->remove(self->sequence, txn, flags);
6242 MYDB_END_ALLOW_THREADS
6244 dummy=DBSequence_close_internal(self,flags,1);
6245 Py_XDECREF(dummy);
6247 RETURN_IF_ERR();
6248 RETURN_NONE();
6251 static PyObject*
6252 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
6254 int err, size;
6255 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
6256 return NULL;
6257 CHECK_SEQUENCE_NOT_CLOSED(self)
6259 MYDB_BEGIN_ALLOW_THREADS
6260 err = self->sequence->set_cachesize(self->sequence, size);
6261 MYDB_END_ALLOW_THREADS
6263 RETURN_IF_ERR();
6264 RETURN_NONE();
6267 static PyObject*
6268 DBSequence_get_cachesize(DBSequenceObject* self)
6270 int err, size;
6272 CHECK_SEQUENCE_NOT_CLOSED(self)
6274 MYDB_BEGIN_ALLOW_THREADS
6275 err = self->sequence->get_cachesize(self->sequence, &size);
6276 MYDB_END_ALLOW_THREADS
6278 RETURN_IF_ERR();
6279 return NUMBER_FromLong(size);
6282 static PyObject*
6283 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
6285 int err, flags = 0;
6286 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
6287 return NULL;
6288 CHECK_SEQUENCE_NOT_CLOSED(self)
6290 MYDB_BEGIN_ALLOW_THREADS
6291 err = self->sequence->set_flags(self->sequence, flags);
6292 MYDB_END_ALLOW_THREADS
6294 RETURN_IF_ERR();
6295 RETURN_NONE();
6298 static PyObject*
6299 DBSequence_get_flags(DBSequenceObject* self)
6301 unsigned int flags;
6302 int err;
6304 CHECK_SEQUENCE_NOT_CLOSED(self)
6306 MYDB_BEGIN_ALLOW_THREADS
6307 err = self->sequence->get_flags(self->sequence, &flags);
6308 MYDB_END_ALLOW_THREADS
6310 RETURN_IF_ERR();
6311 return NUMBER_FromLong((int)flags);
6314 static PyObject*
6315 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
6317 int err;
6318 PY_LONG_LONG min, max;
6319 db_seq_t min2, max2;
6320 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
6321 return NULL;
6322 CHECK_SEQUENCE_NOT_CLOSED(self)
6324 min2=min; /* If truncation, compiler should show a warning */
6325 max2=max;
6326 MYDB_BEGIN_ALLOW_THREADS
6327 err = self->sequence->set_range(self->sequence, min2, max2);
6328 MYDB_END_ALLOW_THREADS
6330 RETURN_IF_ERR();
6331 RETURN_NONE();
6334 static PyObject*
6335 DBSequence_get_range(DBSequenceObject* self)
6337 int err;
6338 PY_LONG_LONG min, max;
6339 db_seq_t min2, max2;
6341 CHECK_SEQUENCE_NOT_CLOSED(self)
6343 MYDB_BEGIN_ALLOW_THREADS
6344 err = self->sequence->get_range(self->sequence, &min2, &max2);
6345 MYDB_END_ALLOW_THREADS
6347 RETURN_IF_ERR();
6348 min=min2; /* If truncation, compiler should show a warning */
6349 max=max2;
6350 return Py_BuildValue("(LL)", min, max);
6353 static PyObject*
6354 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6356 int err, flags = 0;
6357 DB_SEQUENCE_STAT* sp = NULL;
6358 PyObject* dict_stat;
6359 static char* kwnames[] = {"flags", NULL };
6360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6361 return NULL;
6362 CHECK_SEQUENCE_NOT_CLOSED(self);
6364 MYDB_BEGIN_ALLOW_THREADS;
6365 err = self->sequence->stat(self->sequence, &sp, flags);
6366 MYDB_END_ALLOW_THREADS;
6367 RETURN_IF_ERR();
6369 if ((dict_stat = PyDict_New()) == NULL) {
6370 free(sp);
6371 return NULL;
6375 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6376 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6378 MAKE_INT_ENTRY(wait);
6379 MAKE_INT_ENTRY(nowait);
6380 MAKE_LONG_LONG_ENTRY(current);
6381 MAKE_LONG_LONG_ENTRY(value);
6382 MAKE_LONG_LONG_ENTRY(last_value);
6383 MAKE_LONG_LONG_ENTRY(min);
6384 MAKE_LONG_LONG_ENTRY(max);
6385 MAKE_INT_ENTRY(cache_size);
6386 MAKE_INT_ENTRY(flags);
6388 #undef MAKE_INT_ENTRY
6389 #undef MAKE_LONG_LONG_ENTRY
6391 free(sp);
6392 return dict_stat;
6394 #endif
6397 /* --------------------------------------------------------------------- */
6398 /* Method definition tables and type objects */
6400 static PyMethodDef DB_methods[] = {
6401 {"append", (PyCFunction)DB_append, METH_VARARGS|METH_KEYWORDS},
6402 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
6403 {"close", (PyCFunction)DB_close, METH_VARARGS},
6404 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6405 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
6406 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6407 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
6408 {"fd", (PyCFunction)DB_fd, METH_NOARGS},
6409 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
6410 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
6411 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
6412 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_NOARGS},
6413 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6414 {"get_type", (PyCFunction)DB_get_type, METH_NOARGS},
6415 {"join", (PyCFunction)DB_join, METH_VARARGS},
6416 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6417 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS|METH_KEYWORDS},
6418 {"items", (PyCFunction)DB_items, METH_VARARGS},
6419 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6420 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6421 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6422 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6423 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6424 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
6425 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_O},
6426 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
6427 #if (DBVER >= 41)
6428 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6429 #endif
6430 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6431 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6432 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6433 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6434 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6435 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6436 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6437 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6438 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
6439 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize, METH_VARARGS},
6440 {"set_private", (PyCFunction)DB_set_private, METH_O},
6441 {"get_private", (PyCFunction)DB_get_private, METH_NOARGS},
6442 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
6443 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6444 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6445 {"type", (PyCFunction)DB_get_type, METH_NOARGS},
6446 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6447 {"values", (PyCFunction)DB_values, METH_VARARGS},
6448 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6449 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6450 {NULL, NULL} /* sentinel */
6454 static PyMappingMethods DB_mapping = {
6455 DB_length, /*mp_length*/
6456 (binaryfunc)DB_subscript, /*mp_subscript*/
6457 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6461 static PyMethodDef DBCursor_methods[] = {
6462 {"close", (PyCFunction)DBC_close, METH_NOARGS},
6463 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6464 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6465 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6466 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6467 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6468 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
6469 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
6470 {"get_recno", (PyCFunction)DBC_get_recno, METH_NOARGS},
6471 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6472 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6473 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6474 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6475 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6476 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6477 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
6478 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_NOARGS},
6479 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
6480 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6481 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6482 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6483 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6484 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6485 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6486 {NULL, NULL} /* sentinel */
6490 static PyMethodDef DBEnv_methods[] = {
6491 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6492 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6493 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
6494 #if (DBVER >= 41)
6495 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6496 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6497 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6498 #endif
6499 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6500 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
6501 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6502 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
6503 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
6504 #if (DBVER >= 47)
6505 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6506 #endif
6507 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6508 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6509 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
6510 #if (DBVER >= 42)
6511 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_NOARGS},
6512 #endif
6513 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
6514 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
6515 #if (DBVER < 45)
6516 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
6517 #endif
6518 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6519 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6520 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
6521 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6522 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6523 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6524 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6525 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6526 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
6527 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
6528 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6529 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6530 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_NOARGS},
6531 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6532 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6533 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6534 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
6535 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_NOARGS},
6536 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6537 #if (DBVER >= 44)
6538 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6539 #endif
6540 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
6541 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_NOARGS},
6542 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6543 METH_VARARGS||METH_KEYWORDS},
6544 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6545 #if (DBVER >= 42)
6546 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6547 #endif
6548 {"set_private", (PyCFunction)DBEnv_set_private, METH_O},
6549 {"get_private", (PyCFunction)DBEnv_get_private, METH_NOARGS},
6550 {"rep_start", (PyCFunction)DBEnv_rep_start,
6551 METH_VARARGS|METH_KEYWORDS},
6552 {"rep_set_transport", (PyCFunction)DBEnv_rep_set_transport, METH_VARARGS},
6553 {"rep_process_message", (PyCFunction)DBEnv_rep_process_message,
6554 METH_VARARGS},
6555 #if (DBVER >= 46)
6556 {"rep_elect", (PyCFunction)DBEnv_rep_elect, METH_VARARGS},
6557 #endif
6558 #if (DBVER >= 44)
6559 {"rep_set_config", (PyCFunction)DBEnv_rep_set_config, METH_VARARGS},
6560 {"rep_get_config", (PyCFunction)DBEnv_rep_get_config, METH_VARARGS},
6561 {"rep_sync", (PyCFunction)DBEnv_rep_sync, METH_NOARGS},
6562 #endif
6563 #if (DBVER >= 45)
6564 {"rep_set_limit", (PyCFunction)DBEnv_rep_set_limit, METH_VARARGS},
6565 {"rep_get_limit", (PyCFunction)DBEnv_rep_get_limit, METH_NOARGS},
6566 #endif
6567 #if (DBVER >= 47)
6568 {"rep_set_request", (PyCFunction)DBEnv_rep_set_request, METH_VARARGS},
6569 {"rep_get_request", (PyCFunction)DBEnv_rep_get_request, METH_NOARGS},
6570 #endif
6571 #if (DBVER >= 45)
6572 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_O},
6573 #endif
6574 #if (DBVER >= 45)
6575 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6576 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_NOARGS},
6577 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6578 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_NOARGS},
6579 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6580 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6581 #endif
6582 #if (DBVER >= 45)
6583 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6584 METH_VARARGS|METH_KEYWORDS},
6585 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6586 METH_VARARGS|METH_KEYWORDS},
6587 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6588 METH_VARARGS|METH_KEYWORDS},
6589 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6590 METH_VARARGS},
6591 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6592 METH_NOARGS},
6593 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6594 METH_NOARGS},
6595 #endif
6596 #if (DBVER >= 46)
6597 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6598 METH_VARARGS|METH_KEYWORDS},
6599 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6600 METH_VARARGS|METH_KEYWORDS},
6601 #endif
6602 {NULL, NULL} /* sentinel */
6606 static PyMethodDef DBTxn_methods[] = {
6607 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6608 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
6609 {"discard", (PyCFunction)DBTxn_discard, METH_NOARGS},
6610 {"abort", (PyCFunction)DBTxn_abort, METH_NOARGS},
6611 {"id", (PyCFunction)DBTxn_id, METH_NOARGS},
6612 {NULL, NULL} /* sentinel */
6616 #if (DBVER >= 43)
6617 static PyMethodDef DBSequence_methods[] = {
6618 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6619 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6620 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_NOARGS},
6621 {"get_key", (PyCFunction)DBSequence_get_key, METH_NOARGS},
6622 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6623 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6624 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6625 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6626 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_NOARGS},
6627 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6628 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_NOARGS},
6629 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6630 {"get_range", (PyCFunction)DBSequence_get_range, METH_NOARGS},
6631 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6632 {NULL, NULL} /* sentinel */
6634 #endif
6637 static PyObject*
6638 DBEnv_db_home_get(DBEnvObject* self)
6640 const char *home = NULL;
6642 CHECK_ENV_NOT_CLOSED(self);
6644 #if (DBVER >= 42)
6645 self->db_env->get_home(self->db_env, &home);
6646 #else
6647 home=self->db_env->db_home;
6648 #endif
6650 if (home == NULL) {
6651 RETURN_NONE();
6653 return PyBytes_FromString(home);
6656 static PyGetSetDef DBEnv_getsets[] = {
6657 {"db_home", (getter)DBEnv_db_home_get, NULL,},
6658 {NULL}
6662 statichere PyTypeObject DB_Type = {
6663 #if (PY_VERSION_HEX < 0x03000000)
6664 PyObject_HEAD_INIT(NULL)
6665 0, /*ob_size*/
6666 #else
6667 PyVarObject_HEAD_INIT(NULL, 0)
6668 #endif
6669 "DB", /*tp_name*/
6670 sizeof(DBObject), /*tp_basicsize*/
6671 0, /*tp_itemsize*/
6672 /* methods */
6673 (destructor)DB_dealloc, /*tp_dealloc*/
6674 0, /*tp_print*/
6675 0, /*tp_getattr*/
6676 0, /*tp_setattr*/
6677 0, /*tp_compare*/
6678 0, /*tp_repr*/
6679 0, /*tp_as_number*/
6680 0, /*tp_as_sequence*/
6681 &DB_mapping,/*tp_as_mapping*/
6682 0, /*tp_hash*/
6683 0, /* tp_call */
6684 0, /* tp_str */
6685 0, /* tp_getattro */
6686 0, /* tp_setattro */
6687 0, /* tp_as_buffer */
6688 #if (PY_VERSION_HEX < 0x03000000)
6689 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6690 #else
6691 Py_TPFLAGS_DEFAULT, /* tp_flags */
6692 #endif
6693 0, /* tp_doc */
6694 0, /* tp_traverse */
6695 0, /* tp_clear */
6696 0, /* tp_richcompare */
6697 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
6698 0, /*tp_iter*/
6699 0, /*tp_iternext*/
6700 DB_methods, /*tp_methods*/
6701 0, /*tp_members*/
6705 statichere PyTypeObject DBCursor_Type = {
6706 #if (PY_VERSION_HEX < 0x03000000)
6707 PyObject_HEAD_INIT(NULL)
6708 0, /*ob_size*/
6709 #else
6710 PyVarObject_HEAD_INIT(NULL, 0)
6711 #endif
6712 "DBCursor", /*tp_name*/
6713 sizeof(DBCursorObject), /*tp_basicsize*/
6714 0, /*tp_itemsize*/
6715 /* methods */
6716 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6717 0, /*tp_print*/
6718 0, /*tp_getattr*/
6719 0, /*tp_setattr*/
6720 0, /*tp_compare*/
6721 0, /*tp_repr*/
6722 0, /*tp_as_number*/
6723 0, /*tp_as_sequence*/
6724 0, /*tp_as_mapping*/
6725 0, /*tp_hash*/
6726 0, /*tp_call*/
6727 0, /*tp_str*/
6728 0, /*tp_getattro*/
6729 0, /*tp_setattro*/
6730 0, /*tp_as_buffer*/
6731 #if (PY_VERSION_HEX < 0x03000000)
6732 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6733 #else
6734 Py_TPFLAGS_DEFAULT, /* tp_flags */
6735 #endif
6736 0, /* tp_doc */
6737 0, /* tp_traverse */
6738 0, /* tp_clear */
6739 0, /* tp_richcompare */
6740 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6741 0, /*tp_iter*/
6742 0, /*tp_iternext*/
6743 DBCursor_methods, /*tp_methods*/
6744 0, /*tp_members*/
6748 statichere PyTypeObject DBEnv_Type = {
6749 #if (PY_VERSION_HEX < 0x03000000)
6750 PyObject_HEAD_INIT(NULL)
6751 0, /*ob_size*/
6752 #else
6753 PyVarObject_HEAD_INIT(NULL, 0)
6754 #endif
6755 "DBEnv", /*tp_name*/
6756 sizeof(DBEnvObject), /*tp_basicsize*/
6757 0, /*tp_itemsize*/
6758 /* methods */
6759 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6760 0, /*tp_print*/
6761 0, /*tp_getattr*/
6762 0, /*tp_setattr*/
6763 0, /*tp_compare*/
6764 0, /*tp_repr*/
6765 0, /*tp_as_number*/
6766 0, /*tp_as_sequence*/
6767 0, /*tp_as_mapping*/
6768 0, /*tp_hash*/
6769 0, /* tp_call */
6770 0, /* tp_str */
6771 0, /* tp_getattro */
6772 0, /* tp_setattro */
6773 0, /* tp_as_buffer */
6774 #if (PY_VERSION_HEX < 0x03000000)
6775 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6776 #else
6777 Py_TPFLAGS_DEFAULT, /* tp_flags */
6778 #endif
6779 0, /* tp_doc */
6780 0, /* tp_traverse */
6781 0, /* tp_clear */
6782 0, /* tp_richcompare */
6783 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6784 0, /* tp_iter */
6785 0, /* tp_iternext */
6786 DBEnv_methods, /* tp_methods */
6787 0, /* tp_members */
6788 DBEnv_getsets, /* tp_getsets */
6791 statichere PyTypeObject DBTxn_Type = {
6792 #if (PY_VERSION_HEX < 0x03000000)
6793 PyObject_HEAD_INIT(NULL)
6794 0, /*ob_size*/
6795 #else
6796 PyVarObject_HEAD_INIT(NULL, 0)
6797 #endif
6798 "DBTxn", /*tp_name*/
6799 sizeof(DBTxnObject), /*tp_basicsize*/
6800 0, /*tp_itemsize*/
6801 /* methods */
6802 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6803 0, /*tp_print*/
6804 0, /*tp_getattr*/
6805 0, /*tp_setattr*/
6806 0, /*tp_compare*/
6807 0, /*tp_repr*/
6808 0, /*tp_as_number*/
6809 0, /*tp_as_sequence*/
6810 0, /*tp_as_mapping*/
6811 0, /*tp_hash*/
6812 0, /* tp_call */
6813 0, /* tp_str */
6814 0, /* tp_getattro */
6815 0, /* tp_setattro */
6816 0, /* tp_as_buffer */
6817 #if (PY_VERSION_HEX < 0x03000000)
6818 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6819 #else
6820 Py_TPFLAGS_DEFAULT, /* tp_flags */
6821 #endif
6822 0, /* tp_doc */
6823 0, /* tp_traverse */
6824 0, /* tp_clear */
6825 0, /* tp_richcompare */
6826 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6827 0, /*tp_iter*/
6828 0, /*tp_iternext*/
6829 DBTxn_methods, /*tp_methods*/
6830 0, /*tp_members*/
6834 statichere PyTypeObject DBLock_Type = {
6835 #if (PY_VERSION_HEX < 0x03000000)
6836 PyObject_HEAD_INIT(NULL)
6837 0, /*ob_size*/
6838 #else
6839 PyVarObject_HEAD_INIT(NULL, 0)
6840 #endif
6841 "DBLock", /*tp_name*/
6842 sizeof(DBLockObject), /*tp_basicsize*/
6843 0, /*tp_itemsize*/
6844 /* methods */
6845 (destructor)DBLock_dealloc, /*tp_dealloc*/
6846 0, /*tp_print*/
6847 0, /*tp_getattr*/
6848 0, /*tp_setattr*/
6849 0, /*tp_compare*/
6850 0, /*tp_repr*/
6851 0, /*tp_as_number*/
6852 0, /*tp_as_sequence*/
6853 0, /*tp_as_mapping*/
6854 0, /*tp_hash*/
6855 0, /* tp_call */
6856 0, /* tp_str */
6857 0, /* tp_getattro */
6858 0, /* tp_setattro */
6859 0, /* tp_as_buffer */
6860 #if (PY_VERSION_HEX < 0x03000000)
6861 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6862 #else
6863 Py_TPFLAGS_DEFAULT, /* tp_flags */
6864 #endif
6865 0, /* tp_doc */
6866 0, /* tp_traverse */
6867 0, /* tp_clear */
6868 0, /* tp_richcompare */
6869 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6872 #if (DBVER >= 43)
6873 statichere PyTypeObject DBSequence_Type = {
6874 #if (PY_VERSION_HEX < 0x03000000)
6875 PyObject_HEAD_INIT(NULL)
6876 0, /*ob_size*/
6877 #else
6878 PyVarObject_HEAD_INIT(NULL, 0)
6879 #endif
6880 "DBSequence", /*tp_name*/
6881 sizeof(DBSequenceObject), /*tp_basicsize*/
6882 0, /*tp_itemsize*/
6883 /* methods */
6884 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6885 0, /*tp_print*/
6886 0, /*tp_getattr*/
6887 0, /*tp_setattr*/
6888 0, /*tp_compare*/
6889 0, /*tp_repr*/
6890 0, /*tp_as_number*/
6891 0, /*tp_as_sequence*/
6892 0, /*tp_as_mapping*/
6893 0, /*tp_hash*/
6894 0, /* tp_call */
6895 0, /* tp_str */
6896 0, /* tp_getattro */
6897 0, /* tp_setattro */
6898 0, /* tp_as_buffer */
6899 #if (PY_VERSION_HEX < 0x03000000)
6900 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6901 #else
6902 Py_TPFLAGS_DEFAULT, /* tp_flags */
6903 #endif
6904 0, /* tp_doc */
6905 0, /* tp_traverse */
6906 0, /* tp_clear */
6907 0, /* tp_richcompare */
6908 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
6909 0, /*tp_iter*/
6910 0, /*tp_iternext*/
6911 DBSequence_methods, /*tp_methods*/
6912 0, /*tp_members*/
6914 #endif
6916 /* --------------------------------------------------------------------- */
6917 /* Module-level functions */
6919 static PyObject*
6920 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6922 PyObject* dbenvobj = NULL;
6923 int flags = 0;
6924 static char* kwnames[] = { "dbEnv", "flags", NULL};
6926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6927 &dbenvobj, &flags))
6928 return NULL;
6929 if (dbenvobj == Py_None)
6930 dbenvobj = NULL;
6931 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6932 makeTypeError("DBEnv", dbenvobj);
6933 return NULL;
6936 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6940 static PyObject*
6941 DBEnv_construct(PyObject* self, PyObject* args)
6943 int flags = 0;
6944 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6945 return (PyObject* )newDBEnvObject(flags);
6948 #if (DBVER >= 43)
6949 static PyObject*
6950 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6952 PyObject* dbobj;
6953 int flags = 0;
6954 static char* kwnames[] = { "db", "flags", NULL};
6956 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6957 return NULL;
6958 if (!DBObject_Check(dbobj)) {
6959 makeTypeError("DB", dbobj);
6960 return NULL;
6962 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6964 #endif
6966 static char bsddb_version_doc[] =
6967 "Returns a tuple of major, minor, and patch release numbers of the\n\
6968 underlying DB library.";
6970 static PyObject*
6971 bsddb_version(PyObject* self)
6973 int major, minor, patch;
6975 db_version(&major, &minor, &patch);
6976 return Py_BuildValue("(iii)", major, minor, patch);
6980 /* List of functions defined in the module */
6981 static PyMethodDef bsddb_methods[] = {
6982 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6983 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6984 #if (DBVER >= 43)
6985 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6986 #endif
6987 {"version", (PyCFunction)bsddb_version, METH_NOARGS, bsddb_version_doc},
6988 {NULL, NULL} /* sentinel */
6992 /* API structure */
6993 static BSDDB_api bsddb_api;
6996 /* --------------------------------------------------------------------- */
6997 /* Module initialization */
7000 /* Convenience routine to export an integer value.
7001 * Errors are silently ignored, for better or for worse...
7003 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
7005 #define MODULE_NAME_MAX_LEN 11
7006 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
7008 #if (PY_VERSION_HEX >= 0x03000000)
7009 static struct PyModuleDef bsddbmodule = {
7010 PyModuleDef_HEAD_INIT,
7011 _bsddbModuleName, /* Name of module */
7012 NULL, /* module documentation, may be NULL */
7013 -1, /* size of per-interpreter state of the module,
7014 or -1 if the module keeps state in global variables. */
7015 bsddb_methods,
7016 NULL, /* Reload */
7017 NULL, /* Traverse */
7018 NULL, /* Clear */
7019 NULL /* Free */
7021 #endif
7024 #if (PY_VERSION_HEX < 0x03000000)
7025 DL_EXPORT(void) init_bsddb(void)
7026 #else
7027 PyMODINIT_FUNC PyInit__bsddb(void) /* Note the two underscores */
7028 #endif
7030 PyObject* m;
7031 PyObject* d;
7032 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
7033 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
7034 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
7035 PyObject* py_api;
7037 /* Initialize object types */
7038 if ((PyType_Ready(&DB_Type) < 0)
7039 || (PyType_Ready(&DBCursor_Type) < 0)
7040 || (PyType_Ready(&DBEnv_Type) < 0)
7041 || (PyType_Ready(&DBTxn_Type) < 0)
7042 || (PyType_Ready(&DBLock_Type) < 0)
7043 #if (DBVER >= 43)
7044 || (PyType_Ready(&DBSequence_Type) < 0)
7045 #endif
7047 #if (PY_VERSION_HEX < 0x03000000)
7048 return;
7049 #else
7050 return NULL;
7051 #endif
7054 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
7055 /* Save the current interpreter, so callbacks can do the right thing. */
7056 _db_interpreterState = PyThreadState_GET()->interp;
7057 #endif
7059 /* Create the module and add the functions */
7060 #if (PY_VERSION_HEX < 0x03000000)
7061 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
7062 #else
7063 m=PyModule_Create(&bsddbmodule);
7064 #endif
7065 if (m == NULL) {
7066 #if (PY_VERSION_HEX < 0x03000000)
7067 return;
7068 #else
7069 return NULL;
7070 #endif
7073 /* Add some symbolic constants to the module */
7074 d = PyModule_GetDict(m);
7075 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
7076 PyDict_SetItemString(d, "cvsid", cvsid_s);
7077 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
7078 Py_DECREF(pybsddb_version_s);
7079 pybsddb_version_s = NULL;
7080 Py_DECREF(cvsid_s);
7081 cvsid_s = NULL;
7082 Py_DECREF(db_version_s);
7083 db_version_s = NULL;
7085 ADD_INT(d, DB_VERSION_MAJOR);
7086 ADD_INT(d, DB_VERSION_MINOR);
7087 ADD_INT(d, DB_VERSION_PATCH);
7089 ADD_INT(d, DB_MAX_PAGES);
7090 ADD_INT(d, DB_MAX_RECORDS);
7092 #if (DBVER >= 42)
7093 ADD_INT(d, DB_RPCCLIENT);
7094 #else
7095 ADD_INT(d, DB_CLIENT);
7096 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
7097 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
7098 #endif
7099 ADD_INT(d, DB_XA_CREATE);
7101 ADD_INT(d, DB_CREATE);
7102 ADD_INT(d, DB_NOMMAP);
7103 ADD_INT(d, DB_THREAD);
7104 #if (DBVER >= 45)
7105 ADD_INT(d, DB_MULTIVERSION);
7106 #endif
7108 ADD_INT(d, DB_FORCE);
7109 ADD_INT(d, DB_INIT_CDB);
7110 ADD_INT(d, DB_INIT_LOCK);
7111 ADD_INT(d, DB_INIT_LOG);
7112 ADD_INT(d, DB_INIT_MPOOL);
7113 ADD_INT(d, DB_INIT_TXN);
7114 ADD_INT(d, DB_JOINENV);
7116 ADD_INT(d, DB_XIDDATASIZE);
7118 ADD_INT(d, DB_RECOVER);
7119 ADD_INT(d, DB_RECOVER_FATAL);
7120 ADD_INT(d, DB_TXN_NOSYNC);
7121 ADD_INT(d, DB_USE_ENVIRON);
7122 ADD_INT(d, DB_USE_ENVIRON_ROOT);
7124 ADD_INT(d, DB_LOCKDOWN);
7125 ADD_INT(d, DB_PRIVATE);
7126 ADD_INT(d, DB_SYSTEM_MEM);
7128 ADD_INT(d, DB_TXN_SYNC);
7129 ADD_INT(d, DB_TXN_NOWAIT);
7131 ADD_INT(d, DB_EXCL);
7132 ADD_INT(d, DB_FCNTL_LOCKING);
7133 ADD_INT(d, DB_ODDFILESIZE);
7134 ADD_INT(d, DB_RDWRMASTER);
7135 ADD_INT(d, DB_RDONLY);
7136 ADD_INT(d, DB_TRUNCATE);
7137 ADD_INT(d, DB_EXTENT);
7138 ADD_INT(d, DB_CDB_ALLDB);
7139 ADD_INT(d, DB_VERIFY);
7140 ADD_INT(d, DB_UPGRADE);
7142 ADD_INT(d, DB_AGGRESSIVE);
7143 ADD_INT(d, DB_NOORDERCHK);
7144 ADD_INT(d, DB_ORDERCHKONLY);
7145 ADD_INT(d, DB_PR_PAGE);
7147 ADD_INT(d, DB_PR_RECOVERYTEST);
7148 ADD_INT(d, DB_SALVAGE);
7150 ADD_INT(d, DB_LOCK_NORUN);
7151 ADD_INT(d, DB_LOCK_DEFAULT);
7152 ADD_INT(d, DB_LOCK_OLDEST);
7153 ADD_INT(d, DB_LOCK_RANDOM);
7154 ADD_INT(d, DB_LOCK_YOUNGEST);
7155 ADD_INT(d, DB_LOCK_MAXLOCKS);
7156 ADD_INT(d, DB_LOCK_MINLOCKS);
7157 ADD_INT(d, DB_LOCK_MINWRITE);
7159 ADD_INT(d, DB_LOCK_EXPIRE);
7160 #if (DBVER >= 43)
7161 ADD_INT(d, DB_LOCK_MAXWRITE);
7162 #endif
7164 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
7166 ADD_INT(d, DB_LOCK_DUMP);
7167 ADD_INT(d, DB_LOCK_GET);
7168 ADD_INT(d, DB_LOCK_INHERIT);
7169 ADD_INT(d, DB_LOCK_PUT);
7170 ADD_INT(d, DB_LOCK_PUT_ALL);
7171 ADD_INT(d, DB_LOCK_PUT_OBJ);
7173 ADD_INT(d, DB_LOCK_NG);
7174 ADD_INT(d, DB_LOCK_READ);
7175 ADD_INT(d, DB_LOCK_WRITE);
7176 ADD_INT(d, DB_LOCK_NOWAIT);
7177 ADD_INT(d, DB_LOCK_WAIT);
7178 ADD_INT(d, DB_LOCK_IWRITE);
7179 ADD_INT(d, DB_LOCK_IREAD);
7180 ADD_INT(d, DB_LOCK_IWR);
7181 #if (DBVER < 44)
7182 ADD_INT(d, DB_LOCK_DIRTY);
7183 #else
7184 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
7185 #endif
7186 ADD_INT(d, DB_LOCK_WWRITE);
7188 ADD_INT(d, DB_LOCK_RECORD);
7189 ADD_INT(d, DB_LOCK_UPGRADE);
7190 ADD_INT(d, DB_LOCK_SWITCH);
7191 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
7193 ADD_INT(d, DB_LOCK_NOWAIT);
7194 ADD_INT(d, DB_LOCK_RECORD);
7195 ADD_INT(d, DB_LOCK_UPGRADE);
7197 ADD_INT(d, DB_LSTAT_ABORTED);
7198 #if (DBVER < 43)
7199 ADD_INT(d, DB_LSTAT_ERR);
7200 #endif
7201 ADD_INT(d, DB_LSTAT_FREE);
7202 ADD_INT(d, DB_LSTAT_HELD);
7204 ADD_INT(d, DB_LSTAT_PENDING);
7205 ADD_INT(d, DB_LSTAT_WAITING);
7207 ADD_INT(d, DB_ARCH_ABS);
7208 ADD_INT(d, DB_ARCH_DATA);
7209 ADD_INT(d, DB_ARCH_LOG);
7210 #if (DBVER >= 42)
7211 ADD_INT(d, DB_ARCH_REMOVE);
7212 #endif
7214 ADD_INT(d, DB_BTREE);
7215 ADD_INT(d, DB_HASH);
7216 ADD_INT(d, DB_RECNO);
7217 ADD_INT(d, DB_QUEUE);
7218 ADD_INT(d, DB_UNKNOWN);
7220 ADD_INT(d, DB_DUP);
7221 ADD_INT(d, DB_DUPSORT);
7222 ADD_INT(d, DB_RECNUM);
7223 ADD_INT(d, DB_RENUMBER);
7224 ADD_INT(d, DB_REVSPLITOFF);
7225 ADD_INT(d, DB_SNAPSHOT);
7227 ADD_INT(d, DB_JOIN_NOSORT);
7229 ADD_INT(d, DB_AFTER);
7230 ADD_INT(d, DB_APPEND);
7231 ADD_INT(d, DB_BEFORE);
7232 #if (DBVER < 45)
7233 ADD_INT(d, DB_CACHED_COUNTS);
7234 #endif
7236 #if (DBVER >= 41)
7237 _addIntToDict(d, "DB_CHECKPOINT", 0);
7238 #else
7239 ADD_INT(d, DB_CHECKPOINT);
7240 ADD_INT(d, DB_CURLSN);
7241 #endif
7242 #if (DBVER <= 41)
7243 ADD_INT(d, DB_COMMIT);
7244 #endif
7245 ADD_INT(d, DB_CONSUME);
7246 ADD_INT(d, DB_CONSUME_WAIT);
7247 ADD_INT(d, DB_CURRENT);
7248 ADD_INT(d, DB_FAST_STAT);
7249 ADD_INT(d, DB_FIRST);
7250 ADD_INT(d, DB_FLUSH);
7251 ADD_INT(d, DB_GET_BOTH);
7252 ADD_INT(d, DB_GET_RECNO);
7253 ADD_INT(d, DB_JOIN_ITEM);
7254 ADD_INT(d, DB_KEYFIRST);
7255 ADD_INT(d, DB_KEYLAST);
7256 ADD_INT(d, DB_LAST);
7257 ADD_INT(d, DB_NEXT);
7258 ADD_INT(d, DB_NEXT_DUP);
7259 ADD_INT(d, DB_NEXT_NODUP);
7260 ADD_INT(d, DB_NODUPDATA);
7261 ADD_INT(d, DB_NOOVERWRITE);
7262 ADD_INT(d, DB_NOSYNC);
7263 ADD_INT(d, DB_POSITION);
7264 ADD_INT(d, DB_PREV);
7265 ADD_INT(d, DB_PREV_NODUP);
7266 #if (DBVER < 45)
7267 ADD_INT(d, DB_RECORDCOUNT);
7268 #endif
7269 ADD_INT(d, DB_SET);
7270 ADD_INT(d, DB_SET_RANGE);
7271 ADD_INT(d, DB_SET_RECNO);
7272 ADD_INT(d, DB_WRITECURSOR);
7274 ADD_INT(d, DB_OPFLAGS_MASK);
7275 ADD_INT(d, DB_RMW);
7276 ADD_INT(d, DB_DIRTY_READ);
7277 ADD_INT(d, DB_MULTIPLE);
7278 ADD_INT(d, DB_MULTIPLE_KEY);
7280 #if (DBVER >= 44)
7281 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
7282 ADD_INT(d, DB_READ_COMMITTED);
7283 #endif
7285 ADD_INT(d, DB_DONOTINDEX);
7287 #if (DBVER >= 41)
7288 _addIntToDict(d, "DB_INCOMPLETE", 0);
7289 #else
7290 ADD_INT(d, DB_INCOMPLETE);
7291 #endif
7292 ADD_INT(d, DB_KEYEMPTY);
7293 ADD_INT(d, DB_KEYEXIST);
7294 ADD_INT(d, DB_LOCK_DEADLOCK);
7295 ADD_INT(d, DB_LOCK_NOTGRANTED);
7296 ADD_INT(d, DB_NOSERVER);
7297 ADD_INT(d, DB_NOSERVER_HOME);
7298 ADD_INT(d, DB_NOSERVER_ID);
7299 ADD_INT(d, DB_NOTFOUND);
7300 ADD_INT(d, DB_OLD_VERSION);
7301 ADD_INT(d, DB_RUNRECOVERY);
7302 ADD_INT(d, DB_VERIFY_BAD);
7303 ADD_INT(d, DB_PAGE_NOTFOUND);
7304 ADD_INT(d, DB_SECONDARY_BAD);
7305 ADD_INT(d, DB_STAT_CLEAR);
7306 ADD_INT(d, DB_REGION_INIT);
7307 ADD_INT(d, DB_NOLOCKING);
7308 ADD_INT(d, DB_YIELDCPU);
7309 ADD_INT(d, DB_PANIC_ENVIRONMENT);
7310 ADD_INT(d, DB_NOPANIC);
7312 #if (DBVER >= 41)
7313 ADD_INT(d, DB_OVERWRITE);
7314 #endif
7316 #ifdef DB_REGISTER
7317 ADD_INT(d, DB_REGISTER);
7318 #endif
7320 #if (DBVER >= 42)
7321 ADD_INT(d, DB_TIME_NOTGRANTED);
7322 ADD_INT(d, DB_TXN_NOT_DURABLE);
7323 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
7324 ADD_INT(d, DB_DIRECT_DB);
7325 ADD_INT(d, DB_INIT_REP);
7326 ADD_INT(d, DB_ENCRYPT);
7327 ADD_INT(d, DB_CHKSUM);
7328 #endif
7330 #if (DBVER >= 42) && (DBVER < 47)
7331 ADD_INT(d, DB_LOG_AUTOREMOVE);
7332 ADD_INT(d, DB_DIRECT_LOG);
7333 #endif
7335 #if (DBVER >= 47)
7336 ADD_INT(d, DB_LOG_DIRECT);
7337 ADD_INT(d, DB_LOG_DSYNC);
7338 ADD_INT(d, DB_LOG_IN_MEMORY);
7339 ADD_INT(d, DB_LOG_AUTO_REMOVE);
7340 ADD_INT(d, DB_LOG_ZERO);
7341 #endif
7343 #if (DBVER >= 44)
7344 ADD_INT(d, DB_DSYNC_DB);
7345 #endif
7347 #if (DBVER >= 45)
7348 ADD_INT(d, DB_TXN_SNAPSHOT);
7349 #endif
7351 ADD_INT(d, DB_VERB_DEADLOCK);
7352 #if (DBVER >= 46)
7353 ADD_INT(d, DB_VERB_FILEOPS);
7354 ADD_INT(d, DB_VERB_FILEOPS_ALL);
7355 #endif
7356 ADD_INT(d, DB_VERB_RECOVERY);
7357 #if (DBVER >= 44)
7358 ADD_INT(d, DB_VERB_REGISTER);
7359 #endif
7360 ADD_INT(d, DB_VERB_REPLICATION);
7361 ADD_INT(d, DB_VERB_WAITSFOR);
7363 #if (DBVER >= 45)
7364 ADD_INT(d, DB_EVENT_PANIC);
7365 ADD_INT(d, DB_EVENT_REP_CLIENT);
7366 #if (DBVER >= 46)
7367 ADD_INT(d, DB_EVENT_REP_ELECTED);
7368 #endif
7369 ADD_INT(d, DB_EVENT_REP_MASTER);
7370 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
7371 #if (DBVER >= 46)
7372 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
7373 #endif
7374 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
7375 ADD_INT(d, DB_EVENT_WRITE_FAILED);
7376 #endif
7378 ADD_INT(d, DB_REP_DUPMASTER);
7379 ADD_INT(d, DB_REP_HOLDELECTION);
7380 #if (DBVER >= 44)
7381 ADD_INT(d, DB_REP_IGNORE);
7382 ADD_INT(d, DB_REP_JOIN_FAILURE);
7383 #endif
7384 #if (DBVER >= 42)
7385 ADD_INT(d, DB_REP_ISPERM);
7386 ADD_INT(d, DB_REP_NOTPERM);
7387 #endif
7388 ADD_INT(d, DB_REP_NEWSITE);
7390 ADD_INT(d, DB_REP_MASTER);
7391 ADD_INT(d, DB_REP_CLIENT);
7392 #if (DBVER >= 45)
7393 ADD_INT(d, DB_REP_ELECTION);
7395 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7396 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7397 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7398 ADD_INT(d, DB_REP_ELECTION_RETRY);
7399 #endif
7400 #if (DBVER >= 46)
7401 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7402 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7403 #endif
7405 #if (DBVER >= 45)
7406 ADD_INT(d, DB_REPMGR_PEER);
7407 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7408 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7409 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7410 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7411 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7412 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7413 ADD_INT(d, DB_REPMGR_CONNECTED);
7414 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7415 ADD_INT(d, DB_STAT_CLEAR);
7416 ADD_INT(d, DB_STAT_ALL);
7417 #endif
7419 #if (DBVER >= 43)
7420 ADD_INT(d, DB_BUFFER_SMALL);
7421 ADD_INT(d, DB_SEQ_DEC);
7422 ADD_INT(d, DB_SEQ_INC);
7423 ADD_INT(d, DB_SEQ_WRAP);
7424 #endif
7426 #if (DBVER >= 43) && (DBVER < 47)
7427 ADD_INT(d, DB_LOG_INMEMORY);
7428 ADD_INT(d, DB_DSYNC_LOG);
7429 #endif
7431 #if (DBVER >= 41)
7432 ADD_INT(d, DB_ENCRYPT_AES);
7433 ADD_INT(d, DB_AUTO_COMMIT);
7434 #else
7435 /* allow Berkeley DB 4.1 aware apps to run on older versions */
7436 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7437 #endif
7439 ADD_INT(d, EINVAL);
7440 ADD_INT(d, EACCES);
7441 ADD_INT(d, ENOSPC);
7442 ADD_INT(d, ENOMEM);
7443 ADD_INT(d, EAGAIN);
7444 ADD_INT(d, EBUSY);
7445 ADD_INT(d, EEXIST);
7446 ADD_INT(d, ENOENT);
7447 ADD_INT(d, EPERM);
7449 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7450 ADD_INT(d, DB_SET_TXN_TIMEOUT);
7452 /* The exception name must be correct for pickled exception *
7453 * objects to unpickle properly. */
7454 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7455 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7456 #else
7457 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7458 #endif
7460 /* All the rest of the exceptions derive only from DBError */
7461 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7462 PyDict_SetItemString(d, #name, name)
7464 /* The base exception class is DBError */
7465 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7466 MAKE_EX(DBError);
7468 #if (PY_VERSION_HEX < 0x03000000)
7469 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7470 * from both DBError and KeyError, since the API only supports
7471 * using one base class. */
7472 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
7473 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7474 "class DBKeyEmptyError(DBError, KeyError): pass",
7475 Py_file_input, d, d);
7476 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
7477 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
7478 PyDict_DelItemString(d, "KeyError");
7479 #else
7480 /* Since Python 2.5, PyErr_NewException() accepts a tuple, to be able to
7481 ** derive from several classes. We use this new API only for Python 3.0,
7482 ** though.
7485 PyObject* bases;
7487 bases = PyTuple_Pack(2, DBError, PyExc_KeyError);
7489 #define MAKE_EX2(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, bases, NULL); \
7490 PyDict_SetItemString(d, #name, name)
7491 MAKE_EX2(DBNotFoundError);
7492 MAKE_EX2(DBKeyEmptyError);
7494 #undef MAKE_EX2
7496 Py_XDECREF(bases);
7498 #endif
7501 #if !INCOMPLETE_IS_WARNING
7502 MAKE_EX(DBIncompleteError);
7503 #endif
7504 MAKE_EX(DBCursorClosedError);
7505 MAKE_EX(DBKeyEmptyError);
7506 MAKE_EX(DBKeyExistError);
7507 MAKE_EX(DBLockDeadlockError);
7508 MAKE_EX(DBLockNotGrantedError);
7509 MAKE_EX(DBOldVersionError);
7510 MAKE_EX(DBRunRecoveryError);
7511 MAKE_EX(DBVerifyBadError);
7512 MAKE_EX(DBNoServerError);
7513 MAKE_EX(DBNoServerHomeError);
7514 MAKE_EX(DBNoServerIDError);
7515 MAKE_EX(DBPageNotFoundError);
7516 MAKE_EX(DBSecondaryBadError);
7518 MAKE_EX(DBInvalidArgError);
7519 MAKE_EX(DBAccessError);
7520 MAKE_EX(DBNoSpaceError);
7521 MAKE_EX(DBNoMemoryError);
7522 MAKE_EX(DBAgainError);
7523 MAKE_EX(DBBusyError);
7524 MAKE_EX(DBFileExistsError);
7525 MAKE_EX(DBNoSuchFileError);
7526 MAKE_EX(DBPermissionsError);
7528 #if (DBVER >= 42)
7529 MAKE_EX(DBRepHandleDeadError);
7530 #endif
7532 MAKE_EX(DBRepUnavailError);
7534 #undef MAKE_EX
7536 /* Initiliase the C API structure and add it to the module */
7537 bsddb_api.db_type = &DB_Type;
7538 bsddb_api.dbcursor_type = &DBCursor_Type;
7539 bsddb_api.dbenv_type = &DBEnv_Type;
7540 bsddb_api.dbtxn_type = &DBTxn_Type;
7541 bsddb_api.dblock_type = &DBLock_Type;
7542 #if (DBVER >= 43)
7543 bsddb_api.dbsequence_type = &DBSequence_Type;
7544 #endif
7545 bsddb_api.makeDBError = makeDBError;
7547 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7548 PyDict_SetItemString(d, "api", py_api);
7549 Py_DECREF(py_api);
7551 /* Check for errors */
7552 if (PyErr_Occurred()) {
7553 PyErr_Print();
7554 Py_FatalError("can't initialize module _bsddb/_pybsddb");
7555 Py_DECREF(m);
7556 m = NULL;
7558 #if (PY_VERSION_HEX < 0x03000000)
7559 return;
7560 #else
7561 return m;
7562 #endif
7565 /* allow this module to be named _pybsddb so that it can be installed
7566 * and imported on top of python >= 2.3 that includes its own older
7567 * copy of the library named _bsddb without importing the old version. */
7568 #if (PY_VERSION_HEX < 0x03000000)
7569 DL_EXPORT(void) init_pybsddb(void)
7570 #else
7571 PyMODINIT_FUNC PyInit__pybsddb(void) /* Note the two underscores */
7572 #endif
7574 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7575 #if (PY_VERSION_HEX < 0x03000000)
7576 init_bsddb();
7577 #else
7578 return PyInit__bsddb(); /* Note the two underscores */
7579 #endif