Document the fact that urllib2 spans multiple modules with new names in Python
[python.git] / Modules / _bsddb.c
blob812f23321087b1e88419181598367e7662e4e5a1
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 #ifdef WITH_THREAD
120 /* These are for when calling Python --> C */
121 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
122 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
124 /* For 2.3, use the PyGILState_ calls */
125 #if (PY_VERSION_HEX >= 0x02030000)
126 #define MYDB_USE_GILSTATE
127 #endif
129 /* and these are for calling C --> Python */
130 #if defined(MYDB_USE_GILSTATE)
131 #define MYDB_BEGIN_BLOCK_THREADS \
132 PyGILState_STATE __savestate = PyGILState_Ensure();
133 #define MYDB_END_BLOCK_THREADS \
134 PyGILState_Release(__savestate);
135 #else /* MYDB_USE_GILSTATE */
136 /* Pre GILState API - do it the long old way */
137 static PyInterpreterState* _db_interpreterState = NULL;
138 #define MYDB_BEGIN_BLOCK_THREADS { \
139 PyThreadState* prevState; \
140 PyThreadState* newState; \
141 PyEval_AcquireLock(); \
142 newState = PyThreadState_New(_db_interpreterState); \
143 prevState = PyThreadState_Swap(newState);
145 #define MYDB_END_BLOCK_THREADS \
146 newState = PyThreadState_Swap(prevState); \
147 PyThreadState_Clear(newState); \
148 PyEval_ReleaseLock(); \
149 PyThreadState_Delete(newState); \
151 #endif /* MYDB_USE_GILSTATE */
153 #else
154 /* Compiled without threads - avoid all this cruft */
155 #define MYDB_BEGIN_ALLOW_THREADS
156 #define MYDB_END_ALLOW_THREADS
157 #define MYDB_BEGIN_BLOCK_THREADS
158 #define MYDB_END_BLOCK_THREADS
160 #endif
162 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
163 #define INCOMPLETE_IS_WARNING 1
165 /* --------------------------------------------------------------------- */
166 /* Exceptions */
168 static PyObject* DBError; /* Base class, all others derive from this */
169 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
170 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
171 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
172 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
173 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
174 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
175 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
176 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
177 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
178 static PyObject* DBNoServerError; /* DB_NOSERVER */
179 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
180 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
181 #if (DBVER >= 33)
182 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
183 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
184 #endif
186 #if !INCOMPLETE_IS_WARNING
187 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
188 #endif
190 static PyObject* DBInvalidArgError; /* EINVAL */
191 static PyObject* DBAccessError; /* EACCES */
192 static PyObject* DBNoSpaceError; /* ENOSPC */
193 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
194 static PyObject* DBAgainError; /* EAGAIN */
195 static PyObject* DBBusyError; /* EBUSY */
196 static PyObject* DBFileExistsError; /* EEXIST */
197 static PyObject* DBNoSuchFileError; /* ENOENT */
198 static PyObject* DBPermissionsError; /* EPERM */
200 #if (DBVER >= 42)
201 static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
202 #endif
204 #if (DBVER < 43)
205 #define DB_BUFFER_SMALL ENOMEM
206 #endif
209 /* --------------------------------------------------------------------- */
210 /* Structure definitions */
212 #if PYTHON_API_VERSION < 1010
213 #error "Python 2.1 or later required"
214 #endif
217 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
218 #define DEFAULT_GET_RETURNS_NONE 1
219 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
222 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
223 #if (DBVER >= 43)
224 staticforward PyTypeObject DBSequence_Type;
225 #endif
227 #ifndef Py_TYPE
228 /* for compatibility with Python 2.5 and earlier */
229 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
230 #endif
232 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
233 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
234 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
235 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
236 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
237 #if (DBVER >= 43)
238 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
239 #endif
241 #if (DBVER < 46)
242 #define _DBC_close(dbc) dbc->c_close(dbc)
243 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
244 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
245 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
246 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
247 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
248 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
249 #else
250 #define _DBC_close(dbc) dbc->close(dbc)
251 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
252 #define _DBC_del(dbc,a) dbc->del(dbc,a)
253 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
254 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
255 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
256 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
257 #endif
260 /* --------------------------------------------------------------------- */
261 /* Utility macros and functions */
263 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
265 object->sibling_next=backlink; \
266 object->sibling_prev_p=&(backlink); \
267 backlink=object; \
268 if (object->sibling_next) { \
269 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
273 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
275 if (object->sibling_next) { \
276 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
278 *(object->sibling_prev_p)=object->sibling_next; \
281 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
283 if (object->sibling_next) { \
284 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
286 if (object->sibling_prev_p) { \
287 *(object->sibling_prev_p)=object->sibling_next; \
291 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
293 object->sibling_next_txn=backlink; \
294 object->sibling_prev_p_txn=&(backlink); \
295 backlink=object; \
296 if (object->sibling_next_txn) { \
297 object->sibling_next_txn->sibling_prev_p_txn= \
298 &(object->sibling_next_txn); \
302 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
304 if (object->sibling_next_txn) { \
305 object->sibling_next_txn->sibling_prev_p_txn= \
306 object->sibling_prev_p_txn; \
308 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
312 #define RETURN_IF_ERR() \
313 if (makeDBError(err)) { \
314 return NULL; \
317 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
319 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
320 if ((nonNull) == NULL) { \
321 PyObject *errTuple = NULL; \
322 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
323 PyErr_SetObject((pyErrObj), errTuple); \
324 Py_DECREF(errTuple); \
325 return NULL; \
328 #define CHECK_DB_NOT_CLOSED(dbobj) \
329 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
331 #define CHECK_ENV_NOT_CLOSED(env) \
332 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
334 #define CHECK_CURSOR_NOT_CLOSED(curs) \
335 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
337 #if (DBVER >= 43)
338 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
339 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
340 #endif
342 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
343 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
345 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
347 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
348 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
351 static int makeDBError(int err);
354 /* Return the access method type of the DBObject */
355 static int _DB_get_type(DBObject* self)
357 #if (DBVER >= 33)
358 DBTYPE type;
359 int err;
360 err = self->db->get_type(self->db, &type);
361 if (makeDBError(err)) {
362 return -1;
364 return type;
365 #else
366 return self->db->get_type(self->db);
367 #endif
371 /* Create a DBT structure (containing key and data values) from Python
372 strings. Returns 1 on success, 0 on an error. */
373 static int make_dbt(PyObject* obj, DBT* dbt)
375 CLEAR_DBT(*dbt);
376 if (obj == Py_None) {
377 /* no need to do anything, the structure has already been zeroed */
379 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
380 PyErr_SetString(PyExc_TypeError,
381 "Data values must be of type string or None.");
382 return 0;
384 return 1;
388 /* Recno and Queue DBs can have integer keys. This function figures out
389 what's been given, verifies that it's allowed, and then makes the DBT.
391 Caller MUST call FREE_DBT(key) when done. */
392 static int
393 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
395 db_recno_t recno;
396 int type;
398 CLEAR_DBT(*key);
399 if (keyobj == Py_None) {
400 type = _DB_get_type(self);
401 if (type == -1)
402 return 0;
403 if (type == DB_RECNO || type == DB_QUEUE) {
404 PyErr_SetString(
405 PyExc_TypeError,
406 "None keys not allowed for Recno and Queue DB's");
407 return 0;
409 /* no need to do anything, the structure has already been zeroed */
412 else if (PyBytes_Check(keyobj)) {
413 /* verify access method type */
414 type = _DB_get_type(self);
415 if (type == -1)
416 return 0;
417 if (type == DB_RECNO || type == DB_QUEUE) {
418 PyErr_SetString(
419 PyExc_TypeError,
420 "String keys not allowed for Recno and Queue DB's");
421 return 0;
425 * NOTE(gps): I don't like doing a data copy here, it seems
426 * wasteful. But without a clean way to tell FREE_DBT if it
427 * should free key->data or not we have to. Other places in
428 * the code check for DB_THREAD and forceably set DBT_MALLOC
429 * when we otherwise would leave flags 0 to indicate that.
431 key->data = malloc(PyBytes_GET_SIZE(keyobj));
432 if (key->data == NULL) {
433 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
434 return 0;
436 memcpy(key->data, PyBytes_AS_STRING(keyobj),
437 PyBytes_GET_SIZE(keyobj));
438 key->flags = DB_DBT_REALLOC;
439 key->size = PyBytes_GET_SIZE(keyobj);
442 else if (PyInt_Check(keyobj)) {
443 /* verify access method type */
444 type = _DB_get_type(self);
445 if (type == -1)
446 return 0;
447 if (type == DB_BTREE && pflags != NULL) {
448 /* if BTREE then an Integer key is allowed with the
449 * DB_SET_RECNO flag */
450 *pflags |= DB_SET_RECNO;
452 else if (type != DB_RECNO && type != DB_QUEUE) {
453 PyErr_SetString(
454 PyExc_TypeError,
455 "Integer keys only allowed for Recno and Queue DB's");
456 return 0;
459 /* Make a key out of the requested recno, use allocated space so DB
460 * will be able to realloc room for the real key if needed. */
461 recno = PyInt_AS_LONG(keyobj);
462 key->data = malloc(sizeof(db_recno_t));
463 if (key->data == NULL) {
464 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
465 return 0;
467 key->ulen = key->size = sizeof(db_recno_t);
468 memcpy(key->data, &recno, sizeof(db_recno_t));
469 key->flags = DB_DBT_REALLOC;
471 else {
472 PyErr_Format(PyExc_TypeError,
473 "String or Integer object expected for key, %s found",
474 Py_TYPE(keyobj)->tp_name);
475 return 0;
478 return 1;
482 /* Add partial record access to an existing DBT data struct.
483 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
484 and the data storage/retrieval will be done using dlen and doff. */
485 static int add_partial_dbt(DBT* d, int dlen, int doff) {
486 /* if neither were set we do nothing (-1 is the default value) */
487 if ((dlen == -1) && (doff == -1)) {
488 return 1;
491 if ((dlen < 0) || (doff < 0)) {
492 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
493 return 0;
496 d->flags = d->flags | DB_DBT_PARTIAL;
497 d->dlen = (unsigned int) dlen;
498 d->doff = (unsigned int) doff;
499 return 1;
502 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
503 /* TODO: make this use the native libc strlcpy() when available (BSD) */
504 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
506 unsigned int srclen, copylen;
508 srclen = strlen(src);
509 if (n <= 0)
510 return srclen;
511 copylen = (srclen > n-1) ? n-1 : srclen;
512 /* populate dest[0] thru dest[copylen-1] */
513 memcpy(dest, src, copylen);
514 /* guarantee null termination */
515 dest[copylen] = 0;
517 return srclen;
520 /* Callback used to save away more information about errors from the DB
521 * library. */
522 static char _db_errmsg[1024];
523 #if (DBVER <= 42)
524 static void _db_errorCallback(const char* prefix, char* msg)
525 #else
526 static void _db_errorCallback(const DB_ENV *db_env,
527 const char* prefix, const char* msg)
528 #endif
530 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
535 ** We need these functions because some results
536 ** are undefined if pointer is NULL. Some other
537 ** give None instead of "".
539 ** This functions are static and will be
540 ** -I hope- inlined.
542 static const char *DummyString = "This string is a simple placeholder";
543 static PyObject *Build_PyString(const char *p,int s)
545 if (!p) {
546 p=DummyString;
547 assert(s==0);
549 return PyBytes_FromStringAndSize(p,s);
552 static PyObject *BuildValue_S(const void *p,int s)
554 if (!p) {
555 p=DummyString;
556 assert(s==0);
558 return Py_BuildValue("s#",p,s);
561 static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
563 if (!p1) {
564 p1=DummyString;
565 assert(s1==0);
567 if (!p2) {
568 p2=DummyString;
569 assert(s2==0);
571 return Py_BuildValue("s#s#",p1,s1,p2,s2);
574 static PyObject *BuildValue_IS(int i,const void *p,int s)
576 if (!p) {
577 p=DummyString;
578 assert(s==0);
580 return Py_BuildValue("is#",i,p,s);
583 static PyObject *BuildValue_LS(long i,const void *p,int s)
585 if (!p) {
586 p=DummyString;
587 assert(s==0);
589 return Py_BuildValue("ls#",i,p,s);
594 /* make a nice exception object to raise for errors. */
595 static int makeDBError(int err)
597 char errTxt[2048]; /* really big, just in case... */
598 PyObject *errObj = NULL;
599 PyObject *errTuple = NULL;
600 int exceptionRaised = 0;
601 unsigned int bytes_left;
603 switch (err) {
604 case 0: /* successful, no error */ break;
606 #if (DBVER < 41)
607 case DB_INCOMPLETE:
608 #if INCOMPLETE_IS_WARNING
609 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
610 /* Ensure that bytes_left never goes negative */
611 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
612 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
613 assert(bytes_left >= 0);
614 strcat(errTxt, " -- ");
615 strncat(errTxt, _db_errmsg, bytes_left);
617 _db_errmsg[0] = 0;
618 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
620 #else /* do an exception instead */
621 errObj = DBIncompleteError;
622 #endif
623 break;
624 #endif /* DBVER < 41 */
626 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
627 case DB_KEYEXIST: errObj = DBKeyExistError; break;
628 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
629 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
630 case DB_NOTFOUND: errObj = DBNotFoundError; break;
631 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
632 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
633 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
634 case DB_NOSERVER: errObj = DBNoServerError; break;
635 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
636 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
637 #if (DBVER >= 33)
638 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
639 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
640 #endif
641 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
643 #if (DBVER >= 43)
644 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
645 case ENOMEM: errObj = PyExc_MemoryError; break;
646 #endif
647 case EINVAL: errObj = DBInvalidArgError; break;
648 case EACCES: errObj = DBAccessError; break;
649 case ENOSPC: errObj = DBNoSpaceError; break;
650 case EAGAIN: errObj = DBAgainError; break;
651 case EBUSY : errObj = DBBusyError; break;
652 case EEXIST: errObj = DBFileExistsError; break;
653 case ENOENT: errObj = DBNoSuchFileError; break;
654 case EPERM : errObj = DBPermissionsError; break;
656 #if (DBVER >= 42)
657 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
658 #endif
660 default: errObj = DBError; break;
663 if (errObj != NULL) {
664 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
665 /* Ensure that bytes_left never goes negative */
666 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
667 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
668 assert(bytes_left >= 0);
669 strcat(errTxt, " -- ");
670 strncat(errTxt, _db_errmsg, bytes_left);
672 _db_errmsg[0] = 0;
674 errTuple = Py_BuildValue("(is)", err, errTxt);
675 PyErr_SetObject(errObj, errTuple);
676 Py_DECREF(errTuple);
679 return ((errObj != NULL) || exceptionRaised);
684 /* set a type exception */
685 static void makeTypeError(char* expected, PyObject* found)
687 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
688 expected, Py_TYPE(found)->tp_name);
692 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
693 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
695 if (txnobj == Py_None || txnobj == NULL) {
696 *txn = NULL;
697 return 1;
699 if (DBTxnObject_Check(txnobj)) {
700 *txn = ((DBTxnObject*)txnobj)->txn;
701 return 1;
703 else
704 makeTypeError("DBTxn", txnobj);
705 return 0;
709 /* Delete a key from a database
710 Returns 0 on success, -1 on an error. */
711 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
713 int err;
715 MYDB_BEGIN_ALLOW_THREADS;
716 err = self->db->del(self->db, txn, key, 0);
717 MYDB_END_ALLOW_THREADS;
718 if (makeDBError(err)) {
719 return -1;
721 self->haveStat = 0;
722 return 0;
726 /* Store a key into a database
727 Returns 0 on success, -1 on an error. */
728 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
730 int err;
732 MYDB_BEGIN_ALLOW_THREADS;
733 err = self->db->put(self->db, txn, key, data, flags);
734 MYDB_END_ALLOW_THREADS;
735 if (makeDBError(err)) {
736 return -1;
738 self->haveStat = 0;
739 return 0;
742 /* Get a key/data pair from a cursor */
743 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
744 PyObject *args, PyObject *kwargs, char *format)
746 int err;
747 PyObject* retval = NULL;
748 DBT key, data;
749 int dlen = -1;
750 int doff = -1;
751 int flags = 0;
752 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
754 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
755 &flags, &dlen, &doff))
756 return NULL;
758 CHECK_CURSOR_NOT_CLOSED(self);
760 flags |= extra_flags;
761 CLEAR_DBT(key);
762 CLEAR_DBT(data);
763 if (!add_partial_dbt(&data, dlen, doff))
764 return NULL;
766 MYDB_BEGIN_ALLOW_THREADS;
767 err = _DBC_get(self->dbc, &key, &data, flags);
768 MYDB_END_ALLOW_THREADS;
770 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
771 && self->mydb->moduleFlags.getReturnsNone) {
772 Py_INCREF(Py_None);
773 retval = Py_None;
775 else if (makeDBError(err)) {
776 retval = NULL;
778 else { /* otherwise, success! */
780 /* if Recno or Queue, return the key as an Int */
781 switch (_DB_get_type(self->mydb)) {
782 case -1:
783 retval = NULL;
784 break;
786 case DB_RECNO:
787 case DB_QUEUE:
788 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
789 break;
790 case DB_HASH:
791 case DB_BTREE:
792 default:
793 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
794 break;
797 return retval;
801 /* add an integer to a dictionary using the given name as a key */
802 static void _addIntToDict(PyObject* dict, char *name, int value)
804 PyObject* v = PyInt_FromLong((long) value);
805 if (!v || PyDict_SetItemString(dict, name, v))
806 PyErr_Clear();
808 Py_XDECREF(v);
811 /* The same, when the value is a time_t */
812 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
814 PyObject* v;
815 /* if the value fits in regular int, use that. */
816 #ifdef PY_LONG_LONG
817 if (sizeof(time_t) > sizeof(long))
818 v = PyLong_FromLongLong((PY_LONG_LONG) value);
819 else
820 #endif
821 v = PyInt_FromLong((long) value);
822 if (!v || PyDict_SetItemString(dict, name, v))
823 PyErr_Clear();
825 Py_XDECREF(v);
828 #if (DBVER >= 43)
829 /* add an db_seq_t to a dictionary using the given name as a key */
830 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
832 PyObject* v = PyLong_FromLongLong(value);
833 if (!v || PyDict_SetItemString(dict, name, v))
834 PyErr_Clear();
836 Py_XDECREF(v);
838 #endif
840 #if (DBVER >= 40)
841 static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
843 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
844 if (!v || PyDict_SetItemString(dict, name, v))
845 PyErr_Clear();
847 Py_XDECREF(v);
849 #endif
851 /* --------------------------------------------------------------------- */
852 /* Allocators and deallocators */
854 static DBObject*
855 newDBObject(DBEnvObject* arg, int flags)
857 DBObject* self;
858 DB_ENV* db_env = NULL;
859 int err;
861 self = PyObject_New(DBObject, &DB_Type);
862 if (self == NULL)
863 return NULL;
865 self->haveStat = 0;
866 self->flags = 0;
867 self->setflags = 0;
868 self->myenvobj = NULL;
869 self->children_cursors = NULL;
870 #if (DBVER >=43)
871 self->children_sequences = NULL;
872 #endif
873 #if (DBVER >= 33)
874 self->associateCallback = NULL;
875 self->btCompareCallback = NULL;
876 self->primaryDBType = 0;
877 #endif
878 self->in_weakreflist = NULL;
880 /* keep a reference to our python DBEnv object */
881 if (arg) {
882 Py_INCREF(arg);
883 self->myenvobj = arg;
884 db_env = arg->db_env;
885 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
886 } else {
887 self->sibling_prev_p=NULL;
888 self->sibling_next=NULL;
890 self->txn=NULL;
891 self->sibling_prev_p_txn=NULL;
892 self->sibling_next_txn=NULL;
894 if (self->myenvobj)
895 self->moduleFlags = self->myenvobj->moduleFlags;
896 else
897 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
898 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
900 MYDB_BEGIN_ALLOW_THREADS;
901 err = db_create(&self->db, db_env, flags);
902 if (self->db != NULL) {
903 self->db->set_errcall(self->db, _db_errorCallback);
904 #if (DBVER >= 33)
905 self->db->app_private = (void*)self;
906 #endif
908 MYDB_END_ALLOW_THREADS;
909 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
910 * list so that a DBEnv can refuse to close without aborting any open
911 * DBTxns and closing any open DBs first. */
912 if (makeDBError(err)) {
913 if (self->myenvobj) {
914 Py_DECREF(self->myenvobj);
915 self->myenvobj = NULL;
917 Py_DECREF(self);
918 self = NULL;
920 return self;
924 /* Forward declaration */
925 static PyObject *DB_close_internal(DBObject* self, int flags);
927 static void
928 DB_dealloc(DBObject* self)
930 PyObject *dummy;
932 if (self->db != NULL) {
933 dummy=DB_close_internal(self,0);
934 Py_XDECREF(dummy);
936 if (self->in_weakreflist != NULL) {
937 PyObject_ClearWeakRefs((PyObject *) self);
939 if (self->myenvobj) {
940 Py_DECREF(self->myenvobj);
941 self->myenvobj = NULL;
943 #if (DBVER >= 33)
944 if (self->associateCallback != NULL) {
945 Py_DECREF(self->associateCallback);
946 self->associateCallback = NULL;
948 if (self->btCompareCallback != NULL) {
949 Py_DECREF(self->btCompareCallback);
950 self->btCompareCallback = NULL;
952 #endif
953 PyObject_Del(self);
956 static DBCursorObject*
957 newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
959 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
960 if (self == NULL)
961 return NULL;
963 self->dbc = dbc;
964 self->mydb = db;
966 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
967 if (txn && ((PyObject *)txn!=Py_None)) {
968 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
969 self->txn=txn;
970 } else {
971 self->txn=NULL;
974 self->in_weakreflist = NULL;
975 Py_INCREF(self->mydb);
976 return self;
980 /* Forward declaration */
981 static PyObject *DBC_close_internal(DBCursorObject* self);
983 static void
984 DBCursor_dealloc(DBCursorObject* self)
986 PyObject *dummy;
988 if (self->dbc != NULL) {
989 dummy=DBC_close_internal(self);
990 Py_XDECREF(dummy);
992 if (self->in_weakreflist != NULL) {
993 PyObject_ClearWeakRefs((PyObject *) self);
995 Py_DECREF(self->mydb);
996 PyObject_Del(self);
1000 static DBEnvObject*
1001 newDBEnvObject(int flags)
1003 int err;
1004 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
1005 if (self == NULL)
1006 return NULL;
1008 self->closed = 1;
1009 self->flags = flags;
1010 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1011 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
1012 self->children_dbs = NULL;
1013 self->children_txns = NULL;
1014 self->in_weakreflist = NULL;
1016 #if (DBVER >= 40)
1017 self->event_notifyCallback = NULL;
1018 #endif
1020 MYDB_BEGIN_ALLOW_THREADS;
1021 err = db_env_create(&self->db_env, flags);
1022 MYDB_END_ALLOW_THREADS;
1023 if (makeDBError(err)) {
1024 Py_DECREF(self);
1025 self = NULL;
1027 else {
1028 self->db_env->set_errcall(self->db_env, _db_errorCallback);
1029 self->db_env->app_private=self;
1031 return self;
1034 /* Forward declaration */
1035 static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
1037 static void
1038 DBEnv_dealloc(DBEnvObject* self)
1040 PyObject *dummy;
1042 if (self->db_env && !self->closed) {
1043 dummy=DBEnv_close_internal(self,0);
1044 Py_XDECREF(dummy);
1047 #if (DBVER >= 40)
1048 Py_XDECREF(self->event_notifyCallback);
1049 self->event_notifyCallback = NULL;
1050 #endif
1052 if (self->in_weakreflist != NULL) {
1053 PyObject_ClearWeakRefs((PyObject *) self);
1056 PyObject_Del(self);
1060 static DBTxnObject*
1061 newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
1063 int err;
1064 DB_TXN *parent_txn = NULL;
1066 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
1067 if (self == NULL)
1068 return NULL;
1070 self->in_weakreflist = NULL;
1071 self->children_txns = NULL;
1072 self->children_dbs = NULL;
1073 self->children_cursors = NULL;
1074 self->children_sequences = NULL;
1075 self->flag_prepare = 0;
1076 self->parent_txn = NULL;
1077 self->env = NULL;
1079 if (parent && ((PyObject *)parent!=Py_None)) {
1080 parent_txn = parent->txn;
1083 if (txn) {
1084 self->txn = txn;
1085 } else {
1086 MYDB_BEGIN_ALLOW_THREADS;
1087 #if (DBVER >= 40)
1088 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1089 #else
1090 err = txn_begin(myenv->db_env, parent->txn, &(self_txn), flags);
1091 #endif
1092 MYDB_END_ALLOW_THREADS;
1094 if (makeDBError(err)) {
1095 Py_DECREF(self);
1096 return NULL;
1100 /* Can't use 'parent' because could be 'parent==Py_None' */
1101 if (parent_txn) {
1102 self->parent_txn = parent;
1103 Py_INCREF(parent);
1104 self->env = NULL;
1105 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
1106 } else {
1107 self->parent_txn = NULL;
1108 Py_INCREF(myenv);
1109 self->env = myenv;
1110 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
1113 return self;
1116 /* Forward declaration */
1117 static PyObject *
1118 DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
1120 static void
1121 DBTxn_dealloc(DBTxnObject* self)
1123 PyObject *dummy;
1125 if (self->txn) {
1126 int flag_prepare = self->flag_prepare;
1127 dummy=DBTxn_abort_discard_internal(self,0);
1128 Py_XDECREF(dummy);
1129 if (!flag_prepare) {
1130 PyErr_Warn(PyExc_RuntimeWarning,
1131 "DBTxn aborted in destructor. No prior commit() or abort().");
1135 if (self->in_weakreflist != NULL) {
1136 PyObject_ClearWeakRefs((PyObject *) self);
1139 if (self->env) {
1140 Py_DECREF(self->env);
1141 } else {
1142 Py_DECREF(self->parent_txn);
1144 PyObject_Del(self);
1148 static DBLockObject*
1149 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1150 db_lockmode_t lock_mode, int flags)
1152 int err;
1153 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1154 if (self == NULL)
1155 return NULL;
1156 self->in_weakreflist = NULL;
1158 MYDB_BEGIN_ALLOW_THREADS;
1159 #if (DBVER >= 40)
1160 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1161 &self->lock);
1162 #else
1163 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1164 #endif
1165 MYDB_END_ALLOW_THREADS;
1166 if (makeDBError(err)) {
1167 Py_DECREF(self);
1168 self = NULL;
1171 return self;
1175 static void
1176 DBLock_dealloc(DBLockObject* self)
1178 if (self->in_weakreflist != NULL) {
1179 PyObject_ClearWeakRefs((PyObject *) self);
1181 /* TODO: is this lock held? should we release it? */
1183 PyObject_Del(self);
1187 #if (DBVER >= 43)
1188 static DBSequenceObject*
1189 newDBSequenceObject(DBObject* mydb, int flags)
1191 int err;
1192 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1193 if (self == NULL)
1194 return NULL;
1195 Py_INCREF(mydb);
1196 self->mydb = mydb;
1198 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
1199 self->txn = NULL;
1201 self->in_weakreflist = NULL;
1203 MYDB_BEGIN_ALLOW_THREADS;
1204 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1205 MYDB_END_ALLOW_THREADS;
1206 if (makeDBError(err)) {
1207 Py_DECREF(self);
1208 self = NULL;
1211 return self;
1214 /* Forward declaration */
1215 static PyObject
1216 *DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
1218 static void
1219 DBSequence_dealloc(DBSequenceObject* self)
1221 PyObject *dummy;
1223 if (self->sequence != NULL) {
1224 dummy=DBSequence_close_internal(self,0,0);
1225 Py_XDECREF(dummy);
1228 if (self->in_weakreflist != NULL) {
1229 PyObject_ClearWeakRefs((PyObject *) self);
1232 Py_DECREF(self->mydb);
1233 PyObject_Del(self);
1235 #endif
1237 /* --------------------------------------------------------------------- */
1238 /* DB methods */
1240 static PyObject*
1241 DB_append(DBObject* self, PyObject* args)
1243 PyObject* txnobj = NULL;
1244 PyObject* dataobj;
1245 db_recno_t recno;
1246 DBT key, data;
1247 DB_TXN *txn = NULL;
1249 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1250 return NULL;
1252 CHECK_DB_NOT_CLOSED(self);
1254 /* make a dummy key out of a recno */
1255 recno = 0;
1256 CLEAR_DBT(key);
1257 key.data = &recno;
1258 key.size = sizeof(recno);
1259 key.ulen = key.size;
1260 key.flags = DB_DBT_USERMEM;
1262 if (!make_dbt(dataobj, &data)) return NULL;
1263 if (!checkTxnObj(txnobj, &txn)) return NULL;
1265 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1266 return NULL;
1268 return PyInt_FromLong(recno);
1272 #if (DBVER >= 33)
1274 static int
1275 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1276 DBT* secKey)
1278 int retval = DB_DONOTINDEX;
1279 DBObject* secondaryDB = (DBObject*)db->app_private;
1280 PyObject* callback = secondaryDB->associateCallback;
1281 int type = secondaryDB->primaryDBType;
1282 PyObject* args;
1283 PyObject* result = NULL;
1286 if (callback != NULL) {
1287 MYDB_BEGIN_BLOCK_THREADS;
1289 if (type == DB_RECNO || type == DB_QUEUE)
1290 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
1291 else
1292 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
1293 if (args != NULL) {
1294 result = PyEval_CallObject(callback, args);
1296 if (args == NULL || result == NULL) {
1297 PyErr_Print();
1299 else if (result == Py_None) {
1300 retval = DB_DONOTINDEX;
1302 else if (PyInt_Check(result)) {
1303 retval = PyInt_AsLong(result);
1305 else if (PyBytes_Check(result)) {
1306 char* data;
1307 Py_ssize_t size;
1309 CLEAR_DBT(*secKey);
1310 PyBytes_AsStringAndSize(result, &data, &size);
1311 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1312 secKey->data = malloc(size); /* TODO, check this */
1313 if (secKey->data) {
1314 memcpy(secKey->data, data, size);
1315 secKey->size = size;
1316 retval = 0;
1318 else {
1319 PyErr_SetString(PyExc_MemoryError,
1320 "malloc failed in _db_associateCallback");
1321 PyErr_Print();
1324 else {
1325 PyErr_SetString(
1326 PyExc_TypeError,
1327 "DB associate callback should return DB_DONOTINDEX or string.");
1328 PyErr_Print();
1331 Py_XDECREF(args);
1332 Py_XDECREF(result);
1334 MYDB_END_BLOCK_THREADS;
1336 return retval;
1340 static PyObject*
1341 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1343 int err, flags=0;
1344 DBObject* secondaryDB;
1345 PyObject* callback;
1346 #if (DBVER >= 41)
1347 PyObject *txnobj = NULL;
1348 DB_TXN *txn = NULL;
1349 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1350 NULL};
1351 #else
1352 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1353 #endif
1355 #if (DBVER >= 41)
1356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1357 &secondaryDB, &callback, &flags,
1358 &txnobj)) {
1359 #else
1360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1361 &secondaryDB, &callback, &flags)) {
1362 #endif
1363 return NULL;
1366 #if (DBVER >= 41)
1367 if (!checkTxnObj(txnobj, &txn)) return NULL;
1368 #endif
1370 CHECK_DB_NOT_CLOSED(self);
1371 if (!DBObject_Check(secondaryDB)) {
1372 makeTypeError("DB", (PyObject*)secondaryDB);
1373 return NULL;
1375 CHECK_DB_NOT_CLOSED(secondaryDB);
1376 if (callback == Py_None) {
1377 callback = NULL;
1379 else if (!PyCallable_Check(callback)) {
1380 makeTypeError("Callable", callback);
1381 return NULL;
1384 /* Save a reference to the callback in the secondary DB. */
1385 Py_XDECREF(secondaryDB->associateCallback);
1386 Py_XINCREF(callback);
1387 secondaryDB->associateCallback = callback;
1388 secondaryDB->primaryDBType = _DB_get_type(self);
1390 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1391 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1392 * The global interepreter lock is not initialized until the first
1393 * thread is created using thread.start_new_thread() or fork() is
1394 * called. that would cause the ALLOW_THREADS here to segfault due
1395 * to a null pointer reference if no threads or child processes
1396 * have been created. This works around that and is a no-op if
1397 * threads have already been initialized.
1398 * (see pybsddb-users mailing list post on 2002-08-07)
1400 #ifdef WITH_THREAD
1401 PyEval_InitThreads();
1402 #endif
1403 MYDB_BEGIN_ALLOW_THREADS;
1404 #if (DBVER >= 41)
1405 err = self->db->associate(self->db,
1406 txn,
1407 secondaryDB->db,
1408 _db_associateCallback,
1409 flags);
1410 #else
1411 err = self->db->associate(self->db,
1412 secondaryDB->db,
1413 _db_associateCallback,
1414 flags);
1415 #endif
1416 MYDB_END_ALLOW_THREADS;
1418 if (err) {
1419 Py_XDECREF(secondaryDB->associateCallback);
1420 secondaryDB->associateCallback = NULL;
1421 secondaryDB->primaryDBType = 0;
1424 RETURN_IF_ERR();
1425 RETURN_NONE();
1429 #endif
1432 static PyObject*
1433 DB_close_internal(DBObject* self, int flags)
1435 PyObject *dummy;
1436 int err;
1438 if (self->db != NULL) {
1439 /* Can be NULL if db is not in an environment */
1440 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1441 if (self->txn) {
1442 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1443 self->txn=NULL;
1446 while(self->children_cursors) {
1447 dummy=DBC_close_internal(self->children_cursors);
1448 Py_XDECREF(dummy);
1451 #if (DBVER >= 43)
1452 while(self->children_sequences) {
1453 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1454 Py_XDECREF(dummy);
1456 #endif
1458 MYDB_BEGIN_ALLOW_THREADS;
1459 err = self->db->close(self->db, flags);
1460 MYDB_END_ALLOW_THREADS;
1461 self->db = NULL;
1462 RETURN_IF_ERR();
1464 RETURN_NONE();
1467 static PyObject*
1468 DB_close(DBObject* self, PyObject* args)
1470 int flags=0;
1471 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1472 return NULL;
1473 return DB_close_internal(self,flags);
1477 static PyObject*
1478 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1480 int err, flags=0, type;
1481 PyObject* txnobj = NULL;
1482 PyObject* retval = NULL;
1483 DBT key, data;
1484 DB_TXN *txn = NULL;
1485 static char* kwnames[] = { "txn", "flags", NULL };
1487 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1488 &txnobj, &flags))
1489 return NULL;
1491 CHECK_DB_NOT_CLOSED(self);
1492 type = _DB_get_type(self);
1493 if (type == -1)
1494 return NULL;
1495 if (type != DB_QUEUE) {
1496 PyErr_SetString(PyExc_TypeError,
1497 "Consume methods only allowed for Queue DB's");
1498 return NULL;
1500 if (!checkTxnObj(txnobj, &txn))
1501 return NULL;
1503 CLEAR_DBT(key);
1504 CLEAR_DBT(data);
1505 if (CHECK_DBFLAG(self, DB_THREAD)) {
1506 /* Tell Berkeley DB to malloc the return value (thread safe) */
1507 data.flags = DB_DBT_MALLOC;
1508 key.flags = DB_DBT_MALLOC;
1511 MYDB_BEGIN_ALLOW_THREADS;
1512 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1513 MYDB_END_ALLOW_THREADS;
1515 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1516 && self->moduleFlags.getReturnsNone) {
1517 err = 0;
1518 Py_INCREF(Py_None);
1519 retval = Py_None;
1521 else if (!err) {
1522 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1523 FREE_DBT(key);
1524 FREE_DBT(data);
1527 RETURN_IF_ERR();
1528 return retval;
1531 static PyObject*
1532 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1534 return _DB_consume(self, args, kwargs, DB_CONSUME);
1537 static PyObject*
1538 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1539 int consume_flag)
1541 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1545 static PyObject*
1546 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1548 int err, flags=0;
1549 DBC* dbc;
1550 PyObject* txnobj = NULL;
1551 DB_TXN *txn = NULL;
1552 static char* kwnames[] = { "txn", "flags", NULL };
1554 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1555 &txnobj, &flags))
1556 return NULL;
1557 CHECK_DB_NOT_CLOSED(self);
1558 if (!checkTxnObj(txnobj, &txn))
1559 return NULL;
1561 MYDB_BEGIN_ALLOW_THREADS;
1562 err = self->db->cursor(self->db, txn, &dbc, flags);
1563 MYDB_END_ALLOW_THREADS;
1564 RETURN_IF_ERR();
1565 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
1569 static PyObject*
1570 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1572 PyObject* txnobj = NULL;
1573 int flags = 0;
1574 PyObject* keyobj;
1575 DBT key;
1576 DB_TXN *txn = NULL;
1577 static char* kwnames[] = { "key", "txn", "flags", NULL };
1579 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1580 &keyobj, &txnobj, &flags))
1581 return NULL;
1582 CHECK_DB_NOT_CLOSED(self);
1583 if (!make_key_dbt(self, keyobj, &key, NULL))
1584 return NULL;
1585 if (!checkTxnObj(txnobj, &txn)) {
1586 FREE_DBT(key);
1587 return NULL;
1590 if (-1 == _DB_delete(self, txn, &key, 0)) {
1591 FREE_DBT(key);
1592 return NULL;
1595 FREE_DBT(key);
1596 RETURN_NONE();
1600 static PyObject*
1601 DB_fd(DBObject* self, PyObject* args)
1603 int err, the_fd;
1605 if (!PyArg_ParseTuple(args,":fd"))
1606 return NULL;
1607 CHECK_DB_NOT_CLOSED(self);
1609 MYDB_BEGIN_ALLOW_THREADS;
1610 err = self->db->fd(self->db, &the_fd);
1611 MYDB_END_ALLOW_THREADS;
1612 RETURN_IF_ERR();
1613 return PyInt_FromLong(the_fd);
1617 static PyObject*
1618 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1620 int err, flags=0;
1621 PyObject* txnobj = NULL;
1622 PyObject* keyobj;
1623 PyObject* dfltobj = NULL;
1624 PyObject* retval = NULL;
1625 int dlen = -1;
1626 int doff = -1;
1627 DBT key, data;
1628 DB_TXN *txn = NULL;
1629 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1630 "doff", NULL};
1632 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1633 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1634 &doff))
1635 return NULL;
1637 CHECK_DB_NOT_CLOSED(self);
1638 if (!make_key_dbt(self, keyobj, &key, &flags))
1639 return NULL;
1640 if (!checkTxnObj(txnobj, &txn)) {
1641 FREE_DBT(key);
1642 return NULL;
1645 CLEAR_DBT(data);
1646 if (CHECK_DBFLAG(self, DB_THREAD)) {
1647 /* Tell Berkeley DB to malloc the return value (thread safe) */
1648 data.flags = DB_DBT_MALLOC;
1650 if (!add_partial_dbt(&data, dlen, doff)) {
1651 FREE_DBT(key);
1652 return NULL;
1655 MYDB_BEGIN_ALLOW_THREADS;
1656 err = self->db->get(self->db, txn, &key, &data, flags);
1657 MYDB_END_ALLOW_THREADS;
1659 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1660 err = 0;
1661 Py_INCREF(dfltobj);
1662 retval = dfltobj;
1664 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1665 && self->moduleFlags.getReturnsNone) {
1666 err = 0;
1667 Py_INCREF(Py_None);
1668 retval = Py_None;
1670 else if (!err) {
1671 if (flags & DB_SET_RECNO) /* return both key and data */
1672 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
1673 else /* return just the data */
1674 retval = Build_PyString(data.data, data.size);
1675 FREE_DBT(data);
1677 FREE_DBT(key);
1679 RETURN_IF_ERR();
1680 return retval;
1683 #if (DBVER >= 33)
1684 static PyObject*
1685 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1687 int err, flags=0;
1688 PyObject* txnobj = NULL;
1689 PyObject* keyobj;
1690 PyObject* dfltobj = NULL;
1691 PyObject* retval = NULL;
1692 int dlen = -1;
1693 int doff = -1;
1694 DBT key, pkey, data;
1695 DB_TXN *txn = NULL;
1696 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1697 "doff", NULL};
1699 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1700 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1701 &doff))
1702 return NULL;
1704 CHECK_DB_NOT_CLOSED(self);
1705 if (!make_key_dbt(self, keyobj, &key, &flags))
1706 return NULL;
1707 if (!checkTxnObj(txnobj, &txn)) {
1708 FREE_DBT(key);
1709 return NULL;
1712 CLEAR_DBT(data);
1713 if (CHECK_DBFLAG(self, DB_THREAD)) {
1714 /* Tell Berkeley DB to malloc the return value (thread safe) */
1715 data.flags = DB_DBT_MALLOC;
1717 if (!add_partial_dbt(&data, dlen, doff)) {
1718 FREE_DBT(key);
1719 return NULL;
1722 CLEAR_DBT(pkey);
1723 pkey.flags = DB_DBT_MALLOC;
1725 MYDB_BEGIN_ALLOW_THREADS;
1726 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1727 MYDB_END_ALLOW_THREADS;
1729 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1730 err = 0;
1731 Py_INCREF(dfltobj);
1732 retval = dfltobj;
1734 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1735 && self->moduleFlags.getReturnsNone) {
1736 err = 0;
1737 Py_INCREF(Py_None);
1738 retval = Py_None;
1740 else if (!err) {
1741 PyObject *pkeyObj;
1742 PyObject *dataObj;
1743 dataObj = Build_PyString(data.data, data.size);
1745 if (self->primaryDBType == DB_RECNO ||
1746 self->primaryDBType == DB_QUEUE)
1747 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1748 else
1749 pkeyObj = Build_PyString(pkey.data, pkey.size);
1751 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1753 PyObject *keyObj;
1754 int type = _DB_get_type(self);
1755 if (type == DB_RECNO || type == DB_QUEUE)
1756 keyObj = PyInt_FromLong(*(int *)key.data);
1757 else
1758 keyObj = Build_PyString(key.data, key.size);
1759 #if (PY_VERSION_HEX >= 0x02040000)
1760 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1761 #else
1762 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1763 #endif
1764 Py_DECREF(keyObj);
1766 else /* return just the pkey and data */
1768 #if (PY_VERSION_HEX >= 0x02040000)
1769 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1770 #else
1771 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1772 #endif
1774 Py_DECREF(dataObj);
1775 Py_DECREF(pkeyObj);
1776 FREE_DBT(pkey);
1777 FREE_DBT(data);
1779 FREE_DBT(key);
1781 RETURN_IF_ERR();
1782 return retval;
1784 #endif
1787 /* Return size of entry */
1788 static PyObject*
1789 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1791 int err, flags=0;
1792 PyObject* txnobj = NULL;
1793 PyObject* keyobj;
1794 PyObject* retval = NULL;
1795 DBT key, data;
1796 DB_TXN *txn = NULL;
1797 static char* kwnames[] = { "key", "txn", NULL };
1799 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1800 &keyobj, &txnobj))
1801 return NULL;
1802 CHECK_DB_NOT_CLOSED(self);
1803 if (!make_key_dbt(self, keyobj, &key, &flags))
1804 return NULL;
1805 if (!checkTxnObj(txnobj, &txn)) {
1806 FREE_DBT(key);
1807 return NULL;
1809 CLEAR_DBT(data);
1811 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1812 thus getting the record size. */
1813 data.flags = DB_DBT_USERMEM;
1814 data.ulen = 0;
1815 MYDB_BEGIN_ALLOW_THREADS;
1816 err = self->db->get(self->db, txn, &key, &data, flags);
1817 MYDB_END_ALLOW_THREADS;
1818 if (err == DB_BUFFER_SMALL) {
1819 retval = PyInt_FromLong((long)data.size);
1820 err = 0;
1823 FREE_DBT(key);
1824 FREE_DBT(data);
1825 RETURN_IF_ERR();
1826 return retval;
1830 static PyObject*
1831 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1833 int err, flags=0;
1834 PyObject* txnobj = NULL;
1835 PyObject* keyobj;
1836 PyObject* dataobj;
1837 PyObject* retval = NULL;
1838 DBT key, data;
1839 void *orig_data;
1840 DB_TXN *txn = NULL;
1841 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1844 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1845 &keyobj, &dataobj, &txnobj, &flags))
1846 return NULL;
1848 CHECK_DB_NOT_CLOSED(self);
1849 if (!make_key_dbt(self, keyobj, &key, NULL))
1850 return NULL;
1851 if ( !make_dbt(dataobj, &data) ||
1852 !checkTxnObj(txnobj, &txn) )
1854 FREE_DBT(key);
1855 return NULL;
1858 flags |= DB_GET_BOTH;
1859 orig_data = data.data;
1861 if (CHECK_DBFLAG(self, DB_THREAD)) {
1862 /* Tell Berkeley DB to malloc the return value (thread safe) */
1863 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1864 data.flags = DB_DBT_MALLOC;
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->get(self->db, txn, &key, &data, flags);
1869 MYDB_END_ALLOW_THREADS;
1871 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1872 && self->moduleFlags.getReturnsNone) {
1873 err = 0;
1874 Py_INCREF(Py_None);
1875 retval = Py_None;
1877 else if (!err) {
1878 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1879 retval = Build_PyString(data.data, data.size);
1881 /* Even though the flags require DB_DBT_MALLOC, data is not always
1882 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1883 if (data.data != orig_data)
1884 FREE_DBT(data);
1887 FREE_DBT(key);
1888 RETURN_IF_ERR();
1889 return retval;
1893 static PyObject*
1894 DB_get_byteswapped(DBObject* self, PyObject* args)
1896 #if (DBVER >= 33)
1897 int err = 0;
1898 #endif
1899 int retval = -1;
1901 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1902 return NULL;
1903 CHECK_DB_NOT_CLOSED(self);
1905 #if (DBVER >= 33)
1906 MYDB_BEGIN_ALLOW_THREADS;
1907 err = self->db->get_byteswapped(self->db, &retval);
1908 MYDB_END_ALLOW_THREADS;
1909 RETURN_IF_ERR();
1910 #else
1911 MYDB_BEGIN_ALLOW_THREADS;
1912 retval = self->db->get_byteswapped(self->db);
1913 MYDB_END_ALLOW_THREADS;
1914 #endif
1915 return PyInt_FromLong(retval);
1919 static PyObject*
1920 DB_get_type(DBObject* self, PyObject* args)
1922 int type;
1924 if (!PyArg_ParseTuple(args,":get_type"))
1925 return NULL;
1926 CHECK_DB_NOT_CLOSED(self);
1928 type = _DB_get_type(self);
1929 if (type == -1)
1930 return NULL;
1931 return PyInt_FromLong(type);
1935 static PyObject*
1936 DB_join(DBObject* self, PyObject* args)
1938 int err, flags=0;
1939 int length, x;
1940 PyObject* cursorsObj;
1941 DBC** cursors;
1942 DBC* dbc;
1944 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1945 return NULL;
1947 CHECK_DB_NOT_CLOSED(self);
1949 if (!PySequence_Check(cursorsObj)) {
1950 PyErr_SetString(PyExc_TypeError,
1951 "Sequence of DBCursor objects expected");
1952 return NULL;
1955 length = PyObject_Length(cursorsObj);
1956 cursors = malloc((length+1) * sizeof(DBC*));
1957 if (!cursors) {
1958 PyErr_NoMemory();
1959 return NULL;
1962 cursors[length] = NULL;
1963 for (x=0; x<length; x++) {
1964 PyObject* item = PySequence_GetItem(cursorsObj, x);
1965 if (item == NULL) {
1966 free(cursors);
1967 return NULL;
1969 if (!DBCursorObject_Check(item)) {
1970 PyErr_SetString(PyExc_TypeError,
1971 "Sequence of DBCursor objects expected");
1972 free(cursors);
1973 return NULL;
1975 cursors[x] = ((DBCursorObject*)item)->dbc;
1976 Py_DECREF(item);
1979 MYDB_BEGIN_ALLOW_THREADS;
1980 err = self->db->join(self->db, cursors, &dbc, flags);
1981 MYDB_END_ALLOW_THREADS;
1982 free(cursors);
1983 RETURN_IF_ERR();
1985 /* FIXME: this is a buggy interface. The returned cursor
1986 contains internal references to the passed in cursors
1987 but does not hold python references to them or prevent
1988 them from being closed prematurely. This can cause
1989 python to crash when things are done in the wrong order. */
1990 return (PyObject*) newDBCursorObject(dbc, NULL, self);
1994 static PyObject*
1995 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1997 int err, flags=0;
1998 PyObject* txnobj = NULL;
1999 PyObject* keyobj;
2000 DBT key;
2001 DB_TXN *txn = NULL;
2002 DB_KEY_RANGE range;
2003 static char* kwnames[] = { "key", "txn", "flags", NULL };
2005 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
2006 &keyobj, &txnobj, &flags))
2007 return NULL;
2008 CHECK_DB_NOT_CLOSED(self);
2009 if (!make_dbt(keyobj, &key))
2010 /* BTree only, don't need to allow for an int key */
2011 return NULL;
2012 if (!checkTxnObj(txnobj, &txn))
2013 return NULL;
2015 MYDB_BEGIN_ALLOW_THREADS;
2016 err = self->db->key_range(self->db, txn, &key, &range, flags);
2017 MYDB_END_ALLOW_THREADS;
2019 RETURN_IF_ERR();
2020 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2024 static PyObject*
2025 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2027 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2028 char* filename = NULL;
2029 char* dbname = NULL;
2030 #if (DBVER >= 41)
2031 PyObject *txnobj = NULL;
2032 DB_TXN *txn = NULL;
2033 /* with dbname */
2034 static char* kwnames[] = {
2035 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2036 /* without dbname */
2037 static char* kwnames_basic[] = {
2038 "filename", "dbtype", "flags", "mode", "txn", NULL};
2039 #else
2040 /* with dbname */
2041 static char* kwnames[] = {
2042 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2043 /* without dbname */
2044 static char* kwnames_basic[] = {
2045 "filename", "dbtype", "flags", "mode", NULL};
2046 #endif
2048 #if (DBVER >= 41)
2049 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2050 &filename, &dbname, &type, &flags, &mode,
2051 &txnobj))
2052 #else
2053 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
2054 &filename, &dbname, &type, &flags,
2055 &mode))
2056 #endif
2058 PyErr_Clear();
2059 type = DB_UNKNOWN; flags = 0; mode = 0660;
2060 filename = NULL; dbname = NULL;
2061 #if (DBVER >= 41)
2062 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2063 kwnames_basic,
2064 &filename, &type, &flags, &mode,
2065 &txnobj))
2066 return NULL;
2067 #else
2068 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2069 kwnames_basic,
2070 &filename, &type, &flags, &mode))
2071 return NULL;
2072 #endif
2075 #if (DBVER >= 41)
2076 if (!checkTxnObj(txnobj, &txn)) return NULL;
2077 #endif
2079 if (NULL == self->db) {
2080 PyObject *t = Py_BuildValue("(is)", 0,
2081 "Cannot call open() twice for DB object");
2082 PyErr_SetObject(DBError, t);
2083 Py_DECREF(t);
2084 return NULL;
2087 #if (DBVER >= 41)
2088 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2089 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2090 self->txn=(DBTxnObject *)txnobj;
2091 } else {
2092 self->txn=NULL;
2094 #else
2095 self->txn=NULL;
2096 #endif
2098 MYDB_BEGIN_ALLOW_THREADS;
2099 #if (DBVER >= 41)
2100 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2101 #else
2102 err = self->db->open(self->db, filename, dbname, type, flags, mode);
2103 #endif
2104 MYDB_END_ALLOW_THREADS;
2105 if (makeDBError(err)) {
2106 PyObject *dummy;
2108 dummy=DB_close_internal(self,0);
2109 Py_XDECREF(dummy);
2110 return NULL;
2113 #if (DBVER >= 42)
2114 self->db->get_flags(self->db, &self->setflags);
2115 #endif
2117 self->flags = flags;
2119 RETURN_NONE();
2123 static PyObject*
2124 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2126 int flags=0;
2127 PyObject* txnobj = NULL;
2128 int dlen = -1;
2129 int doff = -1;
2130 PyObject* keyobj, *dataobj, *retval;
2131 DBT key, data;
2132 DB_TXN *txn = NULL;
2133 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
2134 "doff", NULL };
2136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2137 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2138 return NULL;
2140 CHECK_DB_NOT_CLOSED(self);
2141 if (!make_key_dbt(self, keyobj, &key, NULL))
2142 return NULL;
2143 if ( !make_dbt(dataobj, &data) ||
2144 !add_partial_dbt(&data, dlen, doff) ||
2145 !checkTxnObj(txnobj, &txn) )
2147 FREE_DBT(key);
2148 return NULL;
2151 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2152 FREE_DBT(key);
2153 return NULL;
2156 if (flags & DB_APPEND)
2157 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2158 else {
2159 retval = Py_None;
2160 Py_INCREF(retval);
2162 FREE_DBT(key);
2163 return retval;
2168 static PyObject*
2169 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2171 char* filename;
2172 char* database = NULL;
2173 int err, flags=0;
2174 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2176 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2177 &filename, &database, &flags))
2178 return NULL;
2179 CHECK_DB_NOT_CLOSED(self);
2181 err = self->db->remove(self->db, filename, database, flags);
2182 self->db = NULL;
2183 RETURN_IF_ERR();
2184 RETURN_NONE();
2189 static PyObject*
2190 DB_rename(DBObject* self, PyObject* args)
2192 char* filename;
2193 char* database;
2194 char* newname;
2195 int err, flags=0;
2197 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2198 &flags))
2199 return NULL;
2200 CHECK_DB_NOT_CLOSED(self);
2202 MYDB_BEGIN_ALLOW_THREADS;
2203 err = self->db->rename(self->db, filename, database, newname, flags);
2204 MYDB_END_ALLOW_THREADS;
2205 RETURN_IF_ERR();
2206 RETURN_NONE();
2210 static PyObject*
2211 DB_set_bt_minkey(DBObject* self, PyObject* args)
2213 int err, minkey;
2215 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2216 return NULL;
2217 CHECK_DB_NOT_CLOSED(self);
2219 MYDB_BEGIN_ALLOW_THREADS;
2220 err = self->db->set_bt_minkey(self->db, minkey);
2221 MYDB_END_ALLOW_THREADS;
2222 RETURN_IF_ERR();
2223 RETURN_NONE();
2226 #if (DBVER >= 33)
2227 static int
2228 _default_cmp(const DBT *leftKey,
2229 const DBT *rightKey)
2231 int res;
2232 int lsize = leftKey->size, rsize = rightKey->size;
2234 res = memcmp(leftKey->data, rightKey->data,
2235 lsize < rsize ? lsize : rsize);
2237 if (res == 0) {
2238 if (lsize < rsize) {
2239 res = -1;
2241 else if (lsize > rsize) {
2242 res = 1;
2245 return res;
2248 static int
2249 _db_compareCallback(DB* db,
2250 const DBT *leftKey,
2251 const DBT *rightKey)
2253 int res = 0;
2254 PyObject *args;
2255 PyObject *result = NULL;
2256 DBObject *self = (DBObject *)db->app_private;
2258 if (self == NULL || self->btCompareCallback == NULL) {
2259 MYDB_BEGIN_BLOCK_THREADS;
2260 PyErr_SetString(PyExc_TypeError,
2261 (self == 0
2262 ? "DB_bt_compare db is NULL."
2263 : "DB_bt_compare callback is NULL."));
2264 /* we're in a callback within the DB code, we can't raise */
2265 PyErr_Print();
2266 res = _default_cmp(leftKey, rightKey);
2267 MYDB_END_BLOCK_THREADS;
2268 } else {
2269 MYDB_BEGIN_BLOCK_THREADS;
2271 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
2272 if (args != NULL) {
2273 /* XXX(twouters) I highly doubt this INCREF is correct */
2274 Py_INCREF(self);
2275 result = PyEval_CallObject(self->btCompareCallback, args);
2277 if (args == NULL || result == NULL) {
2278 /* we're in a callback within the DB code, we can't raise */
2279 PyErr_Print();
2280 res = _default_cmp(leftKey, rightKey);
2281 } else if (PyInt_Check(result)) {
2282 res = PyInt_AsLong(result);
2283 } else {
2284 PyErr_SetString(PyExc_TypeError,
2285 "DB_bt_compare callback MUST return an int.");
2286 /* we're in a callback within the DB code, we can't raise */
2287 PyErr_Print();
2288 res = _default_cmp(leftKey, rightKey);
2291 Py_XDECREF(args);
2292 Py_XDECREF(result);
2294 MYDB_END_BLOCK_THREADS;
2296 return res;
2299 static PyObject*
2300 DB_set_bt_compare(DBObject* self, PyObject* args)
2302 int err;
2303 PyObject *comparator;
2304 PyObject *tuple, *result;
2306 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2307 return NULL;
2309 CHECK_DB_NOT_CLOSED(self);
2311 if (!PyCallable_Check(comparator)) {
2312 makeTypeError("Callable", comparator);
2313 return NULL;
2317 * Perform a test call of the comparator function with two empty
2318 * string objects here. verify that it returns an int (0).
2319 * err if not.
2321 tuple = Py_BuildValue("(ss)", "", "");
2322 result = PyEval_CallObject(comparator, tuple);
2323 Py_DECREF(tuple);
2324 if (result == NULL)
2325 return NULL;
2326 if (!PyInt_Check(result)) {
2327 PyErr_SetString(PyExc_TypeError,
2328 "callback MUST return an int");
2329 return NULL;
2330 } else if (PyInt_AsLong(result) != 0) {
2331 PyErr_SetString(PyExc_TypeError,
2332 "callback failed to return 0 on two empty strings");
2333 return NULL;
2335 Py_DECREF(result);
2337 /* We don't accept multiple set_bt_compare operations, in order to
2338 * simplify the code. This would have no real use, as one cannot
2339 * change the function once the db is opened anyway */
2340 if (self->btCompareCallback != NULL) {
2341 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2342 return NULL;
2345 Py_INCREF(comparator);
2346 self->btCompareCallback = comparator;
2348 /* This is to workaround a problem with un-initialized threads (see
2349 comment in DB_associate) */
2350 #ifdef WITH_THREAD
2351 PyEval_InitThreads();
2352 #endif
2354 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2356 if (err) {
2357 /* restore the old state in case of error */
2358 Py_DECREF(comparator);
2359 self->btCompareCallback = NULL;
2362 RETURN_IF_ERR();
2363 RETURN_NONE();
2365 #endif /* DBVER >= 33 */
2368 static PyObject*
2369 DB_set_cachesize(DBObject* self, PyObject* args)
2371 int err;
2372 int gbytes = 0, bytes = 0, ncache = 0;
2374 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2375 &gbytes,&bytes,&ncache))
2376 return NULL;
2377 CHECK_DB_NOT_CLOSED(self);
2379 MYDB_BEGIN_ALLOW_THREADS;
2380 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2381 MYDB_END_ALLOW_THREADS;
2382 RETURN_IF_ERR();
2383 RETURN_NONE();
2387 static PyObject*
2388 DB_set_flags(DBObject* self, PyObject* args)
2390 int err, flags;
2392 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2393 return NULL;
2394 CHECK_DB_NOT_CLOSED(self);
2396 MYDB_BEGIN_ALLOW_THREADS;
2397 err = self->db->set_flags(self->db, flags);
2398 MYDB_END_ALLOW_THREADS;
2399 RETURN_IF_ERR();
2401 self->setflags |= flags;
2402 RETURN_NONE();
2406 static PyObject*
2407 DB_set_h_ffactor(DBObject* self, PyObject* args)
2409 int err, ffactor;
2411 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2412 return NULL;
2413 CHECK_DB_NOT_CLOSED(self);
2415 MYDB_BEGIN_ALLOW_THREADS;
2416 err = self->db->set_h_ffactor(self->db, ffactor);
2417 MYDB_END_ALLOW_THREADS;
2418 RETURN_IF_ERR();
2419 RETURN_NONE();
2423 static PyObject*
2424 DB_set_h_nelem(DBObject* self, PyObject* args)
2426 int err, nelem;
2428 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2429 return NULL;
2430 CHECK_DB_NOT_CLOSED(self);
2432 MYDB_BEGIN_ALLOW_THREADS;
2433 err = self->db->set_h_nelem(self->db, nelem);
2434 MYDB_END_ALLOW_THREADS;
2435 RETURN_IF_ERR();
2436 RETURN_NONE();
2440 static PyObject*
2441 DB_set_lorder(DBObject* self, PyObject* args)
2443 int err, lorder;
2445 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2446 return NULL;
2447 CHECK_DB_NOT_CLOSED(self);
2449 MYDB_BEGIN_ALLOW_THREADS;
2450 err = self->db->set_lorder(self->db, lorder);
2451 MYDB_END_ALLOW_THREADS;
2452 RETURN_IF_ERR();
2453 RETURN_NONE();
2457 static PyObject*
2458 DB_set_pagesize(DBObject* self, PyObject* args)
2460 int err, pagesize;
2462 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2463 return NULL;
2464 CHECK_DB_NOT_CLOSED(self);
2466 MYDB_BEGIN_ALLOW_THREADS;
2467 err = self->db->set_pagesize(self->db, pagesize);
2468 MYDB_END_ALLOW_THREADS;
2469 RETURN_IF_ERR();
2470 RETURN_NONE();
2474 static PyObject*
2475 DB_set_re_delim(DBObject* self, PyObject* args)
2477 int err;
2478 char delim;
2480 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2481 PyErr_Clear();
2482 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2483 return NULL;
2486 CHECK_DB_NOT_CLOSED(self);
2488 MYDB_BEGIN_ALLOW_THREADS;
2489 err = self->db->set_re_delim(self->db, delim);
2490 MYDB_END_ALLOW_THREADS;
2491 RETURN_IF_ERR();
2492 RETURN_NONE();
2495 static PyObject*
2496 DB_set_re_len(DBObject* self, PyObject* args)
2498 int err, len;
2500 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2501 return NULL;
2502 CHECK_DB_NOT_CLOSED(self);
2504 MYDB_BEGIN_ALLOW_THREADS;
2505 err = self->db->set_re_len(self->db, len);
2506 MYDB_END_ALLOW_THREADS;
2507 RETURN_IF_ERR();
2508 RETURN_NONE();
2512 static PyObject*
2513 DB_set_re_pad(DBObject* self, PyObject* args)
2515 int err;
2516 char pad;
2518 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2519 PyErr_Clear();
2520 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2521 return NULL;
2523 CHECK_DB_NOT_CLOSED(self);
2525 MYDB_BEGIN_ALLOW_THREADS;
2526 err = self->db->set_re_pad(self->db, pad);
2527 MYDB_END_ALLOW_THREADS;
2528 RETURN_IF_ERR();
2529 RETURN_NONE();
2533 static PyObject*
2534 DB_set_re_source(DBObject* self, PyObject* args)
2536 int err;
2537 char *re_source;
2539 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2540 return NULL;
2541 CHECK_DB_NOT_CLOSED(self);
2543 MYDB_BEGIN_ALLOW_THREADS;
2544 err = self->db->set_re_source(self->db, re_source);
2545 MYDB_END_ALLOW_THREADS;
2546 RETURN_IF_ERR();
2547 RETURN_NONE();
2551 static PyObject*
2552 DB_set_q_extentsize(DBObject* self, PyObject* args)
2554 int err;
2555 int extentsize;
2557 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2558 return NULL;
2559 CHECK_DB_NOT_CLOSED(self);
2561 MYDB_BEGIN_ALLOW_THREADS;
2562 err = self->db->set_q_extentsize(self->db, extentsize);
2563 MYDB_END_ALLOW_THREADS;
2564 RETURN_IF_ERR();
2565 RETURN_NONE();
2568 static PyObject*
2569 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2571 int err, flags = 0, type;
2572 void* sp;
2573 PyObject* d;
2574 #if (DBVER >= 43)
2575 PyObject* txnobj = NULL;
2576 DB_TXN *txn = NULL;
2577 static char* kwnames[] = { "flags", "txn", NULL };
2578 #else
2579 static char* kwnames[] = { "flags", NULL };
2580 #endif
2582 #if (DBVER >= 43)
2583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2584 &flags, &txnobj))
2585 return NULL;
2586 if (!checkTxnObj(txnobj, &txn))
2587 return NULL;
2588 #else
2589 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2590 return NULL;
2591 #endif
2592 CHECK_DB_NOT_CLOSED(self);
2594 MYDB_BEGIN_ALLOW_THREADS;
2595 #if (DBVER >= 43)
2596 err = self->db->stat(self->db, txn, &sp, flags);
2597 #elif (DBVER >= 33)
2598 err = self->db->stat(self->db, &sp, flags);
2599 #else
2600 err = self->db->stat(self->db, &sp, NULL, flags);
2601 #endif
2602 MYDB_END_ALLOW_THREADS;
2603 RETURN_IF_ERR();
2605 self->haveStat = 1;
2607 /* Turn the stat structure into a dictionary */
2608 type = _DB_get_type(self);
2609 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2610 free(sp);
2611 return NULL;
2614 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2615 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2616 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2618 switch (type) {
2619 case DB_HASH:
2620 MAKE_HASH_ENTRY(magic);
2621 MAKE_HASH_ENTRY(version);
2622 MAKE_HASH_ENTRY(nkeys);
2623 MAKE_HASH_ENTRY(ndata);
2624 #if (DBVER >= 46)
2625 MAKE_HASH_ENTRY(pagecnt);
2626 #endif
2627 MAKE_HASH_ENTRY(pagesize);
2628 #if (DBVER < 41)
2629 MAKE_HASH_ENTRY(nelem);
2630 #endif
2631 MAKE_HASH_ENTRY(ffactor);
2632 MAKE_HASH_ENTRY(buckets);
2633 MAKE_HASH_ENTRY(free);
2634 MAKE_HASH_ENTRY(bfree);
2635 MAKE_HASH_ENTRY(bigpages);
2636 MAKE_HASH_ENTRY(big_bfree);
2637 MAKE_HASH_ENTRY(overflows);
2638 MAKE_HASH_ENTRY(ovfl_free);
2639 MAKE_HASH_ENTRY(dup);
2640 MAKE_HASH_ENTRY(dup_free);
2641 break;
2643 case DB_BTREE:
2644 case DB_RECNO:
2645 MAKE_BT_ENTRY(magic);
2646 MAKE_BT_ENTRY(version);
2647 MAKE_BT_ENTRY(nkeys);
2648 MAKE_BT_ENTRY(ndata);
2649 #if (DBVER >= 46)
2650 MAKE_BT_ENTRY(pagecnt);
2651 #endif
2652 MAKE_BT_ENTRY(pagesize);
2653 MAKE_BT_ENTRY(minkey);
2654 MAKE_BT_ENTRY(re_len);
2655 MAKE_BT_ENTRY(re_pad);
2656 MAKE_BT_ENTRY(levels);
2657 MAKE_BT_ENTRY(int_pg);
2658 MAKE_BT_ENTRY(leaf_pg);
2659 MAKE_BT_ENTRY(dup_pg);
2660 MAKE_BT_ENTRY(over_pg);
2661 #if (DBVER >= 43)
2662 MAKE_BT_ENTRY(empty_pg);
2663 #endif
2664 MAKE_BT_ENTRY(free);
2665 MAKE_BT_ENTRY(int_pgfree);
2666 MAKE_BT_ENTRY(leaf_pgfree);
2667 MAKE_BT_ENTRY(dup_pgfree);
2668 MAKE_BT_ENTRY(over_pgfree);
2669 break;
2671 case DB_QUEUE:
2672 MAKE_QUEUE_ENTRY(magic);
2673 MAKE_QUEUE_ENTRY(version);
2674 MAKE_QUEUE_ENTRY(nkeys);
2675 MAKE_QUEUE_ENTRY(ndata);
2676 MAKE_QUEUE_ENTRY(pagesize);
2677 #if (DBVER > 40)
2678 MAKE_QUEUE_ENTRY(extentsize);
2679 #endif
2680 MAKE_QUEUE_ENTRY(pages);
2681 MAKE_QUEUE_ENTRY(re_len);
2682 MAKE_QUEUE_ENTRY(re_pad);
2683 MAKE_QUEUE_ENTRY(pgfree);
2684 #if (DBVER == 31)
2685 MAKE_QUEUE_ENTRY(start);
2686 #endif
2687 MAKE_QUEUE_ENTRY(first_recno);
2688 MAKE_QUEUE_ENTRY(cur_recno);
2689 break;
2691 default:
2692 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2693 Py_DECREF(d);
2694 d = NULL;
2697 #undef MAKE_HASH_ENTRY
2698 #undef MAKE_BT_ENTRY
2699 #undef MAKE_QUEUE_ENTRY
2701 free(sp);
2702 return d;
2705 static PyObject*
2706 DB_sync(DBObject* self, PyObject* args)
2708 int err;
2709 int flags = 0;
2711 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2712 return NULL;
2713 CHECK_DB_NOT_CLOSED(self);
2715 MYDB_BEGIN_ALLOW_THREADS;
2716 err = self->db->sync(self->db, flags);
2717 MYDB_END_ALLOW_THREADS;
2718 RETURN_IF_ERR();
2719 RETURN_NONE();
2723 #if (DBVER >= 33)
2724 static PyObject*
2725 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2727 int err, flags=0;
2728 u_int32_t count=0;
2729 PyObject* txnobj = NULL;
2730 DB_TXN *txn = NULL;
2731 static char* kwnames[] = { "txn", "flags", NULL };
2733 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2734 &txnobj, &flags))
2735 return NULL;
2736 CHECK_DB_NOT_CLOSED(self);
2737 if (!checkTxnObj(txnobj, &txn))
2738 return NULL;
2740 MYDB_BEGIN_ALLOW_THREADS;
2741 err = self->db->truncate(self->db, txn, &count, flags);
2742 MYDB_END_ALLOW_THREADS;
2743 RETURN_IF_ERR();
2744 return PyInt_FromLong(count);
2746 #endif
2749 static PyObject*
2750 DB_upgrade(DBObject* self, PyObject* args)
2752 int err, flags=0;
2753 char *filename;
2755 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2756 return NULL;
2757 CHECK_DB_NOT_CLOSED(self);
2759 MYDB_BEGIN_ALLOW_THREADS;
2760 err = self->db->upgrade(self->db, filename, flags);
2761 MYDB_END_ALLOW_THREADS;
2762 RETURN_IF_ERR();
2763 RETURN_NONE();
2767 static PyObject*
2768 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2770 int err, flags=0;
2771 char* fileName;
2772 char* dbName=NULL;
2773 char* outFileName=NULL;
2774 FILE* outFile=NULL;
2775 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2776 NULL };
2778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2779 &fileName, &dbName, &outFileName, &flags))
2780 return NULL;
2782 CHECK_DB_NOT_CLOSED(self);
2783 if (outFileName)
2784 outFile = fopen(outFileName, "w");
2785 /* XXX(nnorwitz): it should probably be an exception if outFile
2786 can't be opened. */
2788 MYDB_BEGIN_ALLOW_THREADS;
2789 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2790 MYDB_END_ALLOW_THREADS;
2791 if (outFile)
2792 fclose(outFile);
2794 { /* DB.verify acts as a DB handle destructor (like close) */
2795 PyObject *error;
2797 error=DB_close_internal(self,0);
2798 if (error ) {
2799 return error;
2803 RETURN_IF_ERR();
2804 RETURN_NONE();
2808 static PyObject*
2809 DB_set_get_returns_none(DBObject* self, PyObject* args)
2811 int flags=0;
2812 int oldValue=0;
2814 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2815 return NULL;
2816 CHECK_DB_NOT_CLOSED(self);
2818 if (self->moduleFlags.getReturnsNone)
2819 ++oldValue;
2820 if (self->moduleFlags.cursorSetReturnsNone)
2821 ++oldValue;
2822 self->moduleFlags.getReturnsNone = (flags >= 1);
2823 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2824 return PyInt_FromLong(oldValue);
2827 #if (DBVER >= 41)
2828 static PyObject*
2829 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2831 int err;
2832 u_int32_t flags=0;
2833 char *passwd = NULL;
2834 static char* kwnames[] = { "passwd", "flags", NULL };
2836 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2837 &passwd, &flags)) {
2838 return NULL;
2841 MYDB_BEGIN_ALLOW_THREADS;
2842 err = self->db->set_encrypt(self->db, passwd, flags);
2843 MYDB_END_ALLOW_THREADS;
2845 RETURN_IF_ERR();
2846 RETURN_NONE();
2848 #endif /* DBVER >= 41 */
2851 /*-------------------------------------------------------------- */
2852 /* Mapping and Dictionary-like access routines */
2854 Py_ssize_t DB_length(PyObject* _self)
2856 int err;
2857 Py_ssize_t size = 0;
2858 int flags = 0;
2859 void* sp;
2860 DBObject* self = (DBObject*)_self;
2862 if (self->db == NULL) {
2863 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2864 PyErr_SetObject(DBError, t);
2865 Py_DECREF(t);
2866 return -1;
2869 if (self->haveStat) { /* Has the stat function been called recently? If
2870 so, we can use the cached value. */
2871 flags = DB_FAST_STAT;
2874 MYDB_BEGIN_ALLOW_THREADS;
2875 redo_stat_for_length:
2876 #if (DBVER >= 43)
2877 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2878 #elif (DBVER >= 33)
2879 err = self->db->stat(self->db, &sp, flags);
2880 #else
2881 err = self->db->stat(self->db, &sp, NULL, flags);
2882 #endif
2884 /* All the stat structures have matching fields upto the ndata field,
2885 so we can use any of them for the type cast */
2886 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2888 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
2889 * redo a full stat to make sure.
2890 * Fixes SF python bug 1493322, pybsddb bug 1184012
2892 if (size == 0 && (flags & DB_FAST_STAT)) {
2893 flags = 0;
2894 if (!err)
2895 free(sp);
2896 goto redo_stat_for_length;
2899 MYDB_END_ALLOW_THREADS;
2901 if (err)
2902 return -1;
2904 self->haveStat = 1;
2906 free(sp);
2907 return size;
2911 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2913 int err;
2914 PyObject* retval;
2915 DBT key;
2916 DBT data;
2918 CHECK_DB_NOT_CLOSED(self);
2919 if (!make_key_dbt(self, keyobj, &key, NULL))
2920 return NULL;
2922 CLEAR_DBT(data);
2923 if (CHECK_DBFLAG(self, DB_THREAD)) {
2924 /* Tell Berkeley DB to malloc the return value (thread safe) */
2925 data.flags = DB_DBT_MALLOC;
2927 MYDB_BEGIN_ALLOW_THREADS;
2928 err = self->db->get(self->db, NULL, &key, &data, 0);
2929 MYDB_END_ALLOW_THREADS;
2930 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2931 PyErr_SetObject(PyExc_KeyError, keyobj);
2932 retval = NULL;
2934 else if (makeDBError(err)) {
2935 retval = NULL;
2937 else {
2938 retval = Build_PyString(data.data, data.size);
2939 FREE_DBT(data);
2942 FREE_DBT(key);
2943 return retval;
2947 static int
2948 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2950 DBT key, data;
2951 int retval;
2952 int flags = 0;
2954 if (self->db == NULL) {
2955 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2956 PyErr_SetObject(DBError, t);
2957 Py_DECREF(t);
2958 return -1;
2961 if (!make_key_dbt(self, keyobj, &key, NULL))
2962 return -1;
2964 if (dataobj != NULL) {
2965 if (!make_dbt(dataobj, &data))
2966 retval = -1;
2967 else {
2968 if (self->setflags & (DB_DUP|DB_DUPSORT))
2969 /* dictionaries shouldn't have duplicate keys */
2970 flags = DB_NOOVERWRITE;
2971 retval = _DB_put(self, NULL, &key, &data, flags);
2973 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2974 /* try deleting any old record that matches and then PUT it
2975 * again... */
2976 _DB_delete(self, NULL, &key, 0);
2977 PyErr_Clear();
2978 retval = _DB_put(self, NULL, &key, &data, flags);
2982 else {
2983 /* dataobj == NULL, so delete the key */
2984 retval = _DB_delete(self, NULL, &key, 0);
2986 FREE_DBT(key);
2987 return retval;
2991 static PyObject*
2992 DB_has_key(DBObject* self, PyObject* args)
2994 int err;
2995 PyObject* keyobj;
2996 DBT key, data;
2997 PyObject* txnobj = NULL;
2998 DB_TXN *txn = NULL;
3000 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
3001 return NULL;
3002 CHECK_DB_NOT_CLOSED(self);
3003 if (!make_key_dbt(self, keyobj, &key, NULL))
3004 return NULL;
3005 if (!checkTxnObj(txnobj, &txn)) {
3006 FREE_DBT(key);
3007 return NULL;
3010 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
3011 it has a record but can't allocate a buffer for the data. This saves
3012 having to deal with data we won't be using.
3014 CLEAR_DBT(data);
3015 data.flags = DB_DBT_USERMEM;
3017 MYDB_BEGIN_ALLOW_THREADS;
3018 err = self->db->get(self->db, txn, &key, &data, 0);
3019 MYDB_END_ALLOW_THREADS;
3020 FREE_DBT(key);
3022 if (err == DB_BUFFER_SMALL || err == 0) {
3023 return PyInt_FromLong(1);
3024 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3025 return PyInt_FromLong(0);
3028 makeDBError(err);
3029 return NULL;
3033 #define _KEYS_LIST 1
3034 #define _VALUES_LIST 2
3035 #define _ITEMS_LIST 3
3037 static PyObject*
3038 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
3040 int err, dbtype;
3041 DBT key;
3042 DBT data;
3043 DBC *cursor;
3044 PyObject* list;
3045 PyObject* item = NULL;
3047 CHECK_DB_NOT_CLOSED(self);
3048 CLEAR_DBT(key);
3049 CLEAR_DBT(data);
3051 dbtype = _DB_get_type(self);
3052 if (dbtype == -1)
3053 return NULL;
3055 list = PyList_New(0);
3056 if (list == NULL)
3057 return NULL;
3059 /* get a cursor */
3060 MYDB_BEGIN_ALLOW_THREADS;
3061 err = self->db->cursor(self->db, txn, &cursor, 0);
3062 MYDB_END_ALLOW_THREADS;
3063 if (makeDBError(err)) {
3064 Py_DECREF(list);
3065 return NULL;
3068 while (1) { /* use the cursor to traverse the DB, collecting items */
3069 MYDB_BEGIN_ALLOW_THREADS;
3070 err = _DBC_get(cursor, &key, &data, DB_NEXT);
3071 MYDB_END_ALLOW_THREADS;
3073 if (err) {
3074 /* for any error, break out of the loop */
3075 break;
3078 switch (type) {
3079 case _KEYS_LIST:
3080 switch(dbtype) {
3081 case DB_BTREE:
3082 case DB_HASH:
3083 default:
3084 item = Build_PyString(key.data, key.size);
3085 break;
3086 case DB_RECNO:
3087 case DB_QUEUE:
3088 item = PyInt_FromLong(*((db_recno_t*)key.data));
3089 break;
3091 break;
3093 case _VALUES_LIST:
3094 item = Build_PyString(data.data, data.size);
3095 break;
3097 case _ITEMS_LIST:
3098 switch(dbtype) {
3099 case DB_BTREE:
3100 case DB_HASH:
3101 default:
3102 item = BuildValue_SS(key.data, key.size, data.data, data.size);
3103 break;
3104 case DB_RECNO:
3105 case DB_QUEUE:
3106 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3107 break;
3109 break;
3110 default:
3111 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3112 item = NULL;
3113 break;
3115 if (item == NULL) {
3116 Py_DECREF(list);
3117 list = NULL;
3118 goto done;
3120 PyList_Append(list, item);
3121 Py_DECREF(item);
3124 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3125 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
3126 Py_DECREF(list);
3127 list = NULL;
3130 done:
3131 MYDB_BEGIN_ALLOW_THREADS;
3132 _DBC_close(cursor);
3133 MYDB_END_ALLOW_THREADS;
3134 return list;
3138 static PyObject*
3139 DB_keys(DBObject* self, PyObject* args)
3141 PyObject* txnobj = NULL;
3142 DB_TXN *txn = NULL;
3144 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
3145 return NULL;
3146 if (!checkTxnObj(txnobj, &txn))
3147 return NULL;
3148 return _DB_make_list(self, txn, _KEYS_LIST);
3152 static PyObject*
3153 DB_items(DBObject* self, PyObject* args)
3155 PyObject* txnobj = NULL;
3156 DB_TXN *txn = NULL;
3158 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3159 return NULL;
3160 if (!checkTxnObj(txnobj, &txn))
3161 return NULL;
3162 return _DB_make_list(self, txn, _ITEMS_LIST);
3166 static PyObject*
3167 DB_values(DBObject* self, PyObject* args)
3169 PyObject* txnobj = NULL;
3170 DB_TXN *txn = NULL;
3172 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3173 return NULL;
3174 if (!checkTxnObj(txnobj, &txn))
3175 return NULL;
3176 return _DB_make_list(self, txn, _VALUES_LIST);
3179 /* --------------------------------------------------------------------- */
3180 /* DBCursor methods */
3183 static PyObject*
3184 DBC_close_internal(DBCursorObject* self)
3186 int err = 0;
3188 if (self->dbc != NULL) {
3189 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3190 if (self->txn) {
3191 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3192 self->txn=NULL;
3195 MYDB_BEGIN_ALLOW_THREADS;
3196 err = _DBC_close(self->dbc);
3197 MYDB_END_ALLOW_THREADS;
3198 self->dbc = NULL;
3200 RETURN_IF_ERR();
3201 RETURN_NONE();
3204 static PyObject*
3205 DBC_close(DBCursorObject* self, PyObject* args)
3207 if (!PyArg_ParseTuple(args, ":close"))
3208 return NULL;
3210 return DBC_close_internal(self);
3214 static PyObject*
3215 DBC_count(DBCursorObject* self, PyObject* args)
3217 int err = 0;
3218 db_recno_t count;
3219 int flags = 0;
3221 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3222 return NULL;
3224 CHECK_CURSOR_NOT_CLOSED(self);
3226 MYDB_BEGIN_ALLOW_THREADS;
3227 err = _DBC_count(self->dbc, &count, flags);
3228 MYDB_END_ALLOW_THREADS;
3229 RETURN_IF_ERR();
3231 return PyInt_FromLong(count);
3235 static PyObject*
3236 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3238 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3242 static PyObject*
3243 DBC_delete(DBCursorObject* self, PyObject* args)
3245 int err, flags=0;
3247 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3248 return NULL;
3250 CHECK_CURSOR_NOT_CLOSED(self);
3252 MYDB_BEGIN_ALLOW_THREADS;
3253 err = _DBC_del(self->dbc, flags);
3254 MYDB_END_ALLOW_THREADS;
3255 RETURN_IF_ERR();
3257 self->mydb->haveStat = 0;
3258 RETURN_NONE();
3262 static PyObject*
3263 DBC_dup(DBCursorObject* self, PyObject* args)
3265 int err, flags =0;
3266 DBC* dbc = NULL;
3268 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3269 return NULL;
3271 CHECK_CURSOR_NOT_CLOSED(self);
3273 MYDB_BEGIN_ALLOW_THREADS;
3274 err = _DBC_dup(self->dbc, &dbc, flags);
3275 MYDB_END_ALLOW_THREADS;
3276 RETURN_IF_ERR();
3278 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
3281 static PyObject*
3282 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3284 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3288 static PyObject*
3289 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3291 int err, flags=0;
3292 PyObject* keyobj = NULL;
3293 PyObject* dataobj = NULL;
3294 PyObject* retval = NULL;
3295 int dlen = -1;
3296 int doff = -1;
3297 DBT key, data;
3298 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3299 NULL };
3301 CLEAR_DBT(key);
3302 CLEAR_DBT(data);
3303 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3304 &flags, &dlen, &doff))
3306 PyErr_Clear();
3307 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3308 &kwnames[1],
3309 &keyobj, &flags, &dlen, &doff))
3311 PyErr_Clear();
3312 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3313 kwnames, &keyobj, &dataobj,
3314 &flags, &dlen, &doff))
3316 return NULL;
3321 CHECK_CURSOR_NOT_CLOSED(self);
3323 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3324 return NULL;
3325 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3326 (!add_partial_dbt(&data, dlen, doff)) )
3328 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3329 return NULL;
3332 MYDB_BEGIN_ALLOW_THREADS;
3333 err = _DBC_get(self->dbc, &key, &data, flags);
3334 MYDB_END_ALLOW_THREADS;
3336 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3337 && self->mydb->moduleFlags.getReturnsNone) {
3338 Py_INCREF(Py_None);
3339 retval = Py_None;
3341 else if (makeDBError(err)) {
3342 retval = NULL;
3344 else {
3345 switch (_DB_get_type(self->mydb)) {
3346 case -1:
3347 retval = NULL;
3348 break;
3349 case DB_BTREE:
3350 case DB_HASH:
3351 default:
3352 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3353 break;
3354 case DB_RECNO:
3355 case DB_QUEUE:
3356 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3357 break;
3360 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3361 return retval;
3364 #if (DBVER >= 33)
3365 static PyObject*
3366 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3368 int err, flags=0;
3369 PyObject* keyobj = NULL;
3370 PyObject* dataobj = NULL;
3371 PyObject* retval = NULL;
3372 int dlen = -1;
3373 int doff = -1;
3374 DBT key, pkey, data;
3375 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3376 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3378 CLEAR_DBT(key);
3379 CLEAR_DBT(data);
3380 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3381 &flags, &dlen, &doff))
3383 PyErr_Clear();
3384 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3385 kwnames_keyOnly,
3386 &keyobj, &flags, &dlen, &doff))
3388 PyErr_Clear();
3389 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3390 kwnames, &keyobj, &dataobj,
3391 &flags, &dlen, &doff))
3393 return NULL;
3398 CHECK_CURSOR_NOT_CLOSED(self);
3400 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3401 return NULL;
3402 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3403 (!add_partial_dbt(&data, dlen, doff)) ) {
3404 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3405 return NULL;
3408 CLEAR_DBT(pkey);
3409 pkey.flags = DB_DBT_MALLOC;
3411 MYDB_BEGIN_ALLOW_THREADS;
3412 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
3413 MYDB_END_ALLOW_THREADS;
3415 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3416 && self->mydb->moduleFlags.getReturnsNone) {
3417 Py_INCREF(Py_None);
3418 retval = Py_None;
3420 else if (makeDBError(err)) {
3421 retval = NULL;
3423 else {
3424 PyObject *pkeyObj;
3425 PyObject *dataObj;
3426 dataObj = Build_PyString(data.data, data.size);
3428 if (self->mydb->primaryDBType == DB_RECNO ||
3429 self->mydb->primaryDBType == DB_QUEUE)
3430 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3431 else
3432 pkeyObj = Build_PyString(pkey.data, pkey.size);
3434 if (key.data && key.size) /* return key, pkey and data */
3436 PyObject *keyObj;
3437 int type = _DB_get_type(self->mydb);
3438 if (type == DB_RECNO || type == DB_QUEUE)
3439 keyObj = PyInt_FromLong(*(int *)key.data);
3440 else
3441 keyObj = Build_PyString(key.data, key.size);
3442 #if (PY_VERSION_HEX >= 0x02040000)
3443 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3444 #else
3445 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3446 #endif
3447 Py_DECREF(keyObj);
3448 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3450 else /* return just the pkey and data */
3452 #if (PY_VERSION_HEX >= 0x02040000)
3453 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3454 #else
3455 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3456 #endif
3458 Py_DECREF(dataObj);
3459 Py_DECREF(pkeyObj);
3460 FREE_DBT(pkey);
3462 /* the only time REALLOC should be set is if we used an integer
3463 * key that make_key_dbt malloc'd for us. always free these. */
3464 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
3465 FREE_DBT(key);
3467 return retval;
3469 #endif
3472 static PyObject*
3473 DBC_get_recno(DBCursorObject* self, PyObject* args)
3475 int err;
3476 db_recno_t recno;
3477 DBT key;
3478 DBT data;
3480 if (!PyArg_ParseTuple(args, ":get_recno"))
3481 return NULL;
3483 CHECK_CURSOR_NOT_CLOSED(self);
3485 CLEAR_DBT(key);
3486 CLEAR_DBT(data);
3488 MYDB_BEGIN_ALLOW_THREADS;
3489 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
3490 MYDB_END_ALLOW_THREADS;
3491 RETURN_IF_ERR();
3493 recno = *((db_recno_t*)data.data);
3494 return PyInt_FromLong(recno);
3498 static PyObject*
3499 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3501 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3505 static PyObject*
3506 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3508 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3512 static PyObject*
3513 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3515 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3519 static PyObject*
3520 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3522 int err, flags = 0;
3523 PyObject* keyobj, *dataobj;
3524 DBT key, data;
3525 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3526 NULL };
3527 int dlen = -1;
3528 int doff = -1;
3530 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3531 &keyobj, &dataobj, &flags, &dlen, &doff))
3532 return NULL;
3534 CHECK_CURSOR_NOT_CLOSED(self);
3536 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3537 return NULL;
3538 if (!make_dbt(dataobj, &data) ||
3539 !add_partial_dbt(&data, dlen, doff) )
3541 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3542 return NULL;
3545 MYDB_BEGIN_ALLOW_THREADS;
3546 err = _DBC_put(self->dbc, &key, &data, flags);
3547 MYDB_END_ALLOW_THREADS;
3548 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3549 RETURN_IF_ERR();
3550 self->mydb->haveStat = 0;
3551 RETURN_NONE();
3555 static PyObject*
3556 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3558 int err, flags = 0;
3559 DBT key, data;
3560 PyObject* retval, *keyobj;
3561 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3562 int dlen = -1;
3563 int doff = -1;
3565 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3566 &keyobj, &flags, &dlen, &doff))
3567 return NULL;
3569 CHECK_CURSOR_NOT_CLOSED(self);
3571 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3572 return NULL;
3574 CLEAR_DBT(data);
3575 if (!add_partial_dbt(&data, dlen, doff)) {
3576 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3577 return NULL;
3580 MYDB_BEGIN_ALLOW_THREADS;
3581 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
3582 MYDB_END_ALLOW_THREADS;
3583 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3584 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3585 Py_INCREF(Py_None);
3586 retval = Py_None;
3588 else if (makeDBError(err)) {
3589 retval = NULL;
3591 else {
3592 switch (_DB_get_type(self->mydb)) {
3593 case -1:
3594 retval = NULL;
3595 break;
3596 case DB_BTREE:
3597 case DB_HASH:
3598 default:
3599 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3600 break;
3601 case DB_RECNO:
3602 case DB_QUEUE:
3603 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3604 break;
3606 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3608 /* the only time REALLOC should be set is if we used an integer
3609 * key that make_key_dbt malloc'd for us. always free these. */
3610 if (key.flags & DB_DBT_REALLOC) {
3611 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3614 return retval;
3618 static PyObject*
3619 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3621 int err, flags = 0;
3622 DBT key, data;
3623 PyObject* retval, *keyobj;
3624 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3625 int dlen = -1;
3626 int doff = -1;
3628 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3629 &keyobj, &flags, &dlen, &doff))
3630 return NULL;
3632 CHECK_CURSOR_NOT_CLOSED(self);
3634 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3635 return NULL;
3637 CLEAR_DBT(data);
3638 if (!add_partial_dbt(&data, dlen, doff)) {
3639 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3640 return NULL;
3642 MYDB_BEGIN_ALLOW_THREADS;
3643 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3644 MYDB_END_ALLOW_THREADS;
3645 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3646 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3647 Py_INCREF(Py_None);
3648 retval = Py_None;
3650 else if (makeDBError(err)) {
3651 retval = NULL;
3653 else {
3654 switch (_DB_get_type(self->mydb)) {
3655 case -1:
3656 retval = NULL;
3657 break;
3658 case DB_BTREE:
3659 case DB_HASH:
3660 default:
3661 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3662 break;
3663 case DB_RECNO:
3664 case DB_QUEUE:
3665 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3666 break;
3668 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3670 /* the only time REALLOC should be set is if we used an integer
3671 * key that make_key_dbt malloc'd for us. always free these. */
3672 if (key.flags & DB_DBT_REALLOC) {
3673 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3676 return retval;
3679 static PyObject*
3680 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3681 int flags, unsigned int returnsNone)
3683 int err;
3684 DBT key, data;
3685 PyObject* retval;
3687 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3688 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3689 return NULL;
3690 if (!make_dbt(dataobj, &data)) {
3691 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3692 return NULL;
3695 MYDB_BEGIN_ALLOW_THREADS;
3696 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3697 MYDB_END_ALLOW_THREADS;
3698 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3699 Py_INCREF(Py_None);
3700 retval = Py_None;
3702 else if (makeDBError(err)) {
3703 retval = NULL;
3705 else {
3706 switch (_DB_get_type(self->mydb)) {
3707 case -1:
3708 retval = NULL;
3709 break;
3710 case DB_BTREE:
3711 case DB_HASH:
3712 default:
3713 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3714 break;
3715 case DB_RECNO:
3716 case DB_QUEUE:
3717 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
3718 break;
3722 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
3723 return retval;
3726 static PyObject*
3727 DBC_get_both(DBCursorObject* self, PyObject* args)
3729 int flags=0;
3730 PyObject *keyobj, *dataobj;
3732 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3733 return NULL;
3735 /* if the cursor is closed, self->mydb may be invalid */
3736 CHECK_CURSOR_NOT_CLOSED(self);
3738 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3739 self->mydb->moduleFlags.getReturnsNone);
3742 /* Return size of entry */
3743 static PyObject*
3744 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3746 int err, flags=DB_CURRENT;
3747 PyObject* retval = NULL;
3748 DBT key, data;
3750 if (!PyArg_ParseTuple(args, ":get_current_size"))
3751 return NULL;
3752 CHECK_CURSOR_NOT_CLOSED(self);
3753 CLEAR_DBT(key);
3754 CLEAR_DBT(data);
3756 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3757 getting the record size. */
3758 data.flags = DB_DBT_USERMEM;
3759 data.ulen = 0;
3760 MYDB_BEGIN_ALLOW_THREADS;
3761 err = _DBC_get(self->dbc, &key, &data, flags);
3762 MYDB_END_ALLOW_THREADS;
3763 if (err == DB_BUFFER_SMALL || !err) {
3764 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3765 retval = PyInt_FromLong((long)data.size);
3766 err = 0;
3769 RETURN_IF_ERR();
3770 return retval;
3773 static PyObject*
3774 DBC_set_both(DBCursorObject* self, PyObject* args)
3776 int flags=0;
3777 PyObject *keyobj, *dataobj;
3779 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3780 return NULL;
3782 /* if the cursor is closed, self->mydb may be invalid */
3783 CHECK_CURSOR_NOT_CLOSED(self);
3785 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3786 self->mydb->moduleFlags.cursorSetReturnsNone);
3790 static PyObject*
3791 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3793 int err, irecno, flags=0;
3794 db_recno_t recno;
3795 DBT key, data;
3796 PyObject* retval;
3797 int dlen = -1;
3798 int doff = -1;
3799 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3802 &irecno, &flags, &dlen, &doff))
3803 return NULL;
3805 CHECK_CURSOR_NOT_CLOSED(self);
3807 CLEAR_DBT(key);
3808 recno = (db_recno_t) irecno;
3809 /* use allocated space so DB will be able to realloc room for the real
3810 * key */
3811 key.data = malloc(sizeof(db_recno_t));
3812 if (key.data == NULL) {
3813 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3814 return NULL;
3816 key.size = sizeof(db_recno_t);
3817 key.ulen = key.size;
3818 memcpy(key.data, &recno, sizeof(db_recno_t));
3819 key.flags = DB_DBT_REALLOC;
3821 CLEAR_DBT(data);
3822 if (!add_partial_dbt(&data, dlen, doff)) {
3823 FREE_DBT(key);
3824 return NULL;
3827 MYDB_BEGIN_ALLOW_THREADS;
3828 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3829 MYDB_END_ALLOW_THREADS;
3830 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3831 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3832 Py_INCREF(Py_None);
3833 retval = Py_None;
3835 else if (makeDBError(err)) {
3836 retval = NULL;
3838 else { /* Can only be used for BTrees, so no need to return int key */
3839 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
3841 FREE_DBT(key);
3843 return retval;
3847 static PyObject*
3848 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3850 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3854 static PyObject*
3855 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3857 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3861 static PyObject*
3862 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3864 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3868 static PyObject*
3869 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3871 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3875 static PyObject*
3876 DBC_join_item(DBCursorObject* self, PyObject* args)
3878 int err, flags=0;
3879 DBT key, data;
3880 PyObject* retval;
3882 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3883 return NULL;
3885 CHECK_CURSOR_NOT_CLOSED(self);
3887 CLEAR_DBT(key);
3888 CLEAR_DBT(data);
3890 MYDB_BEGIN_ALLOW_THREADS;
3891 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3892 MYDB_END_ALLOW_THREADS;
3893 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3894 && self->mydb->moduleFlags.getReturnsNone) {
3895 Py_INCREF(Py_None);
3896 retval = Py_None;
3898 else if (makeDBError(err)) {
3899 retval = NULL;
3901 else {
3902 retval = BuildValue_S(key.data, key.size);
3905 return retval;
3910 /* --------------------------------------------------------------------- */
3911 /* DBEnv methods */
3914 static PyObject*
3915 DBEnv_close_internal(DBEnvObject* self, int flags)
3917 PyObject *dummy;
3918 int err;
3920 if (!self->closed) { /* Don't close more than once */
3921 while(self->children_txns) {
3922 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3923 Py_XDECREF(dummy);
3925 while(self->children_dbs) {
3926 dummy=DB_close_internal(self->children_dbs,0);
3927 Py_XDECREF(dummy);
3930 MYDB_BEGIN_ALLOW_THREADS;
3931 err = self->db_env->close(self->db_env, flags);
3932 MYDB_END_ALLOW_THREADS;
3933 /* after calling DBEnv->close, regardless of error, this DBEnv
3934 * may not be accessed again (Berkeley DB docs). */
3935 self->closed = 1;
3936 self->db_env = NULL;
3937 RETURN_IF_ERR();
3939 RETURN_NONE();
3942 static PyObject*
3943 DBEnv_close(DBEnvObject* self, PyObject* args)
3945 int flags = 0;
3947 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3948 return NULL;
3949 return DBEnv_close_internal(self,flags);
3953 static PyObject*
3954 DBEnv_open(DBEnvObject* self, PyObject* args)
3956 int err, flags=0, mode=0660;
3957 char *db_home;
3959 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3960 return NULL;
3962 CHECK_ENV_NOT_CLOSED(self);
3964 MYDB_BEGIN_ALLOW_THREADS;
3965 err = self->db_env->open(self->db_env, db_home, flags, mode);
3966 MYDB_END_ALLOW_THREADS;
3967 RETURN_IF_ERR();
3968 self->closed = 0;
3969 self->flags = flags;
3970 RETURN_NONE();
3974 static PyObject*
3975 DBEnv_remove(DBEnvObject* self, PyObject* args)
3977 int err, flags=0;
3978 char *db_home;
3980 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3983 MYDB_BEGIN_ALLOW_THREADS;
3984 err = self->db_env->remove(self->db_env, db_home, flags);
3985 MYDB_END_ALLOW_THREADS;
3986 RETURN_IF_ERR();
3987 RETURN_NONE();
3990 #if (DBVER >= 41)
3991 static PyObject*
3992 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3994 int err;
3995 u_int32_t flags=0;
3996 char *file = NULL;
3997 char *database = NULL;
3998 PyObject *txnobj = NULL;
3999 DB_TXN *txn = NULL;
4000 static char* kwnames[] = { "file", "database", "txn", "flags",
4001 NULL };
4003 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
4004 &file, &database, &txnobj, &flags)) {
4005 return NULL;
4007 if (!checkTxnObj(txnobj, &txn)) {
4008 return NULL;
4010 CHECK_ENV_NOT_CLOSED(self);
4011 MYDB_BEGIN_ALLOW_THREADS;
4012 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4013 MYDB_END_ALLOW_THREADS;
4014 RETURN_IF_ERR();
4015 RETURN_NONE();
4018 static PyObject*
4019 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4021 int err;
4022 u_int32_t flags=0;
4023 char *file = NULL;
4024 char *database = NULL;
4025 char *newname = NULL;
4026 PyObject *txnobj = NULL;
4027 DB_TXN *txn = NULL;
4028 static char* kwnames[] = { "file", "database", "newname", "txn",
4029 "flags", NULL };
4031 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
4032 &file, &database, &newname, &txnobj, &flags)) {
4033 return NULL;
4035 if (!checkTxnObj(txnobj, &txn)) {
4036 return NULL;
4038 CHECK_ENV_NOT_CLOSED(self);
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4041 flags);
4042 MYDB_END_ALLOW_THREADS;
4043 RETURN_IF_ERR();
4044 RETURN_NONE();
4047 static PyObject*
4048 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4050 int err;
4051 u_int32_t flags=0;
4052 char *passwd = NULL;
4053 static char* kwnames[] = { "passwd", "flags", NULL };
4055 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4056 &passwd, &flags)) {
4057 return NULL;
4060 MYDB_BEGIN_ALLOW_THREADS;
4061 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4062 MYDB_END_ALLOW_THREADS;
4064 RETURN_IF_ERR();
4065 RETURN_NONE();
4067 #endif /* DBVER >= 41 */
4069 #if (DBVER >= 40)
4070 static PyObject*
4071 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4073 int err;
4074 u_int32_t flags=0;
4075 u_int32_t timeout = 0;
4076 static char* kwnames[] = { "timeout", "flags", NULL };
4078 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4079 &timeout, &flags)) {
4080 return NULL;
4083 MYDB_BEGIN_ALLOW_THREADS;
4084 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4085 MYDB_END_ALLOW_THREADS;
4087 RETURN_IF_ERR();
4088 RETURN_NONE();
4090 #endif /* DBVER >= 40 */
4092 static PyObject*
4093 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4095 int err;
4096 long shm_key = 0;
4098 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4099 return NULL;
4100 CHECK_ENV_NOT_CLOSED(self);
4102 err = self->db_env->set_shm_key(self->db_env, shm_key);
4103 RETURN_IF_ERR();
4104 RETURN_NONE();
4107 static PyObject*
4108 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4110 int err, gbytes=0, bytes=0, ncache=0;
4112 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4113 &gbytes, &bytes, &ncache))
4114 return NULL;
4115 CHECK_ENV_NOT_CLOSED(self);
4117 MYDB_BEGIN_ALLOW_THREADS;
4118 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4119 MYDB_END_ALLOW_THREADS;
4120 RETURN_IF_ERR();
4121 RETURN_NONE();
4125 static PyObject*
4126 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4128 int err, flags=0, onoff=0;
4130 if (!PyArg_ParseTuple(args, "ii:set_flags",
4131 &flags, &onoff))
4132 return NULL;
4133 CHECK_ENV_NOT_CLOSED(self);
4135 MYDB_BEGIN_ALLOW_THREADS;
4136 err = self->db_env->set_flags(self->db_env, flags, onoff);
4137 MYDB_END_ALLOW_THREADS;
4138 RETURN_IF_ERR();
4139 RETURN_NONE();
4143 #if (DBVER >= 47)
4144 static PyObject*
4145 DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4147 int err, flags, onoff;
4149 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4150 &flags, &onoff))
4151 return NULL;
4152 CHECK_ENV_NOT_CLOSED(self);
4154 MYDB_BEGIN_ALLOW_THREADS;
4155 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4156 MYDB_END_ALLOW_THREADS;
4157 RETURN_IF_ERR();
4158 RETURN_NONE();
4160 #endif /* DBVER >= 47 */
4163 static PyObject*
4164 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4166 int err;
4167 char *dir;
4169 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4170 return NULL;
4171 CHECK_ENV_NOT_CLOSED(self);
4173 MYDB_BEGIN_ALLOW_THREADS;
4174 err = self->db_env->set_data_dir(self->db_env, dir);
4175 MYDB_END_ALLOW_THREADS;
4176 RETURN_IF_ERR();
4177 RETURN_NONE();
4181 static PyObject*
4182 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4184 int err, lg_bsize;
4186 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4187 return NULL;
4188 CHECK_ENV_NOT_CLOSED(self);
4190 MYDB_BEGIN_ALLOW_THREADS;
4191 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4192 MYDB_END_ALLOW_THREADS;
4193 RETURN_IF_ERR();
4194 RETURN_NONE();
4198 static PyObject*
4199 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4201 int err;
4202 char *dir;
4204 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4205 return NULL;
4206 CHECK_ENV_NOT_CLOSED(self);
4208 MYDB_BEGIN_ALLOW_THREADS;
4209 err = self->db_env->set_lg_dir(self->db_env, dir);
4210 MYDB_END_ALLOW_THREADS;
4211 RETURN_IF_ERR();
4212 RETURN_NONE();
4215 static PyObject*
4216 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4218 int err, lg_max;
4220 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4221 return NULL;
4222 CHECK_ENV_NOT_CLOSED(self);
4224 MYDB_BEGIN_ALLOW_THREADS;
4225 err = self->db_env->set_lg_max(self->db_env, lg_max);
4226 MYDB_END_ALLOW_THREADS;
4227 RETURN_IF_ERR();
4228 RETURN_NONE();
4231 #if (DBVER >= 42)
4232 static PyObject*
4233 DBEnv_get_lg_max(DBEnvObject* self, PyObject* args)
4235 int err;
4236 u_int32_t lg_max;
4238 if (!PyArg_ParseTuple(args, ":get_lg_max"))
4239 return NULL;
4240 CHECK_ENV_NOT_CLOSED(self);
4242 MYDB_BEGIN_ALLOW_THREADS;
4243 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4244 MYDB_END_ALLOW_THREADS;
4245 RETURN_IF_ERR();
4246 return PyInt_FromLong(lg_max);
4248 #endif
4251 #if (DBVER >= 33)
4252 static PyObject*
4253 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4255 int err, lg_max;
4257 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4258 return NULL;
4259 CHECK_ENV_NOT_CLOSED(self);
4261 MYDB_BEGIN_ALLOW_THREADS;
4262 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4263 MYDB_END_ALLOW_THREADS;
4264 RETURN_IF_ERR();
4265 RETURN_NONE();
4267 #endif
4270 static PyObject*
4271 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4273 int err, lk_detect;
4275 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4276 return NULL;
4277 CHECK_ENV_NOT_CLOSED(self);
4279 MYDB_BEGIN_ALLOW_THREADS;
4280 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4281 MYDB_END_ALLOW_THREADS;
4282 RETURN_IF_ERR();
4283 RETURN_NONE();
4287 #if (DBVER < 45)
4288 static PyObject*
4289 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4291 int err, max;
4293 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4294 return NULL;
4295 CHECK_ENV_NOT_CLOSED(self);
4297 MYDB_BEGIN_ALLOW_THREADS;
4298 err = self->db_env->set_lk_max(self->db_env, max);
4299 MYDB_END_ALLOW_THREADS;
4300 RETURN_IF_ERR();
4301 RETURN_NONE();
4303 #endif
4307 static PyObject*
4308 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4310 int err, max;
4312 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4313 return NULL;
4314 CHECK_ENV_NOT_CLOSED(self);
4316 MYDB_BEGIN_ALLOW_THREADS;
4317 err = self->db_env->set_lk_max_locks(self->db_env, max);
4318 MYDB_END_ALLOW_THREADS;
4319 RETURN_IF_ERR();
4320 RETURN_NONE();
4324 static PyObject*
4325 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4327 int err, max;
4329 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4330 return NULL;
4331 CHECK_ENV_NOT_CLOSED(self);
4333 MYDB_BEGIN_ALLOW_THREADS;
4334 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4335 MYDB_END_ALLOW_THREADS;
4336 RETURN_IF_ERR();
4337 RETURN_NONE();
4341 static PyObject*
4342 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4344 int err, max;
4346 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4347 return NULL;
4348 CHECK_ENV_NOT_CLOSED(self);
4350 MYDB_BEGIN_ALLOW_THREADS;
4351 err = self->db_env->set_lk_max_objects(self->db_env, max);
4352 MYDB_END_ALLOW_THREADS;
4353 RETURN_IF_ERR();
4354 RETURN_NONE();
4358 static PyObject*
4359 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4361 int err, mp_mmapsize;
4363 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4364 return NULL;
4365 CHECK_ENV_NOT_CLOSED(self);
4367 MYDB_BEGIN_ALLOW_THREADS;
4368 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4369 MYDB_END_ALLOW_THREADS;
4370 RETURN_IF_ERR();
4371 RETURN_NONE();
4375 static PyObject*
4376 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4378 int err;
4379 char *dir;
4381 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4382 return NULL;
4383 CHECK_ENV_NOT_CLOSED(self);
4385 MYDB_BEGIN_ALLOW_THREADS;
4386 err = self->db_env->set_tmp_dir(self->db_env, dir);
4387 MYDB_END_ALLOW_THREADS;
4388 RETURN_IF_ERR();
4389 RETURN_NONE();
4393 #if (DBVER >= 40)
4394 static PyObject*
4395 DBEnv_txn_recover(DBEnvObject* self, PyObject* args)
4397 int flags = DB_FIRST;
4398 int err, i;
4399 PyObject *list, *tuple, *gid;
4400 DBTxnObject *txn;
4401 #define PREPLIST_LEN 16
4402 DB_PREPLIST preplist[PREPLIST_LEN];
4403 long retp;
4405 if (!PyArg_ParseTuple(args, ":txn_recover"))
4406 return NULL;
4408 CHECK_ENV_NOT_CLOSED(self);
4410 list=PyList_New(0);
4411 if (!list)
4412 return NULL;
4413 while (!0) {
4414 MYDB_BEGIN_ALLOW_THREADS
4415 err=self->db_env->txn_recover(self->db_env,
4416 preplist, PREPLIST_LEN, &retp, flags);
4417 #undef PREPLIST_LEN
4418 MYDB_END_ALLOW_THREADS
4419 if (err) {
4420 Py_DECREF(list);
4421 RETURN_IF_ERR();
4423 if (!retp) break;
4424 flags=DB_NEXT; /* Prepare for next loop pass */
4425 for (i=0; i<retp; i++) {
4426 gid=PyBytes_FromStringAndSize((char *)(preplist[i].gid),
4427 DB_XIDDATASIZE);
4428 if (!gid) {
4429 Py_DECREF(list);
4430 return NULL;
4432 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4433 if (!txn) {
4434 Py_DECREF(list);
4435 Py_DECREF(gid);
4436 return NULL;
4438 txn->flag_prepare=1; /* Recover state */
4439 tuple=PyTuple_New(2);
4440 if (!tuple) {
4441 Py_DECREF(list);
4442 Py_DECREF(gid);
4443 Py_DECREF(txn);
4444 return NULL;
4446 if (PyTuple_SetItem(tuple, 0, gid)) {
4447 Py_DECREF(list);
4448 Py_DECREF(gid);
4449 Py_DECREF(txn);
4450 Py_DECREF(tuple);
4451 return NULL;
4453 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4454 Py_DECREF(list);
4455 Py_DECREF(txn);
4456 Py_DECREF(tuple); /* This delete the "gid" also */
4457 return NULL;
4459 if (PyList_Append(list, tuple)) {
4460 Py_DECREF(list);
4461 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4462 return NULL;
4464 Py_DECREF(tuple);
4467 return list;
4469 #endif
4471 static PyObject*
4472 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4474 int flags = 0;
4475 PyObject* txnobj = NULL;
4476 DB_TXN *txn = NULL;
4477 static char* kwnames[] = { "parent", "flags", NULL };
4479 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4480 &txnobj, &flags))
4481 return NULL;
4483 if (!checkTxnObj(txnobj, &txn))
4484 return NULL;
4485 CHECK_ENV_NOT_CLOSED(self);
4487 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
4491 static PyObject*
4492 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4494 int err, kbyte=0, min=0, flags=0;
4496 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4497 return NULL;
4498 CHECK_ENV_NOT_CLOSED(self);
4500 MYDB_BEGIN_ALLOW_THREADS;
4501 #if (DBVER >= 40)
4502 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4503 #else
4504 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4505 #endif
4506 MYDB_END_ALLOW_THREADS;
4507 RETURN_IF_ERR();
4508 RETURN_NONE();
4512 static PyObject*
4513 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4515 int err, max;
4517 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4518 return NULL;
4519 CHECK_ENV_NOT_CLOSED(self);
4521 err = self->db_env->set_tx_max(self->db_env, max);
4522 RETURN_IF_ERR();
4523 RETURN_NONE();
4527 static PyObject*
4528 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4530 int err;
4531 long stamp;
4532 time_t timestamp;
4534 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4535 return NULL;
4536 CHECK_ENV_NOT_CLOSED(self);
4537 timestamp = (time_t)stamp;
4538 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4539 RETURN_IF_ERR();
4540 RETURN_NONE();
4544 static PyObject*
4545 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4547 int err, atype, flags=0;
4548 int aborted = 0;
4550 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4551 return NULL;
4552 CHECK_ENV_NOT_CLOSED(self);
4554 MYDB_BEGIN_ALLOW_THREADS;
4555 #if (DBVER >= 40)
4556 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4557 #else
4558 err = lock_detect(self->db_env, flags, atype, &aborted);
4559 #endif
4560 MYDB_END_ALLOW_THREADS;
4561 RETURN_IF_ERR();
4562 return PyInt_FromLong(aborted);
4566 static PyObject*
4567 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4569 int flags=0;
4570 int locker, lock_mode;
4571 DBT obj;
4572 PyObject* objobj;
4574 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4575 return NULL;
4578 if (!make_dbt(objobj, &obj))
4579 return NULL;
4581 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4585 static PyObject*
4586 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4588 int err;
4589 u_int32_t theID;
4591 if (!PyArg_ParseTuple(args, ":lock_id"))
4592 return NULL;
4594 CHECK_ENV_NOT_CLOSED(self);
4595 MYDB_BEGIN_ALLOW_THREADS;
4596 #if (DBVER >= 40)
4597 err = self->db_env->lock_id(self->db_env, &theID);
4598 #else
4599 err = lock_id(self->db_env, &theID);
4600 #endif
4601 MYDB_END_ALLOW_THREADS;
4602 RETURN_IF_ERR();
4604 return PyInt_FromLong((long)theID);
4607 #if (DBVER >= 40)
4608 static PyObject*
4609 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4611 int err;
4612 u_int32_t theID;
4614 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4615 return NULL;
4617 CHECK_ENV_NOT_CLOSED(self);
4618 MYDB_BEGIN_ALLOW_THREADS;
4619 err = self->db_env->lock_id_free(self->db_env, theID);
4620 MYDB_END_ALLOW_THREADS;
4621 RETURN_IF_ERR();
4622 RETURN_NONE();
4624 #endif
4626 static PyObject*
4627 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4629 int err;
4630 DBLockObject* dblockobj;
4632 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4633 return NULL;
4635 CHECK_ENV_NOT_CLOSED(self);
4636 MYDB_BEGIN_ALLOW_THREADS;
4637 #if (DBVER >= 40)
4638 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4639 #else
4640 err = lock_put(self->db_env, &dblockobj->lock);
4641 #endif
4642 MYDB_END_ALLOW_THREADS;
4643 RETURN_IF_ERR();
4644 RETURN_NONE();
4647 #if (DBVER >= 44)
4648 static PyObject*
4649 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4651 int err;
4652 char *file;
4653 u_int32_t flags = 0;
4654 static char* kwnames[] = { "file", "flags", NULL};
4656 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4657 &file, &flags))
4658 return NULL;
4659 CHECK_ENV_NOT_CLOSED(self);
4661 MYDB_BEGIN_ALLOW_THREADS;
4662 err = self->db_env->lsn_reset(self->db_env, file, flags);
4663 MYDB_END_ALLOW_THREADS;
4664 RETURN_IF_ERR();
4665 RETURN_NONE();
4667 #endif /* DBVER >= 4.4 */
4669 #if (DBVER >= 40)
4670 static PyObject*
4671 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4673 int err;
4674 DB_LOG_STAT* statp = NULL;
4675 PyObject* d = NULL;
4676 u_int32_t flags = 0;
4678 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4679 return NULL;
4680 CHECK_ENV_NOT_CLOSED(self);
4682 MYDB_BEGIN_ALLOW_THREADS;
4683 err = self->db_env->log_stat(self->db_env, &statp, flags);
4684 MYDB_END_ALLOW_THREADS;
4685 RETURN_IF_ERR();
4687 /* Turn the stat structure into a dictionary */
4688 d = PyDict_New();
4689 if (d == NULL) {
4690 if (statp)
4691 free(statp);
4692 return NULL;
4695 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4697 MAKE_ENTRY(magic);
4698 MAKE_ENTRY(version);
4699 MAKE_ENTRY(mode);
4700 MAKE_ENTRY(lg_bsize);
4701 #if (DBVER >= 44)
4702 MAKE_ENTRY(lg_size);
4703 MAKE_ENTRY(record);
4704 #endif
4705 #if (DBVER <= 40)
4706 MAKE_ENTRY(lg_max);
4707 #endif
4708 MAKE_ENTRY(w_mbytes);
4709 MAKE_ENTRY(w_bytes);
4710 MAKE_ENTRY(wc_mbytes);
4711 MAKE_ENTRY(wc_bytes);
4712 MAKE_ENTRY(wcount);
4713 MAKE_ENTRY(wcount_fill);
4714 #if (DBVER >= 44)
4715 MAKE_ENTRY(rcount);
4716 #endif
4717 MAKE_ENTRY(scount);
4718 MAKE_ENTRY(cur_file);
4719 MAKE_ENTRY(cur_offset);
4720 MAKE_ENTRY(disk_file);
4721 MAKE_ENTRY(disk_offset);
4722 MAKE_ENTRY(maxcommitperflush);
4723 MAKE_ENTRY(mincommitperflush);
4724 MAKE_ENTRY(regsize);
4725 MAKE_ENTRY(region_wait);
4726 MAKE_ENTRY(region_nowait);
4728 #undef MAKE_ENTRY
4729 free(statp);
4730 return d;
4731 } /* DBEnv_log_stat */
4732 #endif /* DBVER >= 4.0 for log_stat method */
4735 static PyObject*
4736 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4738 int err;
4739 DB_LOCK_STAT* sp;
4740 PyObject* d = NULL;
4741 u_int32_t flags = 0;
4743 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4744 return NULL;
4745 CHECK_ENV_NOT_CLOSED(self);
4747 MYDB_BEGIN_ALLOW_THREADS;
4748 #if (DBVER >= 40)
4749 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4750 #else
4751 #if (DBVER >= 33)
4752 err = lock_stat(self->db_env, &sp);
4753 #else
4754 err = lock_stat(self->db_env, &sp, NULL);
4755 #endif
4756 #endif
4757 MYDB_END_ALLOW_THREADS;
4758 RETURN_IF_ERR();
4760 /* Turn the stat structure into a dictionary */
4761 d = PyDict_New();
4762 if (d == NULL) {
4763 free(sp);
4764 return NULL;
4767 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4769 #if (DBVER < 41)
4770 MAKE_ENTRY(lastid);
4771 #endif
4772 #if (DBVER >=41)
4773 MAKE_ENTRY(id);
4774 MAKE_ENTRY(cur_maxid);
4775 #endif
4776 MAKE_ENTRY(nmodes);
4777 MAKE_ENTRY(maxlocks);
4778 MAKE_ENTRY(maxlockers);
4779 MAKE_ENTRY(maxobjects);
4780 MAKE_ENTRY(nlocks);
4781 MAKE_ENTRY(maxnlocks);
4782 MAKE_ENTRY(nlockers);
4783 MAKE_ENTRY(maxnlockers);
4784 MAKE_ENTRY(nobjects);
4785 MAKE_ENTRY(maxnobjects);
4786 MAKE_ENTRY(nrequests);
4787 MAKE_ENTRY(nreleases);
4788 #if (DBVER >= 44)
4789 MAKE_ENTRY(nupgrade);
4790 MAKE_ENTRY(ndowngrade);
4791 #endif
4792 #if (DBVER < 44)
4793 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4794 MAKE_ENTRY(nconflicts);
4795 #else
4796 MAKE_ENTRY(lock_nowait);
4797 MAKE_ENTRY(lock_wait);
4798 #endif
4799 MAKE_ENTRY(ndeadlocks);
4800 #if (DBVER >= 41)
4801 MAKE_ENTRY(locktimeout);
4802 MAKE_ENTRY(txntimeout);
4803 #endif
4804 #if (DBVER >= 40)
4805 MAKE_ENTRY(nlocktimeouts);
4806 MAKE_ENTRY(ntxntimeouts);
4807 #endif
4808 #if (DBVER >= 46)
4809 MAKE_ENTRY(objs_wait);
4810 MAKE_ENTRY(objs_nowait);
4811 MAKE_ENTRY(lockers_wait);
4812 MAKE_ENTRY(lockers_nowait);
4813 #if (DBVER >= 47)
4814 MAKE_ENTRY(lock_wait);
4815 MAKE_ENTRY(lock_nowait);
4816 #else
4817 MAKE_ENTRY(locks_wait);
4818 MAKE_ENTRY(locks_nowait);
4819 #endif
4820 MAKE_ENTRY(hash_len);
4821 #endif
4822 MAKE_ENTRY(regsize);
4823 MAKE_ENTRY(region_wait);
4824 MAKE_ENTRY(region_nowait);
4826 #undef MAKE_ENTRY
4827 free(sp);
4828 return d;
4831 #if (DBVER >= 40)
4832 static PyObject*
4833 DBEnv_log_flush(DBEnvObject* self, PyObject* args)
4835 int err;
4837 if (!PyArg_ParseTuple(args, ":log_flush"))
4838 return NULL;
4839 CHECK_ENV_NOT_CLOSED(self);
4841 MYDB_BEGIN_ALLOW_THREADS
4842 err = self->db_env->log_flush(self->db_env, NULL);
4843 MYDB_END_ALLOW_THREADS
4845 RETURN_IF_ERR();
4846 RETURN_NONE();
4848 #endif
4850 static PyObject*
4851 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4853 int flags=0;
4854 int err;
4855 char **log_list = NULL;
4856 PyObject* list;
4857 PyObject* item = NULL;
4859 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4860 return NULL;
4862 CHECK_ENV_NOT_CLOSED(self);
4863 MYDB_BEGIN_ALLOW_THREADS;
4864 #if (DBVER >= 40)
4865 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4866 #elif (DBVER == 33)
4867 err = log_archive(self->db_env, &log_list, flags);
4868 #else
4869 err = log_archive(self->db_env, &log_list, flags, NULL);
4870 #endif
4871 MYDB_END_ALLOW_THREADS;
4872 RETURN_IF_ERR();
4874 list = PyList_New(0);
4875 if (list == NULL) {
4876 if (log_list)
4877 free(log_list);
4878 return NULL;
4881 if (log_list) {
4882 char **log_list_start;
4883 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4884 item = PyBytes_FromString (*log_list);
4885 if (item == NULL) {
4886 Py_DECREF(list);
4887 list = NULL;
4888 break;
4890 PyList_Append(list, item);
4891 Py_DECREF(item);
4893 free(log_list_start);
4895 return list;
4899 static PyObject*
4900 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4902 int err;
4903 DB_TXN_STAT* sp;
4904 PyObject* d = NULL;
4905 u_int32_t flags=0;
4907 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4908 return NULL;
4909 CHECK_ENV_NOT_CLOSED(self);
4911 MYDB_BEGIN_ALLOW_THREADS;
4912 #if (DBVER >= 40)
4913 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4914 #elif (DBVER == 33)
4915 err = txn_stat(self->db_env, &sp);
4916 #else
4917 err = txn_stat(self->db_env, &sp, NULL);
4918 #endif
4919 MYDB_END_ALLOW_THREADS;
4920 RETURN_IF_ERR();
4922 /* Turn the stat structure into a dictionary */
4923 d = PyDict_New();
4924 if (d == NULL) {
4925 free(sp);
4926 return NULL;
4929 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4930 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4931 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
4933 #if (DBVER >= 40)
4934 MAKE_DB_LSN_ENTRY(last_ckp);
4935 #endif
4936 MAKE_TIME_T_ENTRY(time_ckp);
4937 MAKE_ENTRY(last_txnid);
4938 MAKE_ENTRY(maxtxns);
4939 MAKE_ENTRY(nactive);
4940 MAKE_ENTRY(maxnactive);
4941 #if (DBVER >= 45)
4942 MAKE_ENTRY(nsnapshot);
4943 MAKE_ENTRY(maxnsnapshot);
4944 #endif
4945 MAKE_ENTRY(nbegins);
4946 MAKE_ENTRY(naborts);
4947 MAKE_ENTRY(ncommits);
4948 #if (DBVER >= 40)
4949 MAKE_ENTRY(nrestores);
4950 #endif
4951 MAKE_ENTRY(regsize);
4952 MAKE_ENTRY(region_wait);
4953 MAKE_ENTRY(region_nowait);
4955 #undef MAKE_DB_LSN_ENTRY
4956 #undef MAKE_ENTRY
4957 #undef MAKE_TIME_T_ENTRY
4958 free(sp);
4959 return d;
4963 static PyObject*
4964 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4966 int flags=0;
4967 int oldValue=0;
4969 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4970 return NULL;
4971 CHECK_ENV_NOT_CLOSED(self);
4973 if (self->moduleFlags.getReturnsNone)
4974 ++oldValue;
4975 if (self->moduleFlags.cursorSetReturnsNone)
4976 ++oldValue;
4977 self->moduleFlags.getReturnsNone = (flags >= 1);
4978 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4979 return PyInt_FromLong(oldValue);
4982 #if (DBVER >= 40)
4983 static PyObject*
4984 DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4986 int err;
4987 char *host;
4988 long cl_timeout=0, sv_timeout=0;
4990 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
4992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
4993 &host, &cl_timeout, &sv_timeout))
4994 return NULL;
4995 CHECK_ENV_NOT_CLOSED(self);
4997 MYDB_BEGIN_ALLOW_THREADS;
4998 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
4999 sv_timeout, 0);
5000 MYDB_END_ALLOW_THREADS;
5001 RETURN_IF_ERR();
5002 RETURN_NONE();
5004 #endif
5006 #if (DBVER >= 40)
5007 static PyObject*
5008 DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
5010 int err;
5011 int which, onoff;
5013 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5014 return NULL;
5016 CHECK_ENV_NOT_CLOSED(self);
5017 MYDB_BEGIN_ALLOW_THREADS;
5018 err = self->db_env->set_verbose(self->db_env, which, onoff);
5019 MYDB_END_ALLOW_THREADS;
5020 RETURN_IF_ERR();
5021 RETURN_NONE();
5024 #if (DBVER >= 42)
5025 static PyObject*
5026 DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5028 int err;
5029 int which;
5030 int verbose;
5032 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5033 return NULL;
5035 CHECK_ENV_NOT_CLOSED(self);
5036 MYDB_BEGIN_ALLOW_THREADS;
5037 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5038 MYDB_END_ALLOW_THREADS;
5039 RETURN_IF_ERR();
5040 return PyBool_FromLong(verbose);
5042 #endif
5043 #endif
5045 #if (DBVER >= 45)
5046 static void
5047 _dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5049 DBEnvObject *dbenv;
5050 PyObject* callback;
5051 PyObject* args;
5052 PyObject* result = NULL;
5054 MYDB_BEGIN_BLOCK_THREADS;
5055 dbenv = (DBEnvObject *)db_env->app_private;
5056 callback = dbenv->event_notifyCallback;
5057 if (callback) {
5058 if (event == DB_EVENT_REP_NEWMASTER) {
5059 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5060 } else {
5061 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5063 if (args) {
5064 result = PyEval_CallObject(callback, args);
5066 if ((!args) || (!result)) {
5067 PyErr_Print();
5069 Py_XDECREF(args);
5070 Py_XDECREF(result);
5072 MYDB_END_BLOCK_THREADS;
5074 #endif
5076 #if (DBVER >= 45)
5077 static PyObject*
5078 DBEnv_set_event_notify(DBEnvObject* self, PyObject* args)
5080 int err;
5081 PyObject *notifyFunc;
5083 if (!PyArg_ParseTuple(args, "O:set_event_notify", &notifyFunc)) {
5084 return NULL;
5087 CHECK_ENV_NOT_CLOSED(self);
5089 if (!PyCallable_Check(notifyFunc)) {
5090 makeTypeError("Callable", notifyFunc);
5091 return NULL;
5094 Py_XDECREF(self->event_notifyCallback);
5095 Py_INCREF(notifyFunc);
5096 self->event_notifyCallback = notifyFunc;
5098 MYDB_BEGIN_ALLOW_THREADS;
5099 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5100 MYDB_END_ALLOW_THREADS;
5102 if (err) {
5103 Py_DECREF(notifyFunc);
5104 self->event_notifyCallback = NULL;
5107 RETURN_IF_ERR();
5108 RETURN_NONE();
5110 #endif
5113 /* --------------------------------------------------------------------- */
5114 /* REPLICATION METHODS: Base Replication */
5116 #if (DBVER >= 45)
5117 static PyObject*
5118 DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5120 int err;
5121 int nsites;
5123 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5124 return NULL;
5126 CHECK_ENV_NOT_CLOSED(self);
5127 MYDB_BEGIN_ALLOW_THREADS;
5128 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5129 MYDB_END_ALLOW_THREADS;
5130 RETURN_IF_ERR();
5131 RETURN_NONE();
5134 static PyObject*
5135 DBEnv_rep_get_nsites(DBEnvObject* self, PyObject* args)
5137 int err;
5138 #if (DBVER >= 47)
5139 u_int32_t nsites;
5140 #else
5141 int nsites;
5142 #endif
5144 if (!PyArg_ParseTuple(args, ":rep_get_nsites")) {
5145 return NULL;
5147 CHECK_ENV_NOT_CLOSED(self);
5148 MYDB_BEGIN_ALLOW_THREADS;
5149 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5150 MYDB_END_ALLOW_THREADS;
5151 RETURN_IF_ERR();
5152 return PyInt_FromLong(nsites);
5155 static PyObject*
5156 DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5158 int err;
5159 int priority;
5161 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5162 return NULL;
5164 CHECK_ENV_NOT_CLOSED(self);
5165 MYDB_BEGIN_ALLOW_THREADS;
5166 err = self->db_env->rep_set_priority(self->db_env, priority);
5167 MYDB_END_ALLOW_THREADS;
5168 RETURN_IF_ERR();
5169 RETURN_NONE();
5172 static PyObject*
5173 DBEnv_rep_get_priority(DBEnvObject* self, PyObject* args)
5175 int err;
5176 #if (DBVER >= 47)
5177 u_int32_t priority;
5178 #else
5179 int priority;
5180 #endif
5182 if (!PyArg_ParseTuple(args, ":rep_get_priority")) {
5183 return NULL;
5185 CHECK_ENV_NOT_CLOSED(self);
5186 MYDB_BEGIN_ALLOW_THREADS;
5187 err = self->db_env->rep_get_priority(self->db_env, &priority);
5188 MYDB_END_ALLOW_THREADS;
5189 RETURN_IF_ERR();
5190 return PyInt_FromLong(priority);
5193 static PyObject*
5194 DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5196 int err;
5197 int which, timeout;
5199 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5200 return NULL;
5202 CHECK_ENV_NOT_CLOSED(self);
5203 MYDB_BEGIN_ALLOW_THREADS;
5204 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5205 MYDB_END_ALLOW_THREADS;
5206 RETURN_IF_ERR();
5207 RETURN_NONE();
5210 static PyObject*
5211 DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5213 int err;
5214 int which;
5215 u_int32_t timeout;
5217 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5218 return NULL;
5220 CHECK_ENV_NOT_CLOSED(self);
5221 MYDB_BEGIN_ALLOW_THREADS;
5222 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5223 MYDB_END_ALLOW_THREADS;
5224 RETURN_IF_ERR();
5225 return PyInt_FromLong(timeout);
5227 #endif
5229 /* --------------------------------------------------------------------- */
5230 /* REPLICATION METHODS: Replication Manager */
5232 #if (DBVER >= 45)
5233 static PyObject*
5234 DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5235 kwargs)
5237 int err;
5238 int nthreads, flags;
5239 static char* kwnames[] = {"nthreads","flags", NULL};
5241 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5242 "ii:repmgr_start", kwnames, &nthreads, &flags))
5244 return NULL;
5246 CHECK_ENV_NOT_CLOSED(self);
5247 MYDB_BEGIN_ALLOW_THREADS;
5248 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5249 MYDB_END_ALLOW_THREADS;
5250 RETURN_IF_ERR();
5251 RETURN_NONE();
5254 static PyObject*
5255 DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5256 kwargs)
5258 int err;
5259 char *host;
5260 int port;
5261 int flags = 0;
5262 static char* kwnames[] = {"host", "port", "flags", NULL};
5264 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5265 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5267 return NULL;
5269 CHECK_ENV_NOT_CLOSED(self);
5270 MYDB_BEGIN_ALLOW_THREADS;
5271 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5272 MYDB_END_ALLOW_THREADS;
5273 RETURN_IF_ERR();
5274 RETURN_NONE();
5277 static PyObject*
5278 DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5279 kwargs)
5281 int err;
5282 char *host;
5283 int port;
5284 int flags = 0;
5285 int eidp;
5286 static char* kwnames[] = {"host", "port", "flags", NULL};
5288 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5289 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5291 return NULL;
5293 CHECK_ENV_NOT_CLOSED(self);
5294 MYDB_BEGIN_ALLOW_THREADS;
5295 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5296 MYDB_END_ALLOW_THREADS;
5297 RETURN_IF_ERR();
5298 return PyInt_FromLong(eidp);
5301 static PyObject*
5302 DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5304 int err;
5305 int ack_policy;
5307 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5309 return NULL;
5311 CHECK_ENV_NOT_CLOSED(self);
5312 MYDB_BEGIN_ALLOW_THREADS;
5313 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5314 MYDB_END_ALLOW_THREADS;
5315 RETURN_IF_ERR();
5316 RETURN_NONE();
5319 static PyObject*
5320 DBEnv_repmgr_get_ack_policy(DBEnvObject* self, PyObject* args)
5322 int err;
5323 int ack_policy;
5325 if (!PyArg_ParseTuple(args, ":repmgr_get_ack_policy"))
5327 return NULL;
5329 CHECK_ENV_NOT_CLOSED(self);
5330 MYDB_BEGIN_ALLOW_THREADS;
5331 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5332 MYDB_END_ALLOW_THREADS;
5333 RETURN_IF_ERR();
5334 return PyInt_FromLong(ack_policy);
5337 static PyObject*
5338 DBEnv_repmgr_site_list(DBEnvObject* self, PyObject* args)
5340 int err;
5341 unsigned int countp;
5342 DB_REPMGR_SITE *listp;
5343 PyObject *stats, *key, *tuple;
5345 if (!PyArg_ParseTuple(args, ":repmgr_site_list"))
5347 return NULL;
5349 CHECK_ENV_NOT_CLOSED(self);
5350 MYDB_BEGIN_ALLOW_THREADS;
5351 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5352 MYDB_END_ALLOW_THREADS;
5353 RETURN_IF_ERR();
5355 stats=PyDict_New();
5356 if (stats == NULL) {
5357 free(listp);
5358 return NULL;
5361 for(;countp--;) {
5362 key=PyInt_FromLong(listp[countp].eid);
5363 if(!key) {
5364 Py_DECREF(stats);
5365 free(listp);
5366 return NULL;
5368 #if (PY_VERSION_HEX >= 0x02040000)
5369 tuple=Py_BuildValue("(sII)", listp[countp].host,
5370 listp[countp].port, listp[countp].status);
5371 #else
5372 tuple=Py_BuildValue("(sii)", listp[countp].host,
5373 listp[countp].port, listp[countp].status);
5374 #endif
5375 if(!tuple) {
5376 Py_DECREF(key);
5377 Py_DECREF(stats);
5378 free(listp);
5379 return NULL;
5381 if(PyDict_SetItem(stats, key, tuple)) {
5382 Py_DECREF(key);
5383 Py_DECREF(tuple);
5384 Py_DECREF(stats);
5385 free(listp);
5386 return NULL;
5389 free(listp);
5390 return stats;
5392 #endif
5394 #if (DBVER >= 46)
5395 static PyObject*
5396 DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5398 int err;
5399 int flags=0;
5400 static char* kwnames[] = { "flags", NULL };
5402 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5403 kwnames, &flags))
5405 return NULL;
5407 CHECK_ENV_NOT_CLOSED(self);
5408 MYDB_BEGIN_ALLOW_THREADS;
5409 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5410 MYDB_END_ALLOW_THREADS;
5411 RETURN_IF_ERR();
5412 RETURN_NONE();
5415 static PyObject*
5416 DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5418 int err;
5419 int flags=0;
5420 DB_REPMGR_STAT *statp;
5421 PyObject *stats;
5422 static char* kwnames[] = { "flags", NULL };
5424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5425 kwnames, &flags))
5427 return NULL;
5429 CHECK_ENV_NOT_CLOSED(self);
5430 MYDB_BEGIN_ALLOW_THREADS;
5431 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5432 MYDB_END_ALLOW_THREADS;
5433 RETURN_IF_ERR();
5435 stats=PyDict_New();
5436 if (stats == NULL) {
5437 free(statp);
5438 return NULL;
5441 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5443 MAKE_ENTRY(perm_failed);
5444 MAKE_ENTRY(msgs_queued);
5445 MAKE_ENTRY(msgs_dropped);
5446 MAKE_ENTRY(connection_drop);
5447 MAKE_ENTRY(connect_fail);
5449 #undef MAKE_ENTRY
5451 free(statp);
5452 return stats;
5454 #endif
5457 /* --------------------------------------------------------------------- */
5458 /* DBTxn methods */
5461 static void _close_transaction_cursors(DBTxnObject* txn)
5463 PyObject *dummy;
5465 while(txn->children_cursors) {
5466 PyErr_Warn(PyExc_RuntimeWarning,
5467 "Must close cursors before resolving a transaction.");
5468 dummy=DBC_close_internal(txn->children_cursors);
5469 Py_XDECREF(dummy);
5473 static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5475 DBObject *db;
5476 #if (DBVER >= 43)
5477 DBSequenceObject *dbs;
5478 #endif
5480 while (txn->children_dbs) {
5481 db=txn->children_dbs;
5482 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5483 if (txn->parent_txn) {
5484 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5485 db->txn=txn->parent_txn;
5486 } else {
5487 /* The db is already linked to its environment,
5488 ** so nothing to do.
5490 db->txn=NULL;
5494 #if (DBVER >= 43)
5495 while (txn->children_sequences) {
5496 dbs=txn->children_sequences;
5497 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5498 if (txn->parent_txn) {
5499 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5500 dbs->txn=txn->parent_txn;
5501 } else {
5502 /* The sequence is already linked to its
5503 ** parent db. Nothing to do.
5505 dbs->txn=NULL;
5508 #endif
5512 static PyObject*
5513 DBTxn_commit(DBTxnObject* self, PyObject* args)
5515 int flags=0, err;
5516 DB_TXN *txn;
5518 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5519 return NULL;
5521 _close_transaction_cursors(self);
5523 if (!self->txn) {
5524 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5525 "after txn_commit, txn_abort "
5526 "or txn_discard");
5527 PyErr_SetObject(DBError, t);
5528 Py_DECREF(t);
5529 return NULL;
5531 self->flag_prepare=0;
5532 txn = self->txn;
5533 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
5535 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5537 MYDB_BEGIN_ALLOW_THREADS;
5538 #if (DBVER >= 40)
5539 err = txn->commit(txn, flags);
5540 #else
5541 err = txn_commit(txn, flags);
5542 #endif
5543 MYDB_END_ALLOW_THREADS;
5545 _promote_transaction_dbs_and_sequences(self);
5547 RETURN_IF_ERR();
5548 RETURN_NONE();
5551 static PyObject*
5552 DBTxn_prepare(DBTxnObject* self, PyObject* args)
5554 #if (DBVER >= 33)
5555 int err;
5556 char* gid=NULL;
5557 int gid_size=0;
5559 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5560 return NULL;
5562 if (gid_size != DB_XIDDATASIZE) {
5563 PyErr_SetString(PyExc_TypeError,
5564 "gid must be DB_XIDDATASIZE bytes long");
5565 return NULL;
5568 if (!self->txn) {
5569 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
5570 "after txn_commit, txn_abort "
5571 "or txn_discard");
5572 PyErr_SetObject(DBError, t);
5573 Py_DECREF(t);
5574 return NULL;
5576 self->flag_prepare=1; /* Prepare state */
5577 MYDB_BEGIN_ALLOW_THREADS;
5578 #if (DBVER >= 40)
5579 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5580 #else
5581 err = txn_prepare(self->txn, (u_int8_t*)gid);
5582 #endif
5583 MYDB_END_ALLOW_THREADS;
5584 RETURN_IF_ERR();
5585 RETURN_NONE();
5586 #else
5587 int err;
5589 if (!PyArg_ParseTuple(args, ":prepare"))
5590 return NULL;
5592 if (!self->txn) {
5593 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5594 "after txn_commit, txn_abort "
5595 "or txn_discard");
5596 PyErr_SetObject(DBError, t);
5597 Py_DECREF(t);
5598 return NULL;
5600 MYDB_BEGIN_ALLOW_THREADS;
5601 err = txn_prepare(self->txn);
5602 MYDB_END_ALLOW_THREADS;
5603 RETURN_IF_ERR();
5604 RETURN_NONE();
5605 #endif
5609 static PyObject*
5610 DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
5612 PyObject *dummy;
5613 int err=0;
5614 DB_TXN *txn;
5616 if (!self->txn) {
5617 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5618 "after txn_commit, txn_abort "
5619 "or txn_discard");
5620 PyErr_SetObject(DBError, t);
5621 Py_DECREF(t);
5622 return NULL;
5624 txn = self->txn;
5625 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
5627 _close_transaction_cursors(self);
5628 #if (DBVER >= 43)
5629 while (self->children_sequences) {
5630 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5631 Py_XDECREF(dummy);
5633 #endif
5634 while (self->children_dbs) {
5635 dummy=DB_close_internal(self->children_dbs,0);
5636 Py_XDECREF(dummy);
5639 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5641 MYDB_BEGIN_ALLOW_THREADS;
5642 if (discard) {
5643 assert(!self->flag_prepare);
5644 #if (DBVER >= 40)
5645 err = txn->discard(txn,0);
5646 #else
5647 err = txn_discard(txn);
5648 #endif
5649 } else {
5651 ** If the transaction is in the "prepare" or "recover" state,
5652 ** we better do not implicitly abort it.
5654 if (!self->flag_prepare) {
5655 #if (DBVER >= 40)
5656 err = txn->abort(txn);
5657 #else
5658 err = txn_abort(txn);
5659 #endif
5662 MYDB_END_ALLOW_THREADS;
5663 RETURN_IF_ERR();
5664 RETURN_NONE();
5667 static PyObject*
5668 DBTxn_abort(DBTxnObject* self, PyObject* args)
5670 if (!PyArg_ParseTuple(args, ":abort"))
5671 return NULL;
5673 self->flag_prepare=0;
5674 _close_transaction_cursors(self);
5676 return DBTxn_abort_discard_internal(self,0);
5679 static PyObject*
5680 DBTxn_discard(DBTxnObject* self, PyObject* args)
5682 if (!PyArg_ParseTuple(args, ":discard"))
5683 return NULL;
5685 self->flag_prepare=0;
5686 _close_transaction_cursors(self);
5688 return DBTxn_abort_discard_internal(self,1);
5692 static PyObject*
5693 DBTxn_id(DBTxnObject* self, PyObject* args)
5695 int id;
5697 if (!PyArg_ParseTuple(args, ":id"))
5698 return NULL;
5700 if (!self->txn) {
5701 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
5702 "after txn_commit, txn_abort "
5703 "or txn_discard");
5704 PyErr_SetObject(DBError, t);
5705 Py_DECREF(t);
5706 return NULL;
5708 MYDB_BEGIN_ALLOW_THREADS;
5709 #if (DBVER >= 40)
5710 id = self->txn->id(self->txn);
5711 #else
5712 id = txn_id(self->txn);
5713 #endif
5714 MYDB_END_ALLOW_THREADS;
5715 return PyInt_FromLong(id);
5718 #if (DBVER >= 43)
5719 /* --------------------------------------------------------------------- */
5720 /* DBSequence methods */
5723 static PyObject*
5724 DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
5726 int err=0;
5728 if (self->sequence!=NULL) {
5729 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5730 if (self->txn) {
5731 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
5732 self->txn=NULL;
5735 if (!do_not_close) {
5736 MYDB_BEGIN_ALLOW_THREADS
5737 err = self->sequence->close(self->sequence, flags);
5738 MYDB_END_ALLOW_THREADS
5740 self->sequence = NULL;
5742 RETURN_IF_ERR();
5745 RETURN_NONE();
5748 static PyObject*
5749 DBSequence_close(DBSequenceObject* self, PyObject* args)
5751 int flags=0;
5752 if (!PyArg_ParseTuple(args,"|i:close", &flags))
5753 return NULL;
5755 return DBSequence_close_internal(self,flags,0);
5758 static PyObject*
5759 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5761 int err, flags = 0;
5762 int delta = 1;
5763 db_seq_t value;
5764 PyObject *txnobj = NULL;
5765 DB_TXN *txn = NULL;
5766 static char* kwnames[] = {"delta", "txn", "flags", NULL };
5767 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
5768 return NULL;
5769 CHECK_SEQUENCE_NOT_CLOSED(self)
5771 if (!checkTxnObj(txnobj, &txn))
5772 return NULL;
5774 MYDB_BEGIN_ALLOW_THREADS
5775 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5776 MYDB_END_ALLOW_THREADS
5778 RETURN_IF_ERR();
5779 return PyLong_FromLongLong(value);
5782 static PyObject*
5783 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
5785 if (!PyArg_ParseTuple(args,":get_dbp"))
5786 return NULL;
5787 CHECK_SEQUENCE_NOT_CLOSED(self)
5788 Py_INCREF(self->mydb);
5789 return (PyObject* )self->mydb;
5792 static PyObject*
5793 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
5795 int err;
5796 DBT key;
5797 PyObject *retval = NULL;
5799 if (!PyArg_ParseTuple(args,":get_key"))
5800 return NULL;
5802 key.flags = DB_DBT_MALLOC;
5803 CHECK_SEQUENCE_NOT_CLOSED(self)
5804 MYDB_BEGIN_ALLOW_THREADS
5805 err = self->sequence->get_key(self->sequence, &key);
5806 MYDB_END_ALLOW_THREADS
5808 if (!err)
5809 retval = Build_PyString(key.data, key.size);
5811 FREE_DBT(key);
5812 RETURN_IF_ERR();
5814 return retval;
5817 static PyObject*
5818 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
5820 int err;
5821 PY_LONG_LONG value;
5822 db_seq_t value2;
5823 if (!PyArg_ParseTuple(args,"L:init_value", &value))
5824 return NULL;
5825 CHECK_SEQUENCE_NOT_CLOSED(self)
5827 value2=value; /* If truncation, compiler should show a warning */
5828 MYDB_BEGIN_ALLOW_THREADS
5829 err = self->sequence->initial_value(self->sequence, value2);
5830 MYDB_END_ALLOW_THREADS
5832 RETURN_IF_ERR();
5834 RETURN_NONE();
5837 static PyObject*
5838 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5840 int err, flags = 0;
5841 PyObject* keyobj;
5842 PyObject *txnobj = NULL;
5843 DB_TXN *txn = NULL;
5844 DBT key;
5846 static char* kwnames[] = {"key", "txn", "flags", NULL };
5847 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
5848 return NULL;
5850 if (!checkTxnObj(txnobj, &txn))
5851 return NULL;
5853 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
5854 return NULL;
5856 MYDB_BEGIN_ALLOW_THREADS
5857 err = self->sequence->open(self->sequence, txn, &key, flags);
5858 MYDB_END_ALLOW_THREADS
5860 CLEAR_DBT(key);
5861 RETURN_IF_ERR();
5863 if (txn) {
5864 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
5865 self->txn=(DBTxnObject *)txnobj;
5868 RETURN_NONE();
5871 static PyObject*
5872 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5874 PyObject *dummy;
5875 int err, flags = 0;
5876 PyObject *txnobj = NULL;
5877 DB_TXN *txn = NULL;
5879 static char* kwnames[] = {"txn", "flags", NULL };
5880 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
5881 return NULL;
5883 if (!checkTxnObj(txnobj, &txn))
5884 return NULL;
5886 CHECK_SEQUENCE_NOT_CLOSED(self)
5888 MYDB_BEGIN_ALLOW_THREADS
5889 err = self->sequence->remove(self->sequence, txn, flags);
5890 MYDB_END_ALLOW_THREADS
5892 dummy=DBSequence_close_internal(self,flags,1);
5893 Py_XDECREF(dummy);
5895 RETURN_IF_ERR();
5896 RETURN_NONE();
5899 static PyObject*
5900 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5902 int err, size;
5903 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
5904 return NULL;
5905 CHECK_SEQUENCE_NOT_CLOSED(self)
5907 MYDB_BEGIN_ALLOW_THREADS
5908 err = self->sequence->set_cachesize(self->sequence, size);
5909 MYDB_END_ALLOW_THREADS
5911 RETURN_IF_ERR();
5912 RETURN_NONE();
5915 static PyObject*
5916 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5918 int err, size;
5919 if (!PyArg_ParseTuple(args,":get_cachesize"))
5920 return NULL;
5921 CHECK_SEQUENCE_NOT_CLOSED(self)
5923 MYDB_BEGIN_ALLOW_THREADS
5924 err = self->sequence->get_cachesize(self->sequence, &size);
5925 MYDB_END_ALLOW_THREADS
5927 RETURN_IF_ERR();
5928 return PyInt_FromLong(size);
5931 static PyObject*
5932 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5934 int err, flags = 0;
5935 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5936 return NULL;
5937 CHECK_SEQUENCE_NOT_CLOSED(self)
5939 MYDB_BEGIN_ALLOW_THREADS
5940 err = self->sequence->set_flags(self->sequence, flags);
5941 MYDB_END_ALLOW_THREADS
5943 RETURN_IF_ERR();
5944 RETURN_NONE();
5947 static PyObject*
5948 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5950 unsigned int flags;
5951 int err;
5952 if (!PyArg_ParseTuple(args,":get_flags"))
5953 return NULL;
5954 CHECK_SEQUENCE_NOT_CLOSED(self)
5956 MYDB_BEGIN_ALLOW_THREADS
5957 err = self->sequence->get_flags(self->sequence, &flags);
5958 MYDB_END_ALLOW_THREADS
5960 RETURN_IF_ERR();
5961 return PyInt_FromLong((int)flags);
5964 static PyObject*
5965 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5967 int err;
5968 PY_LONG_LONG min, max;
5969 db_seq_t min2, max2;
5970 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5971 return NULL;
5972 CHECK_SEQUENCE_NOT_CLOSED(self)
5974 min2=min; /* If truncation, compiler should show a warning */
5975 max2=max;
5976 MYDB_BEGIN_ALLOW_THREADS
5977 err = self->sequence->set_range(self->sequence, min2, max2);
5978 MYDB_END_ALLOW_THREADS
5980 RETURN_IF_ERR();
5981 RETURN_NONE();
5984 static PyObject*
5985 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5987 int err;
5988 PY_LONG_LONG min, max;
5989 db_seq_t min2, max2;
5990 if (!PyArg_ParseTuple(args,":get_range"))
5991 return NULL;
5992 CHECK_SEQUENCE_NOT_CLOSED(self)
5994 MYDB_BEGIN_ALLOW_THREADS
5995 err = self->sequence->get_range(self->sequence, &min2, &max2);
5996 MYDB_END_ALLOW_THREADS
5998 RETURN_IF_ERR();
5999 min=min2; /* If truncation, compiler should show a warning */
6000 max=max2;
6001 return Py_BuildValue("(LL)", min, max);
6004 static PyObject*
6005 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
6007 int err, flags = 0;
6008 DB_SEQUENCE_STAT* sp = NULL;
6009 PyObject* dict_stat;
6010 static char* kwnames[] = {"flags", NULL };
6011 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6012 return NULL;
6013 CHECK_SEQUENCE_NOT_CLOSED(self);
6015 MYDB_BEGIN_ALLOW_THREADS;
6016 err = self->sequence->stat(self->sequence, &sp, flags);
6017 MYDB_END_ALLOW_THREADS;
6018 RETURN_IF_ERR();
6020 if ((dict_stat = PyDict_New()) == NULL) {
6021 free(sp);
6022 return NULL;
6026 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6027 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6029 MAKE_INT_ENTRY(wait);
6030 MAKE_INT_ENTRY(nowait);
6031 MAKE_LONG_LONG_ENTRY(current);
6032 MAKE_LONG_LONG_ENTRY(value);
6033 MAKE_LONG_LONG_ENTRY(last_value);
6034 MAKE_LONG_LONG_ENTRY(min);
6035 MAKE_LONG_LONG_ENTRY(max);
6036 MAKE_INT_ENTRY(cache_size);
6037 MAKE_INT_ENTRY(flags);
6039 #undef MAKE_INT_ENTRY
6040 #undef MAKE_LONG_LONG_ENTRY
6042 free(sp);
6043 return dict_stat;
6045 #endif
6048 /* --------------------------------------------------------------------- */
6049 /* Method definition tables and type objects */
6051 static PyMethodDef DB_methods[] = {
6052 {"append", (PyCFunction)DB_append, METH_VARARGS},
6053 #if (DBVER >= 33)
6054 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
6055 #endif
6056 {"close", (PyCFunction)DB_close, METH_VARARGS},
6057 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6058 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
6059 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6060 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
6061 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
6062 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
6063 #if (DBVER >= 33)
6064 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
6065 #endif
6066 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
6067 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
6068 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6069 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
6070 {"join", (PyCFunction)DB_join, METH_VARARGS},
6071 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6072 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
6073 {"items", (PyCFunction)DB_items, METH_VARARGS},
6074 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6075 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6076 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6077 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6078 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6079 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
6080 #if (DBVER >= 33)
6081 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
6082 #endif
6083 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
6084 #if (DBVER >= 41)
6085 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6086 #endif
6087 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6088 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6089 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6090 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6091 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6092 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6093 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6094 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6095 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
6096 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
6097 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
6098 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6099 #if (DBVER >= 33)
6100 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6101 #endif
6102 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
6103 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6104 {"values", (PyCFunction)DB_values, METH_VARARGS},
6105 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6106 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6107 {NULL, NULL} /* sentinel */
6111 static PyMappingMethods DB_mapping = {
6112 DB_length, /*mp_length*/
6113 (binaryfunc)DB_subscript, /*mp_subscript*/
6114 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6118 static PyMethodDef DBCursor_methods[] = {
6119 {"close", (PyCFunction)DBC_close, METH_VARARGS},
6120 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6121 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6122 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6123 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6124 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6125 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
6126 #if (DBVER >= 33)
6127 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
6128 #endif
6129 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
6130 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6131 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6132 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6133 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6134 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6135 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6136 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
6137 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
6138 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
6139 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6140 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6141 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6142 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6143 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6144 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6145 {NULL, NULL} /* sentinel */
6149 static PyMethodDef DBEnv_methods[] = {
6150 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6151 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6152 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
6153 #if (DBVER >= 41)
6154 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6155 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6156 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6157 #endif
6158 #if (DBVER >= 40)
6159 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6160 #endif
6161 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
6162 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6163 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
6164 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
6165 #if (DBVER >= 47)
6166 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6167 #endif
6168 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6169 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6170 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
6171 #if (DBVER >= 42)
6172 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_VARARGS},
6173 #endif
6174 #if (DBVER >= 33)
6175 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
6176 #endif
6177 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
6178 #if (DBVER < 45)
6179 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
6180 #endif
6181 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6182 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6183 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
6184 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6185 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6186 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6187 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6188 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6189 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
6190 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
6191 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6192 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6193 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
6194 #if (DBVER >= 40)
6195 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6196 #endif
6197 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6198 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6199 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
6200 #if (DBVER >= 40)
6201 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_VARARGS},
6202 #endif
6203 #if (DBVER >= 40)
6204 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6205 #endif
6206 #if (DBVER >= 44)
6207 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6208 #endif
6209 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
6210 #if (DBVER >= 40)
6211 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_VARARGS},
6212 #endif
6213 #if (DBVER >= 40)
6214 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6215 METH_VARARGS||METH_KEYWORDS},
6216 #endif
6217 #if (DBVER >= 40)
6218 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6219 #if (DBVER >= 42)
6220 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6221 #endif
6222 #endif
6223 #if (DBVER >= 45)
6224 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_VARARGS},
6225 #endif
6226 #if (DBVER >= 45)
6227 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6228 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_VARARGS},
6229 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6230 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_VARARGS},
6231 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6232 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6233 #endif
6234 #if (DBVER >= 45)
6235 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6236 METH_VARARGS|METH_KEYWORDS},
6237 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6238 METH_VARARGS|METH_KEYWORDS},
6239 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6240 METH_VARARGS|METH_KEYWORDS},
6241 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6242 METH_VARARGS},
6243 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6244 METH_VARARGS},
6245 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6246 METH_VARARGS},
6247 #endif
6248 #if (DBVER >= 46)
6249 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6250 METH_VARARGS|METH_KEYWORDS},
6251 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6252 METH_VARARGS|METH_KEYWORDS},
6253 #endif
6254 {NULL, NULL} /* sentinel */
6258 static PyMethodDef DBTxn_methods[] = {
6259 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6260 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
6261 {"discard", (PyCFunction)DBTxn_discard, METH_VARARGS},
6262 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
6263 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
6264 {NULL, NULL} /* sentinel */
6268 #if (DBVER >= 43)
6269 static PyMethodDef DBSequence_methods[] = {
6270 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6271 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6272 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
6273 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
6274 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6275 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6276 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6277 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6278 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
6279 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6280 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
6281 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6282 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
6283 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6284 {NULL, NULL} /* sentinel */
6286 #endif
6289 static PyObject*
6290 DB_getattr(DBObject* self, char *name)
6292 return Py_FindMethod(DB_methods, (PyObject* )self, name);
6296 static PyObject*
6297 DBEnv_getattr(DBEnvObject* self, char *name)
6299 if (!strcmp(name, "db_home")) {
6300 const char *home = NULL;
6301 CHECK_ENV_NOT_CLOSED(self);
6302 #if (DBVER >= 42)
6303 self->db_env->get_home(self->db_env, &home);
6304 #else
6305 home=self->db_env->db_home;
6306 #endif
6307 if (home == NULL) {
6308 RETURN_NONE();
6310 return PyBytes_FromString(home);
6313 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
6317 static PyObject*
6318 DBCursor_getattr(DBCursorObject* self, char *name)
6320 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
6323 static PyObject*
6324 DBTxn_getattr(DBTxnObject* self, char *name)
6326 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
6329 static PyObject*
6330 DBLock_getattr(DBLockObject* self, char *name)
6332 return NULL;
6335 #if (DBVER >= 43)
6336 static PyObject*
6337 DBSequence_getattr(DBSequenceObject* self, char *name)
6339 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
6341 #endif
6343 statichere PyTypeObject DB_Type = {
6344 PyObject_HEAD_INIT(NULL)
6345 0, /*ob_size*/
6346 "DB", /*tp_name*/
6347 sizeof(DBObject), /*tp_basicsize*/
6348 0, /*tp_itemsize*/
6349 /* methods */
6350 (destructor)DB_dealloc, /*tp_dealloc*/
6351 0, /*tp_print*/
6352 (getattrfunc)DB_getattr, /*tp_getattr*/
6353 0, /*tp_setattr*/
6354 0, /*tp_compare*/
6355 0, /*tp_repr*/
6356 0, /*tp_as_number*/
6357 0, /*tp_as_sequence*/
6358 &DB_mapping,/*tp_as_mapping*/
6359 0, /*tp_hash*/
6360 0, /* tp_call */
6361 0, /* tp_str */
6362 0, /* tp_getattro */
6363 0, /* tp_setattro */
6364 0, /* tp_as_buffer */
6365 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6366 0, /* tp_doc */
6367 0, /* tp_traverse */
6368 0, /* tp_clear */
6369 0, /* tp_richcompare */
6370 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
6374 statichere PyTypeObject DBCursor_Type = {
6375 PyObject_HEAD_INIT(NULL)
6376 0, /*ob_size*/
6377 "DBCursor", /*tp_name*/
6378 sizeof(DBCursorObject), /*tp_basicsize*/
6379 0, /*tp_itemsize*/
6380 /* methods */
6381 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6382 0, /*tp_print*/
6383 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
6384 0, /*tp_setattr*/
6385 0, /*tp_compare*/
6386 0, /*tp_repr*/
6387 0, /*tp_as_number*/
6388 0, /*tp_as_sequence*/
6389 0, /*tp_as_mapping*/
6390 0, /*tp_hash*/
6391 0, /* tp_call */
6392 0, /* tp_str */
6393 0, /* tp_getattro */
6394 0, /* tp_setattro */
6395 0, /* tp_as_buffer */
6396 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6397 0, /* tp_doc */
6398 0, /* tp_traverse */
6399 0, /* tp_clear */
6400 0, /* tp_richcompare */
6401 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
6405 statichere PyTypeObject DBEnv_Type = {
6406 PyObject_HEAD_INIT(NULL)
6407 0, /*ob_size*/
6408 "DBEnv", /*tp_name*/
6409 sizeof(DBEnvObject), /*tp_basicsize*/
6410 0, /*tp_itemsize*/
6411 /* methods */
6412 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6413 0, /*tp_print*/
6414 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
6415 0, /*tp_setattr*/
6416 0, /*tp_compare*/
6417 0, /*tp_repr*/
6418 0, /*tp_as_number*/
6419 0, /*tp_as_sequence*/
6420 0, /*tp_as_mapping*/
6421 0, /*tp_hash*/
6422 0, /* tp_call */
6423 0, /* tp_str */
6424 0, /* tp_getattro */
6425 0, /* tp_setattro */
6426 0, /* tp_as_buffer */
6427 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6428 0, /* tp_doc */
6429 0, /* tp_traverse */
6430 0, /* tp_clear */
6431 0, /* tp_richcompare */
6432 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
6435 statichere PyTypeObject DBTxn_Type = {
6436 PyObject_HEAD_INIT(NULL)
6437 0, /*ob_size*/
6438 "DBTxn", /*tp_name*/
6439 sizeof(DBTxnObject), /*tp_basicsize*/
6440 0, /*tp_itemsize*/
6441 /* methods */
6442 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6443 0, /*tp_print*/
6444 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
6445 0, /*tp_setattr*/
6446 0, /*tp_compare*/
6447 0, /*tp_repr*/
6448 0, /*tp_as_number*/
6449 0, /*tp_as_sequence*/
6450 0, /*tp_as_mapping*/
6451 0, /*tp_hash*/
6452 0, /* tp_call */
6453 0, /* tp_str */
6454 0, /* tp_getattro */
6455 0, /* tp_setattro */
6456 0, /* tp_as_buffer */
6457 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6458 0, /* tp_doc */
6459 0, /* tp_traverse */
6460 0, /* tp_clear */
6461 0, /* tp_richcompare */
6462 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
6466 statichere PyTypeObject DBLock_Type = {
6467 PyObject_HEAD_INIT(NULL)
6468 0, /*ob_size*/
6469 "DBLock", /*tp_name*/
6470 sizeof(DBLockObject), /*tp_basicsize*/
6471 0, /*tp_itemsize*/
6472 /* methods */
6473 (destructor)DBLock_dealloc, /*tp_dealloc*/
6474 0, /*tp_print*/
6475 (getattrfunc)DBLock_getattr, /*tp_getattr*/
6476 0, /*tp_setattr*/
6477 0, /*tp_compare*/
6478 0, /*tp_repr*/
6479 0, /*tp_as_number*/
6480 0, /*tp_as_sequence*/
6481 0, /*tp_as_mapping*/
6482 0, /*tp_hash*/
6483 0, /* tp_call */
6484 0, /* tp_str */
6485 0, /* tp_getattro */
6486 0, /* tp_setattro */
6487 0, /* tp_as_buffer */
6488 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6489 0, /* tp_doc */
6490 0, /* tp_traverse */
6491 0, /* tp_clear */
6492 0, /* tp_richcompare */
6493 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
6496 #if (DBVER >= 43)
6497 statichere PyTypeObject DBSequence_Type = {
6498 PyObject_HEAD_INIT(NULL)
6499 0, /*ob_size*/
6500 "DBSequence", /*tp_name*/
6501 sizeof(DBSequenceObject), /*tp_basicsize*/
6502 0, /*tp_itemsize*/
6503 /* methods */
6504 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6505 0, /*tp_print*/
6506 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
6507 0, /*tp_setattr*/
6508 0, /*tp_compare*/
6509 0, /*tp_repr*/
6510 0, /*tp_as_number*/
6511 0, /*tp_as_sequence*/
6512 0, /*tp_as_mapping*/
6513 0, /*tp_hash*/
6514 0, /* tp_call */
6515 0, /* tp_str */
6516 0, /* tp_getattro */
6517 0, /* tp_setattro */
6518 0, /* tp_as_buffer */
6519 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6520 0, /* tp_doc */
6521 0, /* tp_traverse */
6522 0, /* tp_clear */
6523 0, /* tp_richcompare */
6524 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
6526 #endif
6528 /* --------------------------------------------------------------------- */
6529 /* Module-level functions */
6531 static PyObject*
6532 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6534 PyObject* dbenvobj = NULL;
6535 int flags = 0;
6536 static char* kwnames[] = { "dbEnv", "flags", NULL};
6538 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6539 &dbenvobj, &flags))
6540 return NULL;
6541 if (dbenvobj == Py_None)
6542 dbenvobj = NULL;
6543 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6544 makeTypeError("DBEnv", dbenvobj);
6545 return NULL;
6548 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6552 static PyObject*
6553 DBEnv_construct(PyObject* self, PyObject* args)
6555 int flags = 0;
6556 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6557 return (PyObject* )newDBEnvObject(flags);
6560 #if (DBVER >= 43)
6561 static PyObject*
6562 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6564 PyObject* dbobj;
6565 int flags = 0;
6566 static char* kwnames[] = { "db", "flags", NULL};
6568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6569 return NULL;
6570 if (!DBObject_Check(dbobj)) {
6571 makeTypeError("DB", dbobj);
6572 return NULL;
6574 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6576 #endif
6578 static char bsddb_version_doc[] =
6579 "Returns a tuple of major, minor, and patch release numbers of the\n\
6580 underlying DB library.";
6582 static PyObject*
6583 bsddb_version(PyObject* self, PyObject* args)
6585 int major, minor, patch;
6587 if (!PyArg_ParseTuple(args, ":version"))
6588 return NULL;
6589 db_version(&major, &minor, &patch);
6590 return Py_BuildValue("(iii)", major, minor, patch);
6594 /* List of functions defined in the module */
6596 static PyMethodDef bsddb_methods[] = {
6597 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6598 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6599 #if (DBVER >= 43)
6600 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6601 #endif
6602 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
6603 {NULL, NULL} /* sentinel */
6606 /* API structure */
6607 static BSDDB_api bsddb_api;
6610 /* --------------------------------------------------------------------- */
6611 /* Module initialization */
6614 /* Convenience routine to export an integer value.
6615 * Errors are silently ignored, for better or for worse...
6617 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6619 #define MODULE_NAME_MAX_LEN 11
6620 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
6622 DL_EXPORT(void) init_bsddb(void)
6624 PyObject* m;
6625 PyObject* d;
6626 PyObject* pybsddb_version_s = PyBytes_FromString( PY_BSDDB_VERSION );
6627 PyObject* db_version_s = PyBytes_FromString( DB_VERSION_STRING );
6628 PyObject* cvsid_s = PyBytes_FromString( rcs_id );
6629 PyObject* py_api;
6631 /* Initialize the type of the new type objects here; doing it here
6632 is required for portability to Windows without requiring C++. */
6633 Py_TYPE(&DB_Type) = &PyType_Type;
6634 Py_TYPE(&DBCursor_Type) = &PyType_Type;
6635 Py_TYPE(&DBEnv_Type) = &PyType_Type;
6636 Py_TYPE(&DBTxn_Type) = &PyType_Type;
6637 Py_TYPE(&DBLock_Type) = &PyType_Type;
6638 #if (DBVER >= 43)
6639 Py_TYPE(&DBSequence_Type) = &PyType_Type;
6640 #endif
6643 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
6644 /* Save the current interpreter, so callbacks can do the right thing. */
6645 _db_interpreterState = PyThreadState_GET()->interp;
6646 #endif
6648 /* Create the module and add the functions */
6649 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
6650 if (m == NULL)
6651 return;
6653 /* Add some symbolic constants to the module */
6654 d = PyModule_GetDict(m);
6655 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
6656 PyDict_SetItemString(d, "cvsid", cvsid_s);
6657 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
6658 Py_DECREF(pybsddb_version_s);
6659 pybsddb_version_s = NULL;
6660 Py_DECREF(cvsid_s);
6661 cvsid_s = NULL;
6662 Py_DECREF(db_version_s);
6663 db_version_s = NULL;
6665 ADD_INT(d, DB_VERSION_MAJOR);
6666 ADD_INT(d, DB_VERSION_MINOR);
6667 ADD_INT(d, DB_VERSION_PATCH);
6669 ADD_INT(d, DB_MAX_PAGES);
6670 ADD_INT(d, DB_MAX_RECORDS);
6672 #if (DBVER >= 42)
6673 ADD_INT(d, DB_RPCCLIENT);
6674 #else
6675 ADD_INT(d, DB_CLIENT);
6676 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
6677 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
6678 #endif
6679 ADD_INT(d, DB_XA_CREATE);
6681 ADD_INT(d, DB_CREATE);
6682 ADD_INT(d, DB_NOMMAP);
6683 ADD_INT(d, DB_THREAD);
6684 #if (DBVER >= 45)
6685 ADD_INT(d, DB_MULTIVERSION);
6686 #endif
6688 ADD_INT(d, DB_FORCE);
6689 ADD_INT(d, DB_INIT_CDB);
6690 ADD_INT(d, DB_INIT_LOCK);
6691 ADD_INT(d, DB_INIT_LOG);
6692 ADD_INT(d, DB_INIT_MPOOL);
6693 ADD_INT(d, DB_INIT_TXN);
6694 ADD_INT(d, DB_JOINENV);
6696 #if (DBVER >= 40)
6697 ADD_INT(d, DB_XIDDATASIZE);
6698 #endif
6700 ADD_INT(d, DB_RECOVER);
6701 ADD_INT(d, DB_RECOVER_FATAL);
6702 ADD_INT(d, DB_TXN_NOSYNC);
6703 ADD_INT(d, DB_USE_ENVIRON);
6704 ADD_INT(d, DB_USE_ENVIRON_ROOT);
6706 ADD_INT(d, DB_LOCKDOWN);
6707 ADD_INT(d, DB_PRIVATE);
6708 ADD_INT(d, DB_SYSTEM_MEM);
6710 ADD_INT(d, DB_TXN_SYNC);
6711 ADD_INT(d, DB_TXN_NOWAIT);
6713 ADD_INT(d, DB_EXCL);
6714 ADD_INT(d, DB_FCNTL_LOCKING);
6715 ADD_INT(d, DB_ODDFILESIZE);
6716 ADD_INT(d, DB_RDWRMASTER);
6717 ADD_INT(d, DB_RDONLY);
6718 ADD_INT(d, DB_TRUNCATE);
6719 ADD_INT(d, DB_EXTENT);
6720 ADD_INT(d, DB_CDB_ALLDB);
6721 ADD_INT(d, DB_VERIFY);
6722 ADD_INT(d, DB_UPGRADE);
6724 ADD_INT(d, DB_AGGRESSIVE);
6725 ADD_INT(d, DB_NOORDERCHK);
6726 ADD_INT(d, DB_ORDERCHKONLY);
6727 ADD_INT(d, DB_PR_PAGE);
6728 #if ! (DBVER >= 33)
6729 ADD_INT(d, DB_VRFY_FLAGMASK);
6730 ADD_INT(d, DB_PR_HEADERS);
6731 #endif
6732 ADD_INT(d, DB_PR_RECOVERYTEST);
6733 ADD_INT(d, DB_SALVAGE);
6735 ADD_INT(d, DB_LOCK_NORUN);
6736 ADD_INT(d, DB_LOCK_DEFAULT);
6737 ADD_INT(d, DB_LOCK_OLDEST);
6738 ADD_INT(d, DB_LOCK_RANDOM);
6739 ADD_INT(d, DB_LOCK_YOUNGEST);
6740 #if (DBVER >= 33)
6741 ADD_INT(d, DB_LOCK_MAXLOCKS);
6742 ADD_INT(d, DB_LOCK_MINLOCKS);
6743 ADD_INT(d, DB_LOCK_MINWRITE);
6744 #endif
6746 #if (DBVER >= 40)
6747 ADD_INT(d, DB_LOCK_EXPIRE);
6748 #endif
6749 #if (DBVER >= 43)
6750 ADD_INT(d, DB_LOCK_MAXWRITE);
6751 #endif
6754 #if (DBVER >= 33)
6755 /* docs say to use zero instead */
6756 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
6757 #else
6758 ADD_INT(d, DB_LOCK_CONFLICT);
6759 #endif
6761 ADD_INT(d, DB_LOCK_DUMP);
6762 ADD_INT(d, DB_LOCK_GET);
6763 ADD_INT(d, DB_LOCK_INHERIT);
6764 ADD_INT(d, DB_LOCK_PUT);
6765 ADD_INT(d, DB_LOCK_PUT_ALL);
6766 ADD_INT(d, DB_LOCK_PUT_OBJ);
6768 ADD_INT(d, DB_LOCK_NG);
6769 ADD_INT(d, DB_LOCK_READ);
6770 ADD_INT(d, DB_LOCK_WRITE);
6771 ADD_INT(d, DB_LOCK_NOWAIT);
6772 ADD_INT(d, DB_LOCK_WAIT);
6773 ADD_INT(d, DB_LOCK_IWRITE);
6774 ADD_INT(d, DB_LOCK_IREAD);
6775 ADD_INT(d, DB_LOCK_IWR);
6776 #if (DBVER >= 33)
6777 #if (DBVER < 44)
6778 ADD_INT(d, DB_LOCK_DIRTY);
6779 #else
6780 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
6781 #endif
6782 ADD_INT(d, DB_LOCK_WWRITE);
6783 #endif
6785 ADD_INT(d, DB_LOCK_RECORD);
6786 ADD_INT(d, DB_LOCK_UPGRADE);
6787 ADD_INT(d, DB_LOCK_SWITCH);
6788 #if (DBVER >= 33)
6789 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
6790 #endif
6792 ADD_INT(d, DB_LOCK_NOWAIT);
6793 ADD_INT(d, DB_LOCK_RECORD);
6794 ADD_INT(d, DB_LOCK_UPGRADE);
6796 #if (DBVER >= 33)
6797 ADD_INT(d, DB_LSTAT_ABORTED);
6798 #if (DBVER < 43)
6799 ADD_INT(d, DB_LSTAT_ERR);
6800 #endif
6801 ADD_INT(d, DB_LSTAT_FREE);
6802 ADD_INT(d, DB_LSTAT_HELD);
6803 #if (DBVER == 33)
6804 ADD_INT(d, DB_LSTAT_NOGRANT);
6805 #endif
6806 ADD_INT(d, DB_LSTAT_PENDING);
6807 ADD_INT(d, DB_LSTAT_WAITING);
6808 #endif
6810 ADD_INT(d, DB_ARCH_ABS);
6811 ADD_INT(d, DB_ARCH_DATA);
6812 ADD_INT(d, DB_ARCH_LOG);
6813 #if (DBVER >= 42)
6814 ADD_INT(d, DB_ARCH_REMOVE);
6815 #endif
6817 ADD_INT(d, DB_BTREE);
6818 ADD_INT(d, DB_HASH);
6819 ADD_INT(d, DB_RECNO);
6820 ADD_INT(d, DB_QUEUE);
6821 ADD_INT(d, DB_UNKNOWN);
6823 ADD_INT(d, DB_DUP);
6824 ADD_INT(d, DB_DUPSORT);
6825 ADD_INT(d, DB_RECNUM);
6826 ADD_INT(d, DB_RENUMBER);
6827 ADD_INT(d, DB_REVSPLITOFF);
6828 ADD_INT(d, DB_SNAPSHOT);
6830 ADD_INT(d, DB_JOIN_NOSORT);
6832 ADD_INT(d, DB_AFTER);
6833 ADD_INT(d, DB_APPEND);
6834 ADD_INT(d, DB_BEFORE);
6835 #if (DBVER < 45)
6836 ADD_INT(d, DB_CACHED_COUNTS);
6837 #endif
6839 #if (DBVER >= 41)
6840 _addIntToDict(d, "DB_CHECKPOINT", 0);
6841 #else
6842 ADD_INT(d, DB_CHECKPOINT);
6843 ADD_INT(d, DB_CURLSN);
6844 #endif
6845 #if ((DBVER >= 33) && (DBVER <= 41))
6846 ADD_INT(d, DB_COMMIT);
6847 #endif
6848 ADD_INT(d, DB_CONSUME);
6849 ADD_INT(d, DB_CONSUME_WAIT);
6850 ADD_INT(d, DB_CURRENT);
6851 #if (DBVER >= 33)
6852 ADD_INT(d, DB_FAST_STAT);
6853 #endif
6854 ADD_INT(d, DB_FIRST);
6855 ADD_INT(d, DB_FLUSH);
6856 ADD_INT(d, DB_GET_BOTH);
6857 ADD_INT(d, DB_GET_RECNO);
6858 ADD_INT(d, DB_JOIN_ITEM);
6859 ADD_INT(d, DB_KEYFIRST);
6860 ADD_INT(d, DB_KEYLAST);
6861 ADD_INT(d, DB_LAST);
6862 ADD_INT(d, DB_NEXT);
6863 ADD_INT(d, DB_NEXT_DUP);
6864 ADD_INT(d, DB_NEXT_NODUP);
6865 ADD_INT(d, DB_NODUPDATA);
6866 ADD_INT(d, DB_NOOVERWRITE);
6867 ADD_INT(d, DB_NOSYNC);
6868 ADD_INT(d, DB_POSITION);
6869 ADD_INT(d, DB_PREV);
6870 ADD_INT(d, DB_PREV_NODUP);
6871 #if (DBVER < 45)
6872 ADD_INT(d, DB_RECORDCOUNT);
6873 #endif
6874 ADD_INT(d, DB_SET);
6875 ADD_INT(d, DB_SET_RANGE);
6876 ADD_INT(d, DB_SET_RECNO);
6877 ADD_INT(d, DB_WRITECURSOR);
6879 ADD_INT(d, DB_OPFLAGS_MASK);
6880 ADD_INT(d, DB_RMW);
6881 #if (DBVER >= 33)
6882 ADD_INT(d, DB_DIRTY_READ);
6883 ADD_INT(d, DB_MULTIPLE);
6884 ADD_INT(d, DB_MULTIPLE_KEY);
6885 #endif
6887 #if (DBVER >= 44)
6888 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
6889 ADD_INT(d, DB_READ_COMMITTED);
6890 #endif
6892 #if (DBVER >= 33)
6893 ADD_INT(d, DB_DONOTINDEX);
6894 #endif
6896 #if (DBVER >= 41)
6897 _addIntToDict(d, "DB_INCOMPLETE", 0);
6898 #else
6899 ADD_INT(d, DB_INCOMPLETE);
6900 #endif
6901 ADD_INT(d, DB_KEYEMPTY);
6902 ADD_INT(d, DB_KEYEXIST);
6903 ADD_INT(d, DB_LOCK_DEADLOCK);
6904 ADD_INT(d, DB_LOCK_NOTGRANTED);
6905 ADD_INT(d, DB_NOSERVER);
6906 ADD_INT(d, DB_NOSERVER_HOME);
6907 ADD_INT(d, DB_NOSERVER_ID);
6908 ADD_INT(d, DB_NOTFOUND);
6909 ADD_INT(d, DB_OLD_VERSION);
6910 ADD_INT(d, DB_RUNRECOVERY);
6911 ADD_INT(d, DB_VERIFY_BAD);
6912 #if (DBVER >= 33)
6913 ADD_INT(d, DB_PAGE_NOTFOUND);
6914 ADD_INT(d, DB_SECONDARY_BAD);
6915 #endif
6916 #if (DBVER >= 40)
6917 ADD_INT(d, DB_STAT_CLEAR);
6918 ADD_INT(d, DB_REGION_INIT);
6919 ADD_INT(d, DB_NOLOCKING);
6920 ADD_INT(d, DB_YIELDCPU);
6921 ADD_INT(d, DB_PANIC_ENVIRONMENT);
6922 ADD_INT(d, DB_NOPANIC);
6923 #endif
6925 #if (DBVER >= 41)
6926 ADD_INT(d, DB_OVERWRITE);
6927 #endif
6929 #ifdef DB_REGISTER
6930 ADD_INT(d, DB_REGISTER);
6931 #endif
6933 #if (DBVER >= 42)
6934 ADD_INT(d, DB_TIME_NOTGRANTED);
6935 ADD_INT(d, DB_TXN_NOT_DURABLE);
6936 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
6937 ADD_INT(d, DB_DIRECT_DB);
6938 ADD_INT(d, DB_INIT_REP);
6939 ADD_INT(d, DB_ENCRYPT);
6940 ADD_INT(d, DB_CHKSUM);
6941 #endif
6943 #if (DBVER >= 42) && (DBVER < 47)
6944 ADD_INT(d, DB_LOG_AUTOREMOVE);
6945 ADD_INT(d, DB_DIRECT_LOG);
6946 #endif
6948 #if (DBVER >= 47)
6949 ADD_INT(d, DB_LOG_DIRECT);
6950 ADD_INT(d, DB_LOG_DSYNC);
6951 ADD_INT(d, DB_LOG_IN_MEMORY);
6952 ADD_INT(d, DB_LOG_AUTO_REMOVE);
6953 ADD_INT(d, DB_LOG_ZERO);
6954 #endif
6956 #if (DBVER >= 44)
6957 ADD_INT(d, DB_DSYNC_DB);
6958 #endif
6960 #if (DBVER >= 45)
6961 ADD_INT(d, DB_TXN_SNAPSHOT);
6962 #endif
6964 #if (DBVER >= 40)
6965 ADD_INT(d, DB_VERB_DEADLOCK);
6966 #if (DBVER >= 46)
6967 ADD_INT(d, DB_VERB_FILEOPS);
6968 ADD_INT(d, DB_VERB_FILEOPS_ALL);
6969 #endif
6970 ADD_INT(d, DB_VERB_RECOVERY);
6971 #if (DBVER >= 44)
6972 ADD_INT(d, DB_VERB_REGISTER);
6973 #endif
6974 ADD_INT(d, DB_VERB_REPLICATION);
6975 ADD_INT(d, DB_VERB_WAITSFOR);
6976 #endif
6978 #if (DBVER >= 45)
6979 ADD_INT(d, DB_EVENT_PANIC);
6980 ADD_INT(d, DB_EVENT_REP_CLIENT);
6981 #if (DBVER >= 46)
6982 ADD_INT(d, DB_EVENT_REP_ELECTED);
6983 #endif
6984 ADD_INT(d, DB_EVENT_REP_MASTER);
6985 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
6986 #if (DBVER >= 46)
6987 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
6988 #endif
6989 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
6990 ADD_INT(d, DB_EVENT_WRITE_FAILED);
6991 #endif
6993 #if (DBVER >= 40)
6994 ADD_INT(d, DB_REP_MASTER);
6995 ADD_INT(d, DB_REP_CLIENT);
6996 #if (DBVER >= 45)
6997 ADD_INT(d, DB_REP_ELECTION);
6999 ADD_INT(d, DB_REP_ACK_TIMEOUT);
7000 ADD_INT(d, DB_REP_CONNECTION_RETRY);
7001 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
7002 ADD_INT(d, DB_REP_ELECTION_RETRY);
7003 #endif
7004 #if (DBVER >= 46)
7005 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
7006 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
7007 #endif
7008 #endif
7010 #if (DBVER >= 45)
7011 ADD_INT(d, DB_REPMGR_PEER);
7012 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7013 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7014 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7015 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7016 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7017 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7018 ADD_INT(d, DB_REPMGR_CONNECTED);
7019 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7020 ADD_INT(d, DB_STAT_CLEAR);
7021 ADD_INT(d, DB_STAT_ALL);
7022 #endif
7024 #if (DBVER >= 43)
7025 ADD_INT(d, DB_BUFFER_SMALL);
7026 ADD_INT(d, DB_SEQ_DEC);
7027 ADD_INT(d, DB_SEQ_INC);
7028 ADD_INT(d, DB_SEQ_WRAP);
7029 #endif
7031 #if (DBVER >= 43) && (DBVER < 47)
7032 ADD_INT(d, DB_LOG_INMEMORY);
7033 ADD_INT(d, DB_DSYNC_LOG);
7034 #endif
7036 #if (DBVER >= 41)
7037 ADD_INT(d, DB_ENCRYPT_AES);
7038 ADD_INT(d, DB_AUTO_COMMIT);
7039 #else
7040 /* allow Berkeley DB 4.1 aware apps to run on older versions */
7041 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7042 #endif
7044 ADD_INT(d, EINVAL);
7045 ADD_INT(d, EACCES);
7046 ADD_INT(d, ENOSPC);
7047 ADD_INT(d, ENOMEM);
7048 ADD_INT(d, EAGAIN);
7049 ADD_INT(d, EBUSY);
7050 ADD_INT(d, EEXIST);
7051 ADD_INT(d, ENOENT);
7052 ADD_INT(d, EPERM);
7054 #if (DBVER >= 40)
7055 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7056 ADD_INT(d, DB_SET_TXN_TIMEOUT);
7057 #endif
7059 /* The exception name must be correct for pickled exception *
7060 * objects to unpickle properly. */
7061 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7062 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7063 #else
7064 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7065 #endif
7067 /* All the rest of the exceptions derive only from DBError */
7068 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7069 PyDict_SetItemString(d, #name, name)
7071 /* The base exception class is DBError */
7072 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7073 MAKE_EX(DBError);
7075 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7076 * from both DBError and KeyError, since the API only supports
7077 * using one base class. */
7078 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
7079 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7080 "class DBKeyEmptyError(DBError, KeyError): pass",
7081 Py_file_input, d, d);
7082 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
7083 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
7084 PyDict_DelItemString(d, "KeyError");
7087 #if !INCOMPLETE_IS_WARNING
7088 MAKE_EX(DBIncompleteError);
7089 #endif
7090 MAKE_EX(DBCursorClosedError);
7091 MAKE_EX(DBKeyEmptyError);
7092 MAKE_EX(DBKeyExistError);
7093 MAKE_EX(DBLockDeadlockError);
7094 MAKE_EX(DBLockNotGrantedError);
7095 MAKE_EX(DBOldVersionError);
7096 MAKE_EX(DBRunRecoveryError);
7097 MAKE_EX(DBVerifyBadError);
7098 MAKE_EX(DBNoServerError);
7099 MAKE_EX(DBNoServerHomeError);
7100 MAKE_EX(DBNoServerIDError);
7101 #if (DBVER >= 33)
7102 MAKE_EX(DBPageNotFoundError);
7103 MAKE_EX(DBSecondaryBadError);
7104 #endif
7106 MAKE_EX(DBInvalidArgError);
7107 MAKE_EX(DBAccessError);
7108 MAKE_EX(DBNoSpaceError);
7109 MAKE_EX(DBNoMemoryError);
7110 MAKE_EX(DBAgainError);
7111 MAKE_EX(DBBusyError);
7112 MAKE_EX(DBFileExistsError);
7113 MAKE_EX(DBNoSuchFileError);
7114 MAKE_EX(DBPermissionsError);
7116 #if (DBVER >= 42)
7117 MAKE_EX(DBRepHandleDeadError);
7118 #endif
7120 #undef MAKE_EX
7122 /* Initiliase the C API structure and add it to the module */
7123 bsddb_api.db_type = &DB_Type;
7124 bsddb_api.dbcursor_type = &DBCursor_Type;
7125 bsddb_api.dbenv_type = &DBEnv_Type;
7126 bsddb_api.dbtxn_type = &DBTxn_Type;
7127 bsddb_api.dblock_type = &DBLock_Type;
7128 #if (DBVER >= 43)
7129 bsddb_api.dbsequence_type = &DBSequence_Type;
7130 #endif
7131 bsddb_api.makeDBError = makeDBError;
7133 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7134 PyDict_SetItemString(d, "api", py_api);
7135 Py_DECREF(py_api);
7137 /* Check for errors */
7138 if (PyErr_Occurred()) {
7139 PyErr_Print();
7140 Py_FatalError("can't initialize module _bsddb");
7144 /* allow this module to be named _pybsddb so that it can be installed
7145 * and imported on top of python >= 2.3 that includes its own older
7146 * copy of the library named _bsddb without importing the old version. */
7147 DL_EXPORT(void) init_pybsddb(void)
7149 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7150 init_bsddb();