Minor fix for currentframe (SF #1652788).
[python.git] / Modules / _bsddb.c
blob23fa573fadebb6be19833ae431e303d7126667b7
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 BerkeleyDB 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 <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped 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@electricrain.com> is once again the maintainer.
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
54 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
57 * http://pybsddb.sf.net
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
62 * http://www.python.org/peps/pep-0291.html
64 * This module contains 6 types:
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 * DBSequence (Sequence)
75 /* --------------------------------------------------------------------- */
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
83 * --Robin
86 /* --------------------------------------------------------------------- */
88 #include <stddef.h> /* for offsetof() */
89 #include <Python.h>
90 #include <db.h>
92 /* --------------------------------------------------------------------- */
93 /* Various macro definitions */
95 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
97 #if DB_VERSION_MINOR > 9
98 #error "eek! DBVER can't handle minor versions > 9"
99 #endif
101 #define PY_BSDDB_VERSION "4.5.0"
102 static char *rcs_id = "$Id$";
105 #if (PY_VERSION_HEX < 0x02050000)
106 typedef int Py_ssize_t;
107 #endif
109 #ifdef WITH_THREAD
111 /* These are for when calling Python --> C */
112 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
115 /* For 2.3, use the PyGILState_ calls */
116 #if (PY_VERSION_HEX >= 0x02030000)
117 #define MYDB_USE_GILSTATE
118 #endif
120 /* and these are for calling C --> Python */
121 #if defined(MYDB_USE_GILSTATE)
122 #define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124 #define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126 #else /* MYDB_USE_GILSTATE */
127 /* Pre GILState API - do it the long old way */
128 static PyInterpreterState* _db_interpreterState = NULL;
129 #define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
136 #define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
142 #endif /* MYDB_USE_GILSTATE */
144 #else
145 /* Compiled without threads - avoid all this cruft */
146 #define MYDB_BEGIN_ALLOW_THREADS
147 #define MYDB_END_ALLOW_THREADS
148 #define MYDB_BEGIN_BLOCK_THREADS
149 #define MYDB_END_BLOCK_THREADS
151 #endif
153 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
154 #define INCOMPLETE_IS_WARNING 1
156 /* --------------------------------------------------------------------- */
157 /* Exceptions */
159 static PyObject* DBError; /* Base class, all others derive from this */
160 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
161 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
162 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169 static PyObject* DBNoServerError; /* DB_NOSERVER */
170 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172 #if (DBVER >= 33)
173 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175 #endif
177 #if !INCOMPLETE_IS_WARNING
178 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179 #endif
181 static PyObject* DBInvalidArgError; /* EINVAL */
182 static PyObject* DBAccessError; /* EACCES */
183 static PyObject* DBNoSpaceError; /* ENOSPC */
184 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
185 static PyObject* DBAgainError; /* EAGAIN */
186 static PyObject* DBBusyError; /* EBUSY */
187 static PyObject* DBFileExistsError; /* EEXIST */
188 static PyObject* DBNoSuchFileError; /* ENOENT */
189 static PyObject* DBPermissionsError; /* EPERM */
191 #if (DBVER < 43)
192 #define DB_BUFFER_SMALL ENOMEM
193 #endif
196 /* --------------------------------------------------------------------- */
197 /* Structure definitions */
199 #if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200 #define HAVE_WEAKREF
201 #else
202 #undef HAVE_WEAKREF
203 #endif
205 /* if Python >= 2.1 better support warnings */
206 #if PYTHON_API_VERSION >= 1010
207 #define HAVE_WARNINGS
208 #else
209 #undef HAVE_WARNINGS
210 #endif
212 #if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214 #define PyObject_New PyObject_NEW
215 #define PyObject_Del PyMem_DEL
216 #endif
218 struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
224 unsigned int cursorSetReturnsNone : 1;
227 #define DEFAULT_GET_RETURNS_NONE 1
228 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
230 typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
233 u_int32_t flags; /* saved flags from open() */
234 int closed;
235 struct behaviourFlags moduleFlags;
236 #ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238 #endif
239 } DBEnvObject;
242 typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
248 int haveStat;
249 struct behaviourFlags moduleFlags;
250 #if (DBVER >= 33)
251 PyObject* associateCallback;
252 PyObject* btCompareCallback;
253 int primaryDBType;
254 #endif
255 #ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257 #endif
258 } DBObject;
261 typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
265 #ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267 #endif
268 } DBCursorObject;
271 typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
274 PyObject *env;
275 #ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277 #endif
278 } DBTxnObject;
281 typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
284 #ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286 #endif
287 } DBLockObject;
289 #if (DBVER >= 43)
290 typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294 #ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296 #endif
297 } DBSequenceObject;
298 staticforward PyTypeObject DBSequence_Type;
299 #endif
301 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
303 #define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304 #define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305 #define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306 #define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307 #define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
308 #if (DBVER >= 43)
309 #define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310 #endif
313 /* --------------------------------------------------------------------- */
314 /* Utility macros and functions */
316 #define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
321 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
323 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
332 #define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
335 #define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
338 #define CHECK_CURSOR_NOT_CLOSED(curs) \
339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
341 #if (DBVER >= 43)
342 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344 #endif
346 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
349 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
351 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
355 static int makeDBError(int err);
358 /* Return the access method type of the DBObject */
359 static int _DB_get_type(DBObject* self)
361 #if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
368 return type;
369 #else
370 return self->db->get_type(self->db);
371 #endif
375 /* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377 static int make_dbt(PyObject* obj, DBT* dbt)
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
385 "Data values must be of type string or None.");
386 return 0;
388 return 1;
392 /* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
395 Caller MUST call FREE_DBT(key) when done. */
396 static int
397 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
399 db_recno_t recno;
400 int type;
402 CLEAR_DBT(*key);
403 if (keyobj == Py_None) {
404 type = _DB_get_type(self);
405 if (type == -1)
406 return 0;
407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
413 /* no need to do anything, the structure has already been zeroed */
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
425 return 0;
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
440 *pflags |= DB_SET_RECNO;
442 else if (type != DB_RECNO && type != DB_QUEUE) {
443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
446 return 0;
449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
468 return 1;
472 /* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475 static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
492 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493 /* TODO: make this use the native libc strlcpy() when available (BSD) */
494 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
496 unsigned int srclen, copylen;
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
507 return srclen;
510 /* Callback used to save away more information about errors from the DB
511 * library. */
512 static char _db_errmsg[1024];
513 #if (DBVER <= 42)
514 static void _db_errorCallback(const char* prefix, char* msg)
515 #else
516 static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518 #endif
520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
524 /* make a nice exception object to raise for errors. */
525 static int makeDBError(int err)
527 char errTxt[2048]; /* really big, just in case... */
528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
530 int exceptionRaised = 0;
531 unsigned int bytes_left;
533 switch (err) {
534 case 0: /* successful, no error */ break;
536 #if (DBVER < 41)
537 case DB_INCOMPLETE:
538 #if INCOMPLETE_IS_WARNING
539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
544 strcat(errTxt, " -- ");
545 strncat(errTxt, _db_errmsg, bytes_left);
547 _db_errmsg[0] = 0;
548 #ifdef HAVE_WARNINGS
549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550 #else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553 #endif
555 #else /* do an exception instead */
556 errObj = DBIncompleteError;
557 #endif
558 break;
559 #endif /* DBVER < 41 */
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572 #if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575 #endif
576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
578 #if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581 #endif
582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
591 default: errObj = DBError; break;
594 if (errObj != NULL) {
595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
600 strcat(errTxt, " -- ");
601 strncat(errTxt, _db_errmsg, bytes_left);
603 _db_errmsg[0] = 0;
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
610 return ((errObj != NULL) || exceptionRaised);
615 /* set a type exception */
616 static void makeTypeError(char* expected, PyObject* found)
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
623 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
624 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
640 /* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
644 int err;
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
652 self->haveStat = 0;
653 return 0;
657 /* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
661 int err;
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
669 self->haveStat = 0;
670 return 0;
673 /* Get a key/data pair from a cursor */
674 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
689 CHECK_CURSOR_NOT_CLOSED(self);
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
708 Py_INCREF(Py_None);
709 retval = Py_None;
711 else if (makeDBError(err)) {
712 retval = NULL;
714 else { /* otherwise, success! */
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
739 return retval;
743 /* add an integer to a dictionary using the given name as a key */
744 static void _addIntToDict(PyObject* dict, char *name, int value)
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
750 Py_XDECREF(v);
752 #if (DBVER >= 43)
753 /* add an db_seq_t to a dictionary using the given name as a key */
754 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
756 PyObject* v = PyLong_FromLongLong(value);
757 if (!v || PyDict_SetItemString(dict, name, v))
758 PyErr_Clear();
760 Py_XDECREF(v);
762 #endif
766 /* --------------------------------------------------------------------- */
767 /* Allocators and deallocators */
769 static DBObject*
770 newDBObject(DBEnvObject* arg, int flags)
772 DBObject* self;
773 DB_ENV* db_env = NULL;
774 int err;
776 self = PyObject_New(DBObject, &DB_Type);
777 if (self == NULL)
778 return NULL;
780 self->haveStat = 0;
781 self->flags = 0;
782 self->setflags = 0;
783 self->myenvobj = NULL;
784 #if (DBVER >= 33)
785 self->associateCallback = NULL;
786 self->btCompareCallback = NULL;
787 self->primaryDBType = 0;
788 #endif
789 #ifdef HAVE_WEAKREF
790 self->in_weakreflist = NULL;
791 #endif
793 /* keep a reference to our python DBEnv object */
794 if (arg) {
795 Py_INCREF(arg);
796 self->myenvobj = arg;
797 db_env = arg->db_env;
800 if (self->myenvobj)
801 self->moduleFlags = self->myenvobj->moduleFlags;
802 else
803 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
804 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = db_create(&self->db, db_env, flags);
808 if (self->db != NULL) {
809 self->db->set_errcall(self->db, _db_errorCallback);
810 #if (DBVER >= 33)
811 self->db->app_private = (void*)self;
812 #endif
814 MYDB_END_ALLOW_THREADS;
815 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
816 * list so that a DBEnv can refuse to close without aborting any open
817 * DBTxns and closing any open DBs first. */
818 if (makeDBError(err)) {
819 if (self->myenvobj) {
820 Py_DECREF(self->myenvobj);
821 self->myenvobj = NULL;
823 PyObject_Del(self);
824 self = NULL;
826 return self;
830 static void
831 DB_dealloc(DBObject* self)
833 if (self->db != NULL) {
834 /* avoid closing a DB when its DBEnv has been closed out from under
835 * it */
836 if (!self->myenvobj ||
837 (self->myenvobj && self->myenvobj->db_env))
839 MYDB_BEGIN_ALLOW_THREADS;
840 self->db->close(self->db, 0);
841 MYDB_END_ALLOW_THREADS;
842 #ifdef HAVE_WARNINGS
843 } else {
844 PyErr_Warn(PyExc_RuntimeWarning,
845 "DB could not be closed in destructor: DBEnv already closed");
846 #endif
848 self->db = NULL;
850 #ifdef HAVE_WEAKREF
851 if (self->in_weakreflist != NULL) {
852 PyObject_ClearWeakRefs((PyObject *) self);
854 #endif
855 if (self->myenvobj) {
856 Py_DECREF(self->myenvobj);
857 self->myenvobj = NULL;
859 #if (DBVER >= 33)
860 if (self->associateCallback != NULL) {
861 Py_DECREF(self->associateCallback);
862 self->associateCallback = NULL;
864 if (self->btCompareCallback != NULL) {
865 Py_DECREF(self->btCompareCallback);
866 self->btCompareCallback = NULL;
868 #endif
869 PyObject_Del(self);
873 static DBCursorObject*
874 newDBCursorObject(DBC* dbc, DBObject* db)
876 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
877 if (self == NULL)
878 return NULL;
880 self->dbc = dbc;
881 self->mydb = db;
882 #ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884 #endif
885 Py_INCREF(self->mydb);
886 return self;
890 static void
891 DBCursor_dealloc(DBCursorObject* self)
893 int err;
895 #ifdef HAVE_WEAKREF
896 if (self->in_weakreflist != NULL) {
897 PyObject_ClearWeakRefs((PyObject *) self);
899 #endif
901 if (self->dbc != NULL) {
902 MYDB_BEGIN_ALLOW_THREADS;
903 /* If the underlying database has been closed, we don't
904 need to do anything. If the environment has been closed
905 we need to leak, as BerkeleyDB will crash trying to access
906 the environment. There was an exception when the
907 user closed the environment even though there still was
908 a database open. */
909 if (self->mydb->db && self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed)
911 err = self->dbc->c_close(self->dbc);
912 self->dbc = NULL;
913 MYDB_END_ALLOW_THREADS;
915 Py_XDECREF( self->mydb );
916 PyObject_Del(self);
920 static DBEnvObject*
921 newDBEnvObject(int flags)
923 int err;
924 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
925 if (self == NULL)
926 return NULL;
928 self->closed = 1;
929 self->flags = flags;
930 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
931 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
932 #ifdef HAVE_WEAKREF
933 self->in_weakreflist = NULL;
934 #endif
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
940 PyObject_Del(self);
941 self = NULL;
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
946 return self;
950 static void
951 DBEnv_dealloc(DBEnvObject* self)
953 #ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
957 #endif
959 if (self->db_env && !self->closed) {
960 MYDB_BEGIN_ALLOW_THREADS;
961 self->db_env->close(self->db_env, 0);
962 MYDB_END_ALLOW_THREADS;
964 PyObject_Del(self);
968 static DBTxnObject*
969 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
971 int err;
972 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
973 if (self == NULL)
974 return NULL;
975 Py_INCREF(myenv);
976 self->env = (PyObject*)myenv;
977 #ifdef HAVE_WEAKREF
978 self->in_weakreflist = NULL;
979 #endif
981 MYDB_BEGIN_ALLOW_THREADS;
982 #if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984 #else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986 #endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
989 Py_DECREF(self->env);
990 PyObject_Del(self);
991 self = NULL;
993 return self;
997 static void
998 DBTxn_dealloc(DBTxnObject* self)
1000 #ifdef HAVE_WEAKREF
1001 if (self->in_weakreflist != NULL) {
1002 PyObject_ClearWeakRefs((PyObject *) self);
1004 #endif
1006 #ifdef HAVE_WARNINGS
1007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010 #if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012 #else
1013 txn_abort(self->txn);
1014 #endif
1015 MYDB_END_ALLOW_THREADS;
1016 PyErr_Warn(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. No prior commit() or abort().");
1019 #endif
1021 Py_DECREF(self->env);
1022 PyObject_Del(self);
1026 static DBLockObject*
1027 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1030 int err;
1031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1032 if (self == NULL)
1033 return NULL;
1034 #ifdef HAVE_WEAKREF
1035 self->in_weakreflist = NULL;
1036 #endif
1038 MYDB_BEGIN_ALLOW_THREADS;
1039 #if (DBVER >= 40)
1040 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1041 &self->lock);
1042 #else
1043 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1044 #endif
1045 MYDB_END_ALLOW_THREADS;
1046 if (makeDBError(err)) {
1047 PyObject_Del(self);
1048 self = NULL;
1051 return self;
1055 static void
1056 DBLock_dealloc(DBLockObject* self)
1058 #ifdef HAVE_WEAKREF
1059 if (self->in_weakreflist != NULL) {
1060 PyObject_ClearWeakRefs((PyObject *) self);
1062 #endif
1063 /* TODO: is this lock held? should we release it? */
1065 PyObject_Del(self);
1069 #if (DBVER >= 43)
1070 static DBSequenceObject*
1071 newDBSequenceObject(DBObject* mydb, int flags)
1073 int err;
1074 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1075 if (self == NULL)
1076 return NULL;
1077 Py_INCREF(mydb);
1078 self->mydb = mydb;
1079 #ifdef HAVE_WEAKREF
1080 self->in_weakreflist = NULL;
1081 #endif
1084 MYDB_BEGIN_ALLOW_THREADS;
1085 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1086 MYDB_END_ALLOW_THREADS;
1087 if (makeDBError(err)) {
1088 Py_DECREF(self->mydb);
1089 PyObject_Del(self);
1090 self = NULL;
1093 return self;
1097 static void
1098 DBSequence_dealloc(DBSequenceObject* self)
1100 #ifdef HAVE_WEAKREF
1101 if (self->in_weakreflist != NULL) {
1102 PyObject_ClearWeakRefs((PyObject *) self);
1104 #endif
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1109 #endif
1111 /* --------------------------------------------------------------------- */
1112 /* DB methods */
1114 static PyObject*
1115 DB_append(DBObject* self, PyObject* args)
1117 PyObject* txnobj = NULL;
1118 PyObject* dataobj;
1119 db_recno_t recno;
1120 DBT key, data;
1121 DB_TXN *txn = NULL;
1123 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1124 return NULL;
1126 CHECK_DB_NOT_CLOSED(self);
1128 /* make a dummy key out of a recno */
1129 recno = 0;
1130 CLEAR_DBT(key);
1131 key.data = &recno;
1132 key.size = sizeof(recno);
1133 key.ulen = key.size;
1134 key.flags = DB_DBT_USERMEM;
1136 if (!make_dbt(dataobj, &data)) return NULL;
1137 if (!checkTxnObj(txnobj, &txn)) return NULL;
1139 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1140 return NULL;
1142 return PyInt_FromLong(recno);
1146 #if (DBVER >= 33)
1148 static int
1149 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1150 DBT* secKey)
1152 int retval = DB_DONOTINDEX;
1153 DBObject* secondaryDB = (DBObject*)db->app_private;
1154 PyObject* callback = secondaryDB->associateCallback;
1155 int type = secondaryDB->primaryDBType;
1156 PyObject* args;
1157 PyObject* result = NULL;
1160 if (callback != NULL) {
1161 MYDB_BEGIN_BLOCK_THREADS;
1163 if (type == DB_RECNO || type == DB_QUEUE)
1164 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1165 priData->data, priData->size);
1166 else
1167 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1168 priData->data, priData->size);
1169 if (args != NULL) {
1170 result = PyEval_CallObject(callback, args);
1172 if (args == NULL || result == NULL) {
1173 PyErr_Print();
1175 else if (result == Py_None) {
1176 retval = DB_DONOTINDEX;
1178 else if (PyInt_Check(result)) {
1179 retval = PyInt_AsLong(result);
1181 else if (PyString_Check(result)) {
1182 char* data;
1183 Py_ssize_t size;
1185 CLEAR_DBT(*secKey);
1186 #if PYTHON_API_VERSION <= 1007
1187 /* 1.5 compatibility */
1188 size = PyString_Size(result);
1189 data = PyString_AsString(result);
1190 #else
1191 PyString_AsStringAndSize(result, &data, &size);
1192 #endif
1193 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1194 secKey->data = malloc(size); /* TODO, check this */
1195 if (secKey->data) {
1196 memcpy(secKey->data, data, size);
1197 secKey->size = size;
1198 retval = 0;
1200 else {
1201 PyErr_SetString(PyExc_MemoryError,
1202 "malloc failed in _db_associateCallback");
1203 PyErr_Print();
1206 else {
1207 PyErr_SetString(
1208 PyExc_TypeError,
1209 "DB associate callback should return DB_DONOTINDEX or string.");
1210 PyErr_Print();
1213 Py_XDECREF(args);
1214 Py_XDECREF(result);
1216 MYDB_END_BLOCK_THREADS;
1218 return retval;
1222 static PyObject*
1223 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1225 int err, flags=0;
1226 DBObject* secondaryDB;
1227 PyObject* callback;
1228 #if (DBVER >= 41)
1229 PyObject *txnobj = NULL;
1230 DB_TXN *txn = NULL;
1231 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1232 NULL};
1233 #else
1234 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1235 #endif
1237 #if (DBVER >= 41)
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1239 &secondaryDB, &callback, &flags,
1240 &txnobj)) {
1241 #else
1242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1243 &secondaryDB, &callback, &flags)) {
1244 #endif
1245 return NULL;
1248 #if (DBVER >= 41)
1249 if (!checkTxnObj(txnobj, &txn)) return NULL;
1250 #endif
1252 CHECK_DB_NOT_CLOSED(self);
1253 if (!DBObject_Check(secondaryDB)) {
1254 makeTypeError("DB", (PyObject*)secondaryDB);
1255 return NULL;
1257 CHECK_DB_NOT_CLOSED(secondaryDB);
1258 if (callback == Py_None) {
1259 callback = NULL;
1261 else if (!PyCallable_Check(callback)) {
1262 makeTypeError("Callable", callback);
1263 return NULL;
1266 /* Save a reference to the callback in the secondary DB. */
1267 Py_XDECREF(secondaryDB->associateCallback);
1268 Py_XINCREF(callback);
1269 secondaryDB->associateCallback = callback;
1270 secondaryDB->primaryDBType = _DB_get_type(self);
1272 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1273 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1274 * The global interepreter lock is not initialized until the first
1275 * thread is created using thread.start_new_thread() or fork() is
1276 * called. that would cause the ALLOW_THREADS here to segfault due
1277 * to a null pointer reference if no threads or child processes
1278 * have been created. This works around that and is a no-op if
1279 * threads have already been initialized.
1280 * (see pybsddb-users mailing list post on 2002-08-07)
1282 #ifdef WITH_THREAD
1283 PyEval_InitThreads();
1284 #endif
1285 MYDB_BEGIN_ALLOW_THREADS;
1286 #if (DBVER >= 41)
1287 err = self->db->associate(self->db,
1288 txn,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
1292 #else
1293 err = self->db->associate(self->db,
1294 secondaryDB->db,
1295 _db_associateCallback,
1296 flags);
1297 #endif
1298 MYDB_END_ALLOW_THREADS;
1300 if (err) {
1301 Py_XDECREF(secondaryDB->associateCallback);
1302 secondaryDB->associateCallback = NULL;
1303 secondaryDB->primaryDBType = 0;
1306 RETURN_IF_ERR();
1307 RETURN_NONE();
1311 #endif
1314 static PyObject*
1315 DB_close(DBObject* self, PyObject* args)
1317 int err, flags=0;
1318 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1319 return NULL;
1320 if (self->db != NULL) {
1321 if (self->myenvobj)
1322 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1323 err = self->db->close(self->db, flags);
1324 self->db = NULL;
1325 RETURN_IF_ERR();
1327 RETURN_NONE();
1331 #if (DBVER >= 32)
1332 static PyObject*
1333 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1335 int err, flags=0, type;
1336 PyObject* txnobj = NULL;
1337 PyObject* retval = NULL;
1338 DBT key, data;
1339 DB_TXN *txn = NULL;
1340 static char* kwnames[] = { "txn", "flags", NULL };
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1343 &txnobj, &flags))
1344 return NULL;
1346 CHECK_DB_NOT_CLOSED(self);
1347 type = _DB_get_type(self);
1348 if (type == -1)
1349 return NULL;
1350 if (type != DB_QUEUE) {
1351 PyErr_SetString(PyExc_TypeError,
1352 "Consume methods only allowed for Queue DB's");
1353 return NULL;
1355 if (!checkTxnObj(txnobj, &txn))
1356 return NULL;
1358 CLEAR_DBT(key);
1359 CLEAR_DBT(data);
1360 if (CHECK_DBFLAG(self, DB_THREAD)) {
1361 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1362 data.flags = DB_DBT_MALLOC;
1363 key.flags = DB_DBT_MALLOC;
1366 MYDB_BEGIN_ALLOW_THREADS;
1367 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1368 MYDB_END_ALLOW_THREADS;
1370 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1371 && self->moduleFlags.getReturnsNone) {
1372 err = 0;
1373 Py_INCREF(Py_None);
1374 retval = Py_None;
1376 else if (!err) {
1377 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1378 data.size);
1379 FREE_DBT(key);
1380 FREE_DBT(data);
1383 RETURN_IF_ERR();
1384 return retval;
1387 static PyObject*
1388 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1390 return _DB_consume(self, args, kwargs, DB_CONSUME);
1393 static PyObject*
1394 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1395 int consume_flag)
1397 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1399 #endif
1403 static PyObject*
1404 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1406 int err, flags=0;
1407 DBC* dbc;
1408 PyObject* txnobj = NULL;
1409 DB_TXN *txn = NULL;
1410 static char* kwnames[] = { "txn", "flags", NULL };
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1413 &txnobj, &flags))
1414 return NULL;
1415 CHECK_DB_NOT_CLOSED(self);
1416 if (!checkTxnObj(txnobj, &txn))
1417 return NULL;
1419 MYDB_BEGIN_ALLOW_THREADS;
1420 err = self->db->cursor(self->db, txn, &dbc, flags);
1421 MYDB_END_ALLOW_THREADS;
1422 RETURN_IF_ERR();
1423 return (PyObject*) newDBCursorObject(dbc, self);
1427 static PyObject*
1428 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1430 PyObject* txnobj = NULL;
1431 int flags = 0;
1432 PyObject* keyobj;
1433 DBT key;
1434 DB_TXN *txn = NULL;
1435 static char* kwnames[] = { "key", "txn", "flags", NULL };
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1438 &keyobj, &txnobj, &flags))
1439 return NULL;
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
1443 if (!checkTxnObj(txnobj, &txn)) {
1444 FREE_DBT(key);
1445 return NULL;
1448 if (-1 == _DB_delete(self, txn, &key, 0)) {
1449 FREE_DBT(key);
1450 return NULL;
1453 FREE_DBT(key);
1454 RETURN_NONE();
1458 static PyObject*
1459 DB_fd(DBObject* self, PyObject* args)
1461 int err, the_fd;
1463 if (!PyArg_ParseTuple(args,":fd"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1467 MYDB_BEGIN_ALLOW_THREADS;
1468 err = self->db->fd(self->db, &the_fd);
1469 MYDB_END_ALLOW_THREADS;
1470 RETURN_IF_ERR();
1471 return PyInt_FromLong(the_fd);
1475 static PyObject*
1476 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1478 int err, flags=0;
1479 PyObject* txnobj = NULL;
1480 PyObject* keyobj;
1481 PyObject* dfltobj = NULL;
1482 PyObject* retval = NULL;
1483 int dlen = -1;
1484 int doff = -1;
1485 DBT key, data;
1486 DB_TXN *txn = NULL;
1487 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1488 "doff", NULL};
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1491 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1492 &doff))
1493 return NULL;
1495 CHECK_DB_NOT_CLOSED(self);
1496 if (!make_key_dbt(self, keyobj, &key, &flags))
1497 return NULL;
1498 if (!checkTxnObj(txnobj, &txn)) {
1499 FREE_DBT(key);
1500 return NULL;
1503 CLEAR_DBT(data);
1504 if (CHECK_DBFLAG(self, DB_THREAD)) {
1505 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1506 data.flags = DB_DBT_MALLOC;
1508 if (!add_partial_dbt(&data, dlen, doff)) {
1509 FREE_DBT(key);
1510 return NULL;
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 err = self->db->get(self->db, txn, &key, &data, flags);
1515 MYDB_END_ALLOW_THREADS;
1517 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1518 err = 0;
1519 Py_INCREF(dfltobj);
1520 retval = dfltobj;
1522 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1523 && self->moduleFlags.getReturnsNone) {
1524 err = 0;
1525 Py_INCREF(Py_None);
1526 retval = Py_None;
1528 else if (!err) {
1529 if (flags & DB_SET_RECNO) /* return both key and data */
1530 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1531 data.size);
1532 else /* return just the data */
1533 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1534 FREE_DBT(data);
1536 FREE_DBT(key);
1538 RETURN_IF_ERR();
1539 return retval;
1542 #if (DBVER >= 33)
1543 static PyObject*
1544 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* dfltobj = NULL;
1550 PyObject* retval = NULL;
1551 int dlen = -1;
1552 int doff = -1;
1553 DBT key, pkey, data;
1554 DB_TXN *txn = NULL;
1555 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1556 "doff", NULL};
1558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1559 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1560 &doff))
1561 return NULL;
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1571 CLEAR_DBT(data);
1572 if (CHECK_DBFLAG(self, DB_THREAD)) {
1573 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1574 data.flags = DB_DBT_MALLOC;
1576 if (!add_partial_dbt(&data, dlen, doff)) {
1577 FREE_DBT(key);
1578 return NULL;
1581 CLEAR_DBT(pkey);
1582 pkey.flags = DB_DBT_MALLOC;
1584 MYDB_BEGIN_ALLOW_THREADS;
1585 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1586 MYDB_END_ALLOW_THREADS;
1588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1589 err = 0;
1590 Py_INCREF(dfltobj);
1591 retval = dfltobj;
1593 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1594 && self->moduleFlags.getReturnsNone) {
1595 err = 0;
1596 Py_INCREF(Py_None);
1597 retval = Py_None;
1599 else if (!err) {
1600 PyObject *pkeyObj;
1601 PyObject *dataObj;
1602 dataObj = PyString_FromStringAndSize(data.data, data.size);
1604 if (self->primaryDBType == DB_RECNO ||
1605 self->primaryDBType == DB_QUEUE)
1606 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1607 else
1608 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1610 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1612 PyObject *keyObj;
1613 int type = _DB_get_type(self);
1614 if (type == DB_RECNO || type == DB_QUEUE)
1615 keyObj = PyInt_FromLong(*(int *)key.data);
1616 else
1617 keyObj = PyString_FromStringAndSize(key.data, key.size);
1618 #if (PY_VERSION_HEX >= 0x02040000)
1619 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1620 #else
1621 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1622 #endif
1623 Py_DECREF(keyObj);
1625 else /* return just the pkey and data */
1627 #if (PY_VERSION_HEX >= 0x02040000)
1628 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1629 #else
1630 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1631 #endif
1633 Py_DECREF(dataObj);
1634 Py_DECREF(pkeyObj);
1635 FREE_DBT(pkey);
1636 FREE_DBT(data);
1638 FREE_DBT(key);
1640 RETURN_IF_ERR();
1641 return retval;
1643 #endif
1646 /* Return size of entry */
1647 static PyObject*
1648 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1650 int err, flags=0;
1651 PyObject* txnobj = NULL;
1652 PyObject* keyobj;
1653 PyObject* retval = NULL;
1654 DBT key, data;
1655 DB_TXN *txn = NULL;
1656 static char* kwnames[] = { "key", "txn", NULL };
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1659 &keyobj, &txnobj))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!make_key_dbt(self, keyobj, &key, &flags))
1663 return NULL;
1664 if (!checkTxnObj(txnobj, &txn)) {
1665 FREE_DBT(key);
1666 return NULL;
1668 CLEAR_DBT(data);
1670 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1671 thus getting the record size. */
1672 data.flags = DB_DBT_USERMEM;
1673 data.ulen = 0;
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->get(self->db, txn, &key, &data, flags);
1676 MYDB_END_ALLOW_THREADS;
1677 if (err == DB_BUFFER_SMALL) {
1678 retval = PyInt_FromLong((long)data.size);
1679 err = 0;
1682 FREE_DBT(key);
1683 FREE_DBT(data);
1684 RETURN_IF_ERR();
1685 return retval;
1689 static PyObject*
1690 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1692 int err, flags=0;
1693 PyObject* txnobj = NULL;
1694 PyObject* keyobj;
1695 PyObject* dataobj;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
1699 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1703 &keyobj, &dataobj, &txnobj, &flags))
1704 return NULL;
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, NULL))
1708 return NULL;
1709 if ( !make_dbt(dataobj, &data) ||
1710 !checkTxnObj(txnobj, &txn) )
1712 FREE_DBT(key);
1713 return NULL;
1716 flags |= DB_GET_BOTH;
1718 if (CHECK_DBFLAG(self, DB_THREAD)) {
1719 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1720 data.flags = DB_DBT_MALLOC;
1721 /* TODO: Is this flag needed? We're passing a data object that should
1722 match what's in the DB, so there should be no need to malloc.
1723 We run the risk of freeing something twice! Check this. */
1726 MYDB_BEGIN_ALLOW_THREADS;
1727 err = self->db->get(self->db, txn, &key, &data, flags);
1728 MYDB_END_ALLOW_THREADS;
1730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
1732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1736 else if (!err) {
1737 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1738 FREE_DBT(data); /* Only if retrieval was successful */
1741 FREE_DBT(key);
1742 RETURN_IF_ERR();
1743 return retval;
1747 static PyObject*
1748 DB_get_byteswapped(DBObject* self, PyObject* args)
1750 #if (DBVER >= 33)
1751 int err = 0;
1752 #endif
1753 int retval = -1;
1755 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1759 #if (DBVER >= 33)
1760 MYDB_BEGIN_ALLOW_THREADS;
1761 err = self->db->get_byteswapped(self->db, &retval);
1762 MYDB_END_ALLOW_THREADS;
1763 RETURN_IF_ERR();
1764 #else
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 retval = self->db->get_byteswapped(self->db);
1767 MYDB_END_ALLOW_THREADS;
1768 #endif
1769 return PyInt_FromLong(retval);
1773 static PyObject*
1774 DB_get_type(DBObject* self, PyObject* args)
1776 int type;
1778 if (!PyArg_ParseTuple(args,":get_type"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1782 type = _DB_get_type(self);
1783 if (type == -1)
1784 return NULL;
1785 return PyInt_FromLong(type);
1789 static PyObject*
1790 DB_join(DBObject* self, PyObject* args)
1792 int err, flags=0;
1793 int length, x;
1794 PyObject* cursorsObj;
1795 DBC** cursors;
1796 DBC* dbc;
1798 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1799 return NULL;
1801 CHECK_DB_NOT_CLOSED(self);
1803 if (!PySequence_Check(cursorsObj)) {
1804 PyErr_SetString(PyExc_TypeError,
1805 "Sequence of DBCursor objects expected");
1806 return NULL;
1809 length = PyObject_Length(cursorsObj);
1810 cursors = malloc((length+1) * sizeof(DBC*));
1811 if (!cursors) {
1812 PyErr_NoMemory();
1813 return NULL;
1816 cursors[length] = NULL;
1817 for (x=0; x<length; x++) {
1818 PyObject* item = PySequence_GetItem(cursorsObj, x);
1819 if (item == NULL) {
1820 free(cursors);
1821 return NULL;
1823 if (!DBCursorObject_Check(item)) {
1824 PyErr_SetString(PyExc_TypeError,
1825 "Sequence of DBCursor objects expected");
1826 free(cursors);
1827 return NULL;
1829 cursors[x] = ((DBCursorObject*)item)->dbc;
1830 Py_DECREF(item);
1833 MYDB_BEGIN_ALLOW_THREADS;
1834 err = self->db->join(self->db, cursors, &dbc, flags);
1835 MYDB_END_ALLOW_THREADS;
1836 free(cursors);
1837 RETURN_IF_ERR();
1839 /* FIXME: this is a buggy interface. The returned cursor
1840 contains internal references to the passed in cursors
1841 but does not hold python references to them or prevent
1842 them from being closed prematurely. This can cause
1843 python to crash when things are done in the wrong order. */
1844 return (PyObject*) newDBCursorObject(dbc, self);
1848 static PyObject*
1849 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1851 int err, flags=0;
1852 PyObject* txnobj = NULL;
1853 PyObject* keyobj;
1854 DBT key;
1855 DB_TXN *txn = NULL;
1856 DB_KEY_RANGE range;
1857 static char* kwnames[] = { "key", "txn", "flags", NULL };
1859 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1860 &keyobj, &txnobj, &flags))
1861 return NULL;
1862 CHECK_DB_NOT_CLOSED(self);
1863 if (!make_dbt(keyobj, &key))
1864 /* BTree only, don't need to allow for an int key */
1865 return NULL;
1866 if (!checkTxnObj(txnobj, &txn))
1867 return NULL;
1869 MYDB_BEGIN_ALLOW_THREADS;
1870 err = self->db->key_range(self->db, txn, &key, &range, flags);
1871 MYDB_END_ALLOW_THREADS;
1873 RETURN_IF_ERR();
1874 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1878 static PyObject*
1879 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1881 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1882 char* filename = NULL;
1883 char* dbname = NULL;
1884 #if (DBVER >= 41)
1885 PyObject *txnobj = NULL;
1886 DB_TXN *txn = NULL;
1887 /* with dbname */
1888 static char* kwnames[] = {
1889 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1890 /* without dbname */
1891 static char* kwnames_basic[] = {
1892 "filename", "dbtype", "flags", "mode", "txn", NULL};
1893 #else
1894 /* with dbname */
1895 static char* kwnames[] = {
1896 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1897 /* without dbname */
1898 static char* kwnames_basic[] = {
1899 "filename", "dbtype", "flags", "mode", NULL};
1900 #endif
1902 #if (DBVER >= 41)
1903 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1904 &filename, &dbname, &type, &flags, &mode,
1905 &txnobj))
1906 #else
1907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1908 &filename, &dbname, &type, &flags,
1909 &mode))
1910 #endif
1912 PyErr_Clear();
1913 type = DB_UNKNOWN; flags = 0; mode = 0660;
1914 filename = NULL; dbname = NULL;
1915 #if (DBVER >= 41)
1916 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1917 kwnames_basic,
1918 &filename, &type, &flags, &mode,
1919 &txnobj))
1920 return NULL;
1921 #else
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1923 kwnames_basic,
1924 &filename, &type, &flags, &mode))
1925 return NULL;
1926 #endif
1929 #if (DBVER >= 41)
1930 if (!checkTxnObj(txnobj, &txn)) return NULL;
1931 #endif
1933 if (NULL == self->db) {
1934 PyObject *t = Py_BuildValue("(is)", 0,
1935 "Cannot call open() twice for DB object");
1936 PyErr_SetObject(DBError, t);
1937 Py_DECREF(t);
1938 return NULL;
1941 #if 0 && (DBVER >= 41)
1942 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1943 && (self->myenvobj->flags & DB_INIT_TXN))
1945 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1946 * explicitly passed) but we are in a transaction ready environment:
1947 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1948 * to work on BerkeleyDB 4.1 without needing to modify their
1949 * DBEnv or DB open calls.
1950 * TODO make this behaviour of the library configurable.
1952 flags |= DB_AUTO_COMMIT;
1954 #endif
1956 MYDB_BEGIN_ALLOW_THREADS;
1957 #if (DBVER >= 41)
1958 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1959 #else
1960 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1961 #endif
1962 MYDB_END_ALLOW_THREADS;
1963 if (makeDBError(err)) {
1964 self->db->close(self->db, 0);
1965 self->db = NULL;
1966 return NULL;
1969 self->flags = flags;
1970 RETURN_NONE();
1974 static PyObject*
1975 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1977 int flags=0;
1978 PyObject* txnobj = NULL;
1979 int dlen = -1;
1980 int doff = -1;
1981 PyObject* keyobj, *dataobj, *retval;
1982 DBT key, data;
1983 DB_TXN *txn = NULL;
1984 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1985 "doff", NULL };
1987 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1988 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1989 return NULL;
1991 CHECK_DB_NOT_CLOSED(self);
1992 if (!make_key_dbt(self, keyobj, &key, NULL))
1993 return NULL;
1994 if ( !make_dbt(dataobj, &data) ||
1995 !add_partial_dbt(&data, dlen, doff) ||
1996 !checkTxnObj(txnobj, &txn) )
1998 FREE_DBT(key);
1999 return NULL;
2002 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2003 FREE_DBT(key);
2004 return NULL;
2007 if (flags & DB_APPEND)
2008 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2009 else {
2010 retval = Py_None;
2011 Py_INCREF(retval);
2013 FREE_DBT(key);
2014 return retval;
2019 static PyObject*
2020 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2022 char* filename;
2023 char* database = NULL;
2024 int err, flags=0;
2025 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2027 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2028 &filename, &database, &flags))
2029 return NULL;
2030 CHECK_DB_NOT_CLOSED(self);
2032 err = self->db->remove(self->db, filename, database, flags);
2033 self->db = NULL;
2034 RETURN_IF_ERR();
2035 RETURN_NONE();
2040 static PyObject*
2041 DB_rename(DBObject* self, PyObject* args)
2043 char* filename;
2044 char* database;
2045 char* newname;
2046 int err, flags=0;
2048 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2049 &flags))
2050 return NULL;
2051 CHECK_DB_NOT_CLOSED(self);
2053 MYDB_BEGIN_ALLOW_THREADS;
2054 err = self->db->rename(self->db, filename, database, newname, flags);
2055 MYDB_END_ALLOW_THREADS;
2056 RETURN_IF_ERR();
2057 RETURN_NONE();
2061 static PyObject*
2062 DB_set_bt_minkey(DBObject* self, PyObject* args)
2064 int err, minkey;
2066 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2067 return NULL;
2068 CHECK_DB_NOT_CLOSED(self);
2070 MYDB_BEGIN_ALLOW_THREADS;
2071 err = self->db->set_bt_minkey(self->db, minkey);
2072 MYDB_END_ALLOW_THREADS;
2073 RETURN_IF_ERR();
2074 RETURN_NONE();
2077 #if (DBVER >= 33)
2078 static int
2079 _default_cmp(const DBT *leftKey,
2080 const DBT *rightKey)
2082 int res;
2083 int lsize = leftKey->size, rsize = rightKey->size;
2085 res = memcmp(leftKey->data, rightKey->data,
2086 lsize < rsize ? lsize : rsize);
2088 if (res == 0) {
2089 if (lsize < rsize) {
2090 res = -1;
2092 else if (lsize > rsize) {
2093 res = 1;
2096 return res;
2099 static int
2100 _db_compareCallback(DB* db,
2101 const DBT *leftKey,
2102 const DBT *rightKey)
2104 int res = 0;
2105 PyObject *args;
2106 PyObject *result = NULL;
2107 DBObject *self = (DBObject *)db->app_private;
2109 if (self == NULL || self->btCompareCallback == NULL) {
2110 MYDB_BEGIN_BLOCK_THREADS;
2111 PyErr_SetString(PyExc_TypeError,
2112 (self == 0
2113 ? "DB_bt_compare db is NULL."
2114 : "DB_bt_compare callback is NULL."));
2115 /* we're in a callback within the DB code, we can't raise */
2116 PyErr_Print();
2117 res = _default_cmp(leftKey, rightKey);
2118 MYDB_END_BLOCK_THREADS;
2119 } else {
2120 MYDB_BEGIN_BLOCK_THREADS;
2122 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2123 rightKey->data, rightKey->size);
2124 if (args != NULL) {
2125 /* XXX(twouters) I highly doubt this INCREF is correct */
2126 Py_INCREF(self);
2127 result = PyEval_CallObject(self->btCompareCallback, args);
2129 if (args == NULL || result == NULL) {
2130 /* we're in a callback within the DB code, we can't raise */
2131 PyErr_Print();
2132 res = _default_cmp(leftKey, rightKey);
2133 } else if (PyInt_Check(result)) {
2134 res = PyInt_AsLong(result);
2135 } else {
2136 PyErr_SetString(PyExc_TypeError,
2137 "DB_bt_compare callback MUST return an int.");
2138 /* we're in a callback within the DB code, we can't raise */
2139 PyErr_Print();
2140 res = _default_cmp(leftKey, rightKey);
2143 Py_XDECREF(args);
2144 Py_XDECREF(result);
2146 MYDB_END_BLOCK_THREADS;
2148 return res;
2151 static PyObject*
2152 DB_set_bt_compare(DBObject* self, PyObject* args)
2154 int err;
2155 PyObject *comparator;
2156 PyObject *tuple, *result;
2158 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2159 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2163 if (!PyCallable_Check(comparator)) {
2164 makeTypeError("Callable", comparator);
2165 return NULL;
2169 * Perform a test call of the comparator function with two empty
2170 * string objects here. verify that it returns an int (0).
2171 * err if not.
2173 tuple = Py_BuildValue("(ss)", "", "");
2174 result = PyEval_CallObject(comparator, tuple);
2175 Py_DECREF(tuple);
2176 if (result == NULL)
2177 return NULL;
2178 if (!PyInt_Check(result)) {
2179 PyErr_SetString(PyExc_TypeError,
2180 "callback MUST return an int");
2181 return NULL;
2182 } else if (PyInt_AsLong(result) != 0) {
2183 PyErr_SetString(PyExc_TypeError,
2184 "callback failed to return 0 on two empty strings");
2185 return NULL;
2187 Py_DECREF(result);
2189 /* We don't accept multiple set_bt_compare operations, in order to
2190 * simplify the code. This would have no real use, as one cannot
2191 * change the function once the db is opened anyway */
2192 if (self->btCompareCallback != NULL) {
2193 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2194 return NULL;
2197 Py_INCREF(comparator);
2198 self->btCompareCallback = comparator;
2200 /* This is to workaround a problem with un-initialized threads (see
2201 comment in DB_associate) */
2202 #ifdef WITH_THREAD
2203 PyEval_InitThreads();
2204 #endif
2206 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2208 if (err) {
2209 /* restore the old state in case of error */
2210 Py_DECREF(comparator);
2211 self->btCompareCallback = NULL;
2214 RETURN_IF_ERR();
2215 RETURN_NONE();
2217 #endif /* DBVER >= 33 */
2220 static PyObject*
2221 DB_set_cachesize(DBObject* self, PyObject* args)
2223 int err;
2224 int gbytes = 0, bytes = 0, ncache = 0;
2226 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2227 &gbytes,&bytes,&ncache))
2228 return NULL;
2229 CHECK_DB_NOT_CLOSED(self);
2231 MYDB_BEGIN_ALLOW_THREADS;
2232 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2233 MYDB_END_ALLOW_THREADS;
2234 RETURN_IF_ERR();
2235 RETURN_NONE();
2239 static PyObject*
2240 DB_set_flags(DBObject* self, PyObject* args)
2242 int err, flags;
2244 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_flags(self->db, flags);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2253 self->setflags |= flags;
2254 RETURN_NONE();
2258 static PyObject*
2259 DB_set_h_ffactor(DBObject* self, PyObject* args)
2261 int err, ffactor;
2263 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_h_ffactor(self->db, ffactor);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271 RETURN_NONE();
2275 static PyObject*
2276 DB_set_h_nelem(DBObject* self, PyObject* args)
2278 int err, nelem;
2280 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_h_nelem(self->db, nelem);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2292 static PyObject*
2293 DB_set_lorder(DBObject* self, PyObject* args)
2295 int err, lorder;
2297 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2298 return NULL;
2299 CHECK_DB_NOT_CLOSED(self);
2301 MYDB_BEGIN_ALLOW_THREADS;
2302 err = self->db->set_lorder(self->db, lorder);
2303 MYDB_END_ALLOW_THREADS;
2304 RETURN_IF_ERR();
2305 RETURN_NONE();
2309 static PyObject*
2310 DB_set_pagesize(DBObject* self, PyObject* args)
2312 int err, pagesize;
2314 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2315 return NULL;
2316 CHECK_DB_NOT_CLOSED(self);
2318 MYDB_BEGIN_ALLOW_THREADS;
2319 err = self->db->set_pagesize(self->db, pagesize);
2320 MYDB_END_ALLOW_THREADS;
2321 RETURN_IF_ERR();
2322 RETURN_NONE();
2326 static PyObject*
2327 DB_set_re_delim(DBObject* self, PyObject* args)
2329 int err;
2330 char delim;
2332 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2333 PyErr_Clear();
2334 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2335 return NULL;
2338 CHECK_DB_NOT_CLOSED(self);
2340 MYDB_BEGIN_ALLOW_THREADS;
2341 err = self->db->set_re_delim(self->db, delim);
2342 MYDB_END_ALLOW_THREADS;
2343 RETURN_IF_ERR();
2344 RETURN_NONE();
2347 static PyObject*
2348 DB_set_re_len(DBObject* self, PyObject* args)
2350 int err, len;
2352 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2353 return NULL;
2354 CHECK_DB_NOT_CLOSED(self);
2356 MYDB_BEGIN_ALLOW_THREADS;
2357 err = self->db->set_re_len(self->db, len);
2358 MYDB_END_ALLOW_THREADS;
2359 RETURN_IF_ERR();
2360 RETURN_NONE();
2364 static PyObject*
2365 DB_set_re_pad(DBObject* self, PyObject* args)
2367 int err;
2368 char pad;
2370 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2371 PyErr_Clear();
2372 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2373 return NULL;
2375 CHECK_DB_NOT_CLOSED(self);
2377 MYDB_BEGIN_ALLOW_THREADS;
2378 err = self->db->set_re_pad(self->db, pad);
2379 MYDB_END_ALLOW_THREADS;
2380 RETURN_IF_ERR();
2381 RETURN_NONE();
2385 static PyObject*
2386 DB_set_re_source(DBObject* self, PyObject* args)
2388 int err;
2389 char *re_source;
2391 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2392 return NULL;
2393 CHECK_DB_NOT_CLOSED(self);
2395 MYDB_BEGIN_ALLOW_THREADS;
2396 err = self->db->set_re_source(self->db, re_source);
2397 MYDB_END_ALLOW_THREADS;
2398 RETURN_IF_ERR();
2399 RETURN_NONE();
2403 #if (DBVER >= 32)
2404 static PyObject*
2405 DB_set_q_extentsize(DBObject* self, PyObject* args)
2407 int err;
2408 int extentsize;
2410 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2411 return NULL;
2412 CHECK_DB_NOT_CLOSED(self);
2414 MYDB_BEGIN_ALLOW_THREADS;
2415 err = self->db->set_q_extentsize(self->db, extentsize);
2416 MYDB_END_ALLOW_THREADS;
2417 RETURN_IF_ERR();
2418 RETURN_NONE();
2420 #endif
2422 static PyObject*
2423 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2425 int err, flags = 0, type;
2426 void* sp;
2427 PyObject* d;
2428 #if (DBVER >= 43)
2429 PyObject* txnobj = NULL;
2430 DB_TXN *txn = NULL;
2431 static char* kwnames[] = { "flags", "txn", NULL };
2432 #else
2433 static char* kwnames[] = { "flags", NULL };
2434 #endif
2436 #if (DBVER >= 43)
2437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2438 &flags, &txnobj))
2439 return NULL;
2440 if (!checkTxnObj(txnobj, &txn))
2441 return NULL;
2442 #else
2443 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2444 return NULL;
2445 #endif
2446 CHECK_DB_NOT_CLOSED(self);
2448 MYDB_BEGIN_ALLOW_THREADS;
2449 #if (DBVER >= 43)
2450 err = self->db->stat(self->db, txn, &sp, flags);
2451 #elif (DBVER >= 33)
2452 err = self->db->stat(self->db, &sp, flags);
2453 #else
2454 err = self->db->stat(self->db, &sp, NULL, flags);
2455 #endif
2456 MYDB_END_ALLOW_THREADS;
2457 RETURN_IF_ERR();
2459 self->haveStat = 1;
2461 /* Turn the stat structure into a dictionary */
2462 type = _DB_get_type(self);
2463 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2464 free(sp);
2465 return NULL;
2468 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2469 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2470 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2472 switch (type) {
2473 case DB_HASH:
2474 MAKE_HASH_ENTRY(magic);
2475 MAKE_HASH_ENTRY(version);
2476 MAKE_HASH_ENTRY(nkeys);
2477 MAKE_HASH_ENTRY(ndata);
2478 MAKE_HASH_ENTRY(pagesize);
2479 #if (DBVER < 41)
2480 MAKE_HASH_ENTRY(nelem);
2481 #endif
2482 MAKE_HASH_ENTRY(ffactor);
2483 MAKE_HASH_ENTRY(buckets);
2484 MAKE_HASH_ENTRY(free);
2485 MAKE_HASH_ENTRY(bfree);
2486 MAKE_HASH_ENTRY(bigpages);
2487 MAKE_HASH_ENTRY(big_bfree);
2488 MAKE_HASH_ENTRY(overflows);
2489 MAKE_HASH_ENTRY(ovfl_free);
2490 MAKE_HASH_ENTRY(dup);
2491 MAKE_HASH_ENTRY(dup_free);
2492 break;
2494 case DB_BTREE:
2495 case DB_RECNO:
2496 MAKE_BT_ENTRY(magic);
2497 MAKE_BT_ENTRY(version);
2498 MAKE_BT_ENTRY(nkeys);
2499 MAKE_BT_ENTRY(ndata);
2500 MAKE_BT_ENTRY(pagesize);
2501 MAKE_BT_ENTRY(minkey);
2502 MAKE_BT_ENTRY(re_len);
2503 MAKE_BT_ENTRY(re_pad);
2504 MAKE_BT_ENTRY(levels);
2505 MAKE_BT_ENTRY(int_pg);
2506 MAKE_BT_ENTRY(leaf_pg);
2507 MAKE_BT_ENTRY(dup_pg);
2508 MAKE_BT_ENTRY(over_pg);
2509 MAKE_BT_ENTRY(free);
2510 MAKE_BT_ENTRY(int_pgfree);
2511 MAKE_BT_ENTRY(leaf_pgfree);
2512 MAKE_BT_ENTRY(dup_pgfree);
2513 MAKE_BT_ENTRY(over_pgfree);
2514 break;
2516 case DB_QUEUE:
2517 MAKE_QUEUE_ENTRY(magic);
2518 MAKE_QUEUE_ENTRY(version);
2519 MAKE_QUEUE_ENTRY(nkeys);
2520 MAKE_QUEUE_ENTRY(ndata);
2521 MAKE_QUEUE_ENTRY(pagesize);
2522 MAKE_QUEUE_ENTRY(pages);
2523 MAKE_QUEUE_ENTRY(re_len);
2524 MAKE_QUEUE_ENTRY(re_pad);
2525 MAKE_QUEUE_ENTRY(pgfree);
2526 #if (DBVER == 31)
2527 MAKE_QUEUE_ENTRY(start);
2528 #endif
2529 MAKE_QUEUE_ENTRY(first_recno);
2530 MAKE_QUEUE_ENTRY(cur_recno);
2531 break;
2533 default:
2534 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2535 Py_DECREF(d);
2536 d = NULL;
2539 #undef MAKE_HASH_ENTRY
2540 #undef MAKE_BT_ENTRY
2541 #undef MAKE_QUEUE_ENTRY
2543 free(sp);
2544 return d;
2547 static PyObject*
2548 DB_sync(DBObject* self, PyObject* args)
2550 int err;
2551 int flags = 0;
2553 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2554 return NULL;
2555 CHECK_DB_NOT_CLOSED(self);
2557 MYDB_BEGIN_ALLOW_THREADS;
2558 err = self->db->sync(self->db, flags);
2559 MYDB_END_ALLOW_THREADS;
2560 RETURN_IF_ERR();
2561 RETURN_NONE();
2565 #if (DBVER >= 33)
2566 static PyObject*
2567 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2569 int err, flags=0;
2570 u_int32_t count=0;
2571 PyObject* txnobj = NULL;
2572 DB_TXN *txn = NULL;
2573 static char* kwnames[] = { "txn", "flags", NULL };
2575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2576 &txnobj, &flags))
2577 return NULL;
2578 CHECK_DB_NOT_CLOSED(self);
2579 if (!checkTxnObj(txnobj, &txn))
2580 return NULL;
2582 MYDB_BEGIN_ALLOW_THREADS;
2583 err = self->db->truncate(self->db, txn, &count, flags);
2584 MYDB_END_ALLOW_THREADS;
2585 RETURN_IF_ERR();
2586 return PyInt_FromLong(count);
2588 #endif
2591 static PyObject*
2592 DB_upgrade(DBObject* self, PyObject* args)
2594 int err, flags=0;
2595 char *filename;
2597 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2598 return NULL;
2599 CHECK_DB_NOT_CLOSED(self);
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 err = self->db->upgrade(self->db, filename, flags);
2603 MYDB_END_ALLOW_THREADS;
2604 RETURN_IF_ERR();
2605 RETURN_NONE();
2609 static PyObject*
2610 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2612 int err, flags=0;
2613 char* fileName;
2614 char* dbName=NULL;
2615 char* outFileName=NULL;
2616 FILE* outFile=NULL;
2617 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2618 NULL };
2620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2621 &fileName, &dbName, &outFileName, &flags))
2622 return NULL;
2624 CHECK_DB_NOT_CLOSED(self);
2625 if (outFileName)
2626 outFile = fopen(outFileName, "w");
2627 /* XXX(nnorwitz): it should probably be an exception if outFile
2628 can't be opened. */
2630 MYDB_BEGIN_ALLOW_THREADS;
2631 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2632 MYDB_END_ALLOW_THREADS;
2633 if (outFile)
2634 fclose(outFile);
2636 /* DB.verify acts as a DB handle destructor (like close); this was
2637 * documented in BerkeleyDB 4.2 but had the undocumented effect
2638 * of not being safe in prior versions while still requiring an explicit
2639 * DB.close call afterwards. Lets call close for the user to emulate
2640 * the safe 4.2 behaviour. */
2641 #if (DBVER <= 41)
2642 self->db->close(self->db, 0);
2643 #endif
2644 self->db = NULL;
2646 RETURN_IF_ERR();
2647 RETURN_NONE();
2651 static PyObject*
2652 DB_set_get_returns_none(DBObject* self, PyObject* args)
2654 int flags=0;
2655 int oldValue=0;
2657 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2658 return NULL;
2659 CHECK_DB_NOT_CLOSED(self);
2661 if (self->moduleFlags.getReturnsNone)
2662 ++oldValue;
2663 if (self->moduleFlags.cursorSetReturnsNone)
2664 ++oldValue;
2665 self->moduleFlags.getReturnsNone = (flags >= 1);
2666 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2667 return PyInt_FromLong(oldValue);
2670 #if (DBVER >= 41)
2671 static PyObject*
2672 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2674 int err;
2675 u_int32_t flags=0;
2676 char *passwd = NULL;
2677 static char* kwnames[] = { "passwd", "flags", NULL };
2679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2680 &passwd, &flags)) {
2681 return NULL;
2684 MYDB_BEGIN_ALLOW_THREADS;
2685 err = self->db->set_encrypt(self->db, passwd, flags);
2686 MYDB_END_ALLOW_THREADS;
2688 RETURN_IF_ERR();
2689 RETURN_NONE();
2691 #endif /* DBVER >= 41 */
2694 /*-------------------------------------------------------------- */
2695 /* Mapping and Dictionary-like access routines */
2697 Py_ssize_t DB_length(PyObject* _self)
2699 int err;
2700 Py_ssize_t size = 0;
2701 int flags = 0;
2702 void* sp;
2703 DBObject* self = (DBObject*)_self;
2705 if (self->db == NULL) {
2706 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2707 PyErr_SetObject(DBError, t);
2708 Py_DECREF(t);
2709 return -1;
2712 if (self->haveStat) { /* Has the stat function been called recently? If
2713 so, we can use the cached value. */
2714 flags = DB_FAST_STAT;
2717 MYDB_BEGIN_ALLOW_THREADS;
2718 redo_stat_for_length:
2719 #if (DBVER >= 43)
2720 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2721 #elif (DBVER >= 33)
2722 err = self->db->stat(self->db, &sp, flags);
2723 #else
2724 err = self->db->stat(self->db, &sp, NULL, flags);
2725 #endif
2727 /* All the stat structures have matching fields upto the ndata field,
2728 so we can use any of them for the type cast */
2729 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2731 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2732 * redo a full stat to make sure.
2733 * Fixes SF python bug 1493322, pybsddb bug 1184012
2735 if (size == 0 && (flags & DB_FAST_STAT)) {
2736 flags = 0;
2737 if (!err)
2738 free(sp);
2739 goto redo_stat_for_length;
2742 MYDB_END_ALLOW_THREADS;
2744 if (err)
2745 return -1;
2747 self->haveStat = 1;
2749 free(sp);
2750 return size;
2754 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2756 int err;
2757 PyObject* retval;
2758 DBT key;
2759 DBT data;
2761 CHECK_DB_NOT_CLOSED(self);
2762 if (!make_key_dbt(self, keyobj, &key, NULL))
2763 return NULL;
2765 CLEAR_DBT(data);
2766 if (CHECK_DBFLAG(self, DB_THREAD)) {
2767 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2768 data.flags = DB_DBT_MALLOC;
2770 MYDB_BEGIN_ALLOW_THREADS;
2771 err = self->db->get(self->db, NULL, &key, &data, 0);
2772 MYDB_END_ALLOW_THREADS;
2773 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2774 PyErr_SetObject(PyExc_KeyError, keyobj);
2775 retval = NULL;
2777 else if (makeDBError(err)) {
2778 retval = NULL;
2780 else {
2781 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2782 FREE_DBT(data);
2785 FREE_DBT(key);
2786 return retval;
2790 static int
2791 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2793 DBT key, data;
2794 int retval;
2795 int flags = 0;
2797 if (self->db == NULL) {
2798 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2799 PyErr_SetObject(DBError, t);
2800 Py_DECREF(t);
2801 return -1;
2804 if (!make_key_dbt(self, keyobj, &key, NULL))
2805 return -1;
2807 if (dataobj != NULL) {
2808 if (!make_dbt(dataobj, &data))
2809 retval = -1;
2810 else {
2811 if (self->setflags & (DB_DUP|DB_DUPSORT))
2812 /* dictionaries shouldn't have duplicate keys */
2813 flags = DB_NOOVERWRITE;
2814 retval = _DB_put(self, NULL, &key, &data, flags);
2816 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2817 /* try deleting any old record that matches and then PUT it
2818 * again... */
2819 _DB_delete(self, NULL, &key, 0);
2820 PyErr_Clear();
2821 retval = _DB_put(self, NULL, &key, &data, flags);
2825 else {
2826 /* dataobj == NULL, so delete the key */
2827 retval = _DB_delete(self, NULL, &key, 0);
2829 FREE_DBT(key);
2830 return retval;
2834 static PyObject*
2835 DB_has_key(DBObject* self, PyObject* args)
2837 int err;
2838 PyObject* keyobj;
2839 DBT key, data;
2840 PyObject* txnobj = NULL;
2841 DB_TXN *txn = NULL;
2843 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2844 return NULL;
2845 CHECK_DB_NOT_CLOSED(self);
2846 if (!make_key_dbt(self, keyobj, &key, NULL))
2847 return NULL;
2848 if (!checkTxnObj(txnobj, &txn)) {
2849 FREE_DBT(key);
2850 return NULL;
2853 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2854 it has a record but can't allocate a buffer for the data. This saves
2855 having to deal with data we won't be using.
2857 CLEAR_DBT(data);
2858 data.flags = DB_DBT_USERMEM;
2860 MYDB_BEGIN_ALLOW_THREADS;
2861 err = self->db->get(self->db, txn, &key, &data, 0);
2862 MYDB_END_ALLOW_THREADS;
2863 FREE_DBT(key);
2865 if (err == DB_BUFFER_SMALL || err == 0) {
2866 return PyInt_FromLong(1);
2867 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2868 return PyInt_FromLong(0);
2871 makeDBError(err);
2872 return NULL;
2876 #define _KEYS_LIST 1
2877 #define _VALUES_LIST 2
2878 #define _ITEMS_LIST 3
2880 static PyObject*
2881 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2883 int err, dbtype;
2884 DBT key;
2885 DBT data;
2886 DBC *cursor;
2887 PyObject* list;
2888 PyObject* item = NULL;
2890 CHECK_DB_NOT_CLOSED(self);
2891 CLEAR_DBT(key);
2892 CLEAR_DBT(data);
2894 dbtype = _DB_get_type(self);
2895 if (dbtype == -1)
2896 return NULL;
2898 list = PyList_New(0);
2899 if (list == NULL)
2900 return NULL;
2902 /* get a cursor */
2903 MYDB_BEGIN_ALLOW_THREADS;
2904 err = self->db->cursor(self->db, txn, &cursor, 0);
2905 MYDB_END_ALLOW_THREADS;
2906 if (makeDBError(err)) {
2907 Py_DECREF(list);
2908 return NULL;
2911 if (CHECK_DBFLAG(self, DB_THREAD)) {
2912 key.flags = DB_DBT_REALLOC;
2913 data.flags = DB_DBT_REALLOC;
2916 while (1) { /* use the cursor to traverse the DB, collecting items */
2917 MYDB_BEGIN_ALLOW_THREADS;
2918 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2919 MYDB_END_ALLOW_THREADS;
2921 if (err) {
2922 /* for any error, break out of the loop */
2923 break;
2926 switch (type) {
2927 case _KEYS_LIST:
2928 switch(dbtype) {
2929 case DB_BTREE:
2930 case DB_HASH:
2931 default:
2932 item = PyString_FromStringAndSize((char*)key.data, key.size);
2933 break;
2934 case DB_RECNO:
2935 case DB_QUEUE:
2936 item = PyInt_FromLong(*((db_recno_t*)key.data));
2937 break;
2939 break;
2941 case _VALUES_LIST:
2942 item = PyString_FromStringAndSize((char*)data.data, data.size);
2943 break;
2945 case _ITEMS_LIST:
2946 switch(dbtype) {
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
2950 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2951 data.size);
2952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
2955 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2956 data.data, data.size);
2957 break;
2959 break;
2960 default:
2961 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2962 item = NULL;
2963 break;
2965 if (item == NULL) {
2966 Py_DECREF(list);
2967 list = NULL;
2968 goto done;
2970 PyList_Append(list, item);
2971 Py_DECREF(item);
2974 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2975 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2976 Py_DECREF(list);
2977 list = NULL;
2980 done:
2981 FREE_DBT(key);
2982 FREE_DBT(data);
2983 MYDB_BEGIN_ALLOW_THREADS;
2984 cursor->c_close(cursor);
2985 MYDB_END_ALLOW_THREADS;
2986 return list;
2990 static PyObject*
2991 DB_keys(DBObject* self, PyObject* args)
2993 PyObject* txnobj = NULL;
2994 DB_TXN *txn = NULL;
2996 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2997 return NULL;
2998 if (!checkTxnObj(txnobj, &txn))
2999 return NULL;
3000 return _DB_make_list(self, txn, _KEYS_LIST);
3004 static PyObject*
3005 DB_items(DBObject* self, PyObject* args)
3007 PyObject* txnobj = NULL;
3008 DB_TXN *txn = NULL;
3010 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3011 return NULL;
3012 if (!checkTxnObj(txnobj, &txn))
3013 return NULL;
3014 return _DB_make_list(self, txn, _ITEMS_LIST);
3018 static PyObject*
3019 DB_values(DBObject* self, PyObject* args)
3021 PyObject* txnobj = NULL;
3022 DB_TXN *txn = NULL;
3024 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3025 return NULL;
3026 if (!checkTxnObj(txnobj, &txn))
3027 return NULL;
3028 return _DB_make_list(self, txn, _VALUES_LIST);
3031 /* --------------------------------------------------------------------- */
3032 /* DBCursor methods */
3035 static PyObject*
3036 DBC_close(DBCursorObject* self, PyObject* args)
3038 int err = 0;
3040 if (!PyArg_ParseTuple(args, ":close"))
3041 return NULL;
3043 if (self->dbc != NULL) {
3044 MYDB_BEGIN_ALLOW_THREADS;
3045 err = self->dbc->c_close(self->dbc);
3046 self->dbc = NULL;
3047 MYDB_END_ALLOW_THREADS;
3049 RETURN_IF_ERR();
3050 RETURN_NONE();
3054 static PyObject*
3055 DBC_count(DBCursorObject* self, PyObject* args)
3057 int err = 0;
3058 db_recno_t count;
3059 int flags = 0;
3061 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3062 return NULL;
3064 CHECK_CURSOR_NOT_CLOSED(self);
3066 MYDB_BEGIN_ALLOW_THREADS;
3067 err = self->dbc->c_count(self->dbc, &count, flags);
3068 MYDB_END_ALLOW_THREADS;
3069 RETURN_IF_ERR();
3071 return PyInt_FromLong(count);
3075 static PyObject*
3076 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3078 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3082 static PyObject*
3083 DBC_delete(DBCursorObject* self, PyObject* args)
3085 int err, flags=0;
3087 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3088 return NULL;
3090 CHECK_CURSOR_NOT_CLOSED(self);
3092 MYDB_BEGIN_ALLOW_THREADS;
3093 err = self->dbc->c_del(self->dbc, flags);
3094 MYDB_END_ALLOW_THREADS;
3095 RETURN_IF_ERR();
3097 self->mydb->haveStat = 0;
3098 RETURN_NONE();
3102 static PyObject*
3103 DBC_dup(DBCursorObject* self, PyObject* args)
3105 int err, flags =0;
3106 DBC* dbc = NULL;
3108 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3109 return NULL;
3111 CHECK_CURSOR_NOT_CLOSED(self);
3113 MYDB_BEGIN_ALLOW_THREADS;
3114 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3115 MYDB_END_ALLOW_THREADS;
3116 RETURN_IF_ERR();
3118 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3121 static PyObject*
3122 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3124 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3128 static PyObject*
3129 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3131 int err, flags=0;
3132 PyObject* keyobj = NULL;
3133 PyObject* dataobj = NULL;
3134 PyObject* retval = NULL;
3135 int dlen = -1;
3136 int doff = -1;
3137 DBT key, data;
3138 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3139 NULL };
3141 CLEAR_DBT(key);
3142 CLEAR_DBT(data);
3143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3144 &flags, &dlen, &doff))
3146 PyErr_Clear();
3147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3148 &kwnames[1],
3149 &keyobj, &flags, &dlen, &doff))
3151 PyErr_Clear();
3152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3153 kwnames, &keyobj, &dataobj,
3154 &flags, &dlen, &doff))
3156 return NULL;
3161 CHECK_CURSOR_NOT_CLOSED(self);
3163 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3164 return NULL;
3165 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3166 (!add_partial_dbt(&data, dlen, doff)) )
3168 FREE_DBT(key);
3169 return NULL;
3172 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3173 data.flags = DB_DBT_MALLOC;
3174 if (!(key.flags & DB_DBT_REALLOC)) {
3175 key.flags |= DB_DBT_MALLOC;
3179 MYDB_BEGIN_ALLOW_THREADS;
3180 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3181 MYDB_END_ALLOW_THREADS;
3183 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3184 && self->mydb->moduleFlags.getReturnsNone) {
3185 Py_INCREF(Py_None);
3186 retval = Py_None;
3188 else if (makeDBError(err)) {
3189 retval = NULL;
3191 else {
3192 switch (_DB_get_type(self->mydb)) {
3193 case -1:
3194 retval = NULL;
3195 break;
3196 case DB_BTREE:
3197 case DB_HASH:
3198 default:
3199 retval = Py_BuildValue("s#s#", key.data, key.size,
3200 data.data, data.size);
3201 break;
3202 case DB_RECNO:
3203 case DB_QUEUE:
3204 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3205 data.data, data.size);
3206 break;
3208 FREE_DBT(data);
3210 FREE_DBT(key);
3211 return retval;
3214 #if (DBVER >= 33)
3215 static PyObject*
3216 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3218 int err, flags=0;
3219 PyObject* keyobj = NULL;
3220 PyObject* dataobj = NULL;
3221 PyObject* retval = NULL;
3222 int dlen = -1;
3223 int doff = -1;
3224 DBT key, pkey, data;
3225 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3226 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3228 CLEAR_DBT(key);
3229 CLEAR_DBT(data);
3230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3231 &flags, &dlen, &doff))
3233 PyErr_Clear();
3234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3235 kwnames_keyOnly,
3236 &keyobj, &flags, &dlen, &doff))
3238 PyErr_Clear();
3239 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3240 kwnames, &keyobj, &dataobj,
3241 &flags, &dlen, &doff))
3243 return NULL;
3248 CHECK_CURSOR_NOT_CLOSED(self);
3250 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3251 return NULL;
3252 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3253 (!add_partial_dbt(&data, dlen, doff)) ) {
3254 FREE_DBT(key);
3255 return NULL;
3258 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3259 data.flags = DB_DBT_MALLOC;
3260 if (!(key.flags & DB_DBT_REALLOC)) {
3261 key.flags |= DB_DBT_MALLOC;
3265 CLEAR_DBT(pkey);
3266 pkey.flags = DB_DBT_MALLOC;
3268 MYDB_BEGIN_ALLOW_THREADS;
3269 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3270 MYDB_END_ALLOW_THREADS;
3272 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3273 && self->mydb->moduleFlags.getReturnsNone) {
3274 Py_INCREF(Py_None);
3275 retval = Py_None;
3277 else if (makeDBError(err)) {
3278 retval = NULL;
3280 else {
3281 PyObject *pkeyObj;
3282 PyObject *dataObj;
3283 dataObj = PyString_FromStringAndSize(data.data, data.size);
3285 if (self->mydb->primaryDBType == DB_RECNO ||
3286 self->mydb->primaryDBType == DB_QUEUE)
3287 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3288 else
3289 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3291 if (key.data && key.size) /* return key, pkey and data */
3293 PyObject *keyObj;
3294 int type = _DB_get_type(self->mydb);
3295 if (type == DB_RECNO || type == DB_QUEUE)
3296 keyObj = PyInt_FromLong(*(int *)key.data);
3297 else
3298 keyObj = PyString_FromStringAndSize(key.data, key.size);
3299 #if (PY_VERSION_HEX >= 0x02040000)
3300 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3301 #else
3302 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3303 #endif
3304 Py_DECREF(keyObj);
3305 FREE_DBT(key);
3307 else /* return just the pkey and data */
3309 #if (PY_VERSION_HEX >= 0x02040000)
3310 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3311 #else
3312 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3313 #endif
3315 Py_DECREF(dataObj);
3316 Py_DECREF(pkeyObj);
3317 FREE_DBT(pkey);
3318 FREE_DBT(data);
3320 /* the only time REALLOC should be set is if we used an integer
3321 * key that make_key_dbt malloc'd for us. always free these. */
3322 if (key.flags & DB_DBT_REALLOC) {
3323 FREE_DBT(key);
3325 return retval;
3327 #endif
3330 static PyObject*
3331 DBC_get_recno(DBCursorObject* self, PyObject* args)
3333 int err;
3334 db_recno_t recno;
3335 DBT key;
3336 DBT data;
3338 if (!PyArg_ParseTuple(args, ":get_recno"))
3339 return NULL;
3341 CHECK_CURSOR_NOT_CLOSED(self);
3343 CLEAR_DBT(key);
3344 CLEAR_DBT(data);
3345 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3346 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3347 data.flags = DB_DBT_MALLOC;
3348 key.flags = DB_DBT_MALLOC;
3351 MYDB_BEGIN_ALLOW_THREADS;
3352 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3353 MYDB_END_ALLOW_THREADS;
3354 RETURN_IF_ERR();
3356 recno = *((db_recno_t*)data.data);
3357 FREE_DBT(key);
3358 FREE_DBT(data);
3359 return PyInt_FromLong(recno);
3363 static PyObject*
3364 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3366 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3370 static PyObject*
3371 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3373 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3377 static PyObject*
3378 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3380 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3384 static PyObject*
3385 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3387 int err, flags = 0;
3388 PyObject* keyobj, *dataobj;
3389 DBT key, data;
3390 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3391 NULL };
3392 int dlen = -1;
3393 int doff = -1;
3395 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3396 &keyobj, &dataobj, &flags, &dlen, &doff))
3397 return NULL;
3399 CHECK_CURSOR_NOT_CLOSED(self);
3401 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3402 return NULL;
3403 if (!make_dbt(dataobj, &data) ||
3404 !add_partial_dbt(&data, dlen, doff) )
3406 FREE_DBT(key);
3407 return NULL;
3410 MYDB_BEGIN_ALLOW_THREADS;
3411 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3412 MYDB_END_ALLOW_THREADS;
3413 FREE_DBT(key);
3414 RETURN_IF_ERR();
3415 self->mydb->haveStat = 0;
3416 RETURN_NONE();
3420 static PyObject*
3421 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3423 int err, flags = 0;
3424 DBT key, data;
3425 PyObject* retval, *keyobj;
3426 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3427 int dlen = -1;
3428 int doff = -1;
3430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3431 &keyobj, &flags, &dlen, &doff))
3432 return NULL;
3434 CHECK_CURSOR_NOT_CLOSED(self);
3436 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3437 return NULL;
3439 CLEAR_DBT(data);
3440 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3441 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3442 data.flags = DB_DBT_MALLOC;
3444 if (!add_partial_dbt(&data, dlen, doff)) {
3445 FREE_DBT(key);
3446 return NULL;
3449 MYDB_BEGIN_ALLOW_THREADS;
3450 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3451 MYDB_END_ALLOW_THREADS;
3452 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3453 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3454 Py_INCREF(Py_None);
3455 retval = Py_None;
3457 else if (makeDBError(err)) {
3458 retval = NULL;
3460 else {
3461 switch (_DB_get_type(self->mydb)) {
3462 case -1:
3463 retval = NULL;
3464 break;
3465 case DB_BTREE:
3466 case DB_HASH:
3467 default:
3468 retval = Py_BuildValue("s#s#", key.data, key.size,
3469 data.data, data.size);
3470 break;
3471 case DB_RECNO:
3472 case DB_QUEUE:
3473 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3474 data.data, data.size);
3475 break;
3477 FREE_DBT(data);
3478 FREE_DBT(key);
3480 /* the only time REALLOC should be set is if we used an integer
3481 * key that make_key_dbt malloc'd for us. always free these. */
3482 if (key.flags & DB_DBT_REALLOC) {
3483 FREE_DBT(key);
3486 return retval;
3490 static PyObject*
3491 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3493 int err, flags = 0;
3494 DBT key, data;
3495 PyObject* retval, *keyobj;
3496 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3497 int dlen = -1;
3498 int doff = -1;
3500 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3501 &keyobj, &flags, &dlen, &doff))
3502 return NULL;
3504 CHECK_CURSOR_NOT_CLOSED(self);
3506 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3507 return NULL;
3509 CLEAR_DBT(data);
3510 if (!add_partial_dbt(&data, dlen, doff)) {
3511 FREE_DBT(key);
3512 return NULL;
3514 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3515 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3516 data.flags |= DB_DBT_MALLOC;
3517 /* only BTREE databases will return anything in the key */
3518 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3519 key.flags |= DB_DBT_MALLOC;
3522 MYDB_BEGIN_ALLOW_THREADS;
3523 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3524 MYDB_END_ALLOW_THREADS;
3525 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3526 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3527 Py_INCREF(Py_None);
3528 retval = Py_None;
3530 else if (makeDBError(err)) {
3531 retval = NULL;
3533 else {
3534 switch (_DB_get_type(self->mydb)) {
3535 case -1:
3536 retval = NULL;
3537 break;
3538 case DB_BTREE:
3539 case DB_HASH:
3540 default:
3541 retval = Py_BuildValue("s#s#", key.data, key.size,
3542 data.data, data.size);
3543 break;
3544 case DB_RECNO:
3545 case DB_QUEUE:
3546 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3547 data.data, data.size);
3548 break;
3550 FREE_DBT(key);
3551 FREE_DBT(data);
3553 /* the only time REALLOC should be set is if we used an integer
3554 * key that make_key_dbt malloc'd for us. always free these. */
3555 if (key.flags & DB_DBT_REALLOC) {
3556 FREE_DBT(key);
3559 return retval;
3562 static PyObject*
3563 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3564 int flags, unsigned int returnsNone)
3566 int err;
3567 DBT key, data;
3568 PyObject* retval;
3570 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3571 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3572 return NULL;
3573 if (!make_dbt(dataobj, &data)) {
3574 FREE_DBT(key);
3575 return NULL;
3578 MYDB_BEGIN_ALLOW_THREADS;
3579 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3580 MYDB_END_ALLOW_THREADS;
3581 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3582 Py_INCREF(Py_None);
3583 retval = Py_None;
3585 else if (makeDBError(err)) {
3586 retval = NULL;
3588 else {
3589 switch (_DB_get_type(self->mydb)) {
3590 case -1:
3591 retval = NULL;
3592 break;
3593 case DB_BTREE:
3594 case DB_HASH:
3595 default:
3596 retval = Py_BuildValue("s#s#", key.data, key.size,
3597 data.data, data.size);
3598 break;
3599 case DB_RECNO:
3600 case DB_QUEUE:
3601 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3602 data.data, data.size);
3603 break;
3607 FREE_DBT(key);
3608 return retval;
3611 static PyObject*
3612 DBC_get_both(DBCursorObject* self, PyObject* args)
3614 int flags=0;
3615 PyObject *keyobj, *dataobj;
3617 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3618 return NULL;
3620 /* if the cursor is closed, self->mydb may be invalid */
3621 CHECK_CURSOR_NOT_CLOSED(self);
3623 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3624 self->mydb->moduleFlags.getReturnsNone);
3627 /* Return size of entry */
3628 static PyObject*
3629 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3631 int err, flags=DB_CURRENT;
3632 PyObject* retval = NULL;
3633 DBT key, data;
3635 if (!PyArg_ParseTuple(args, ":get_current_size"))
3636 return NULL;
3637 CHECK_CURSOR_NOT_CLOSED(self);
3638 CLEAR_DBT(key);
3639 CLEAR_DBT(data);
3641 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3642 getting the record size. */
3643 data.flags = DB_DBT_USERMEM;
3644 data.ulen = 0;
3645 MYDB_BEGIN_ALLOW_THREADS;
3646 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3647 MYDB_END_ALLOW_THREADS;
3648 if (err == DB_BUFFER_SMALL || !err) {
3649 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3650 retval = PyInt_FromLong((long)data.size);
3651 err = 0;
3654 FREE_DBT(key);
3655 FREE_DBT(data);
3656 RETURN_IF_ERR();
3657 return retval;
3660 static PyObject*
3661 DBC_set_both(DBCursorObject* self, PyObject* args)
3663 int flags=0;
3664 PyObject *keyobj, *dataobj;
3666 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3667 return NULL;
3669 /* if the cursor is closed, self->mydb may be invalid */
3670 CHECK_CURSOR_NOT_CLOSED(self);
3672 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3673 self->mydb->moduleFlags.cursorSetReturnsNone);
3677 static PyObject*
3678 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3680 int err, irecno, flags=0;
3681 db_recno_t recno;
3682 DBT key, data;
3683 PyObject* retval;
3684 int dlen = -1;
3685 int doff = -1;
3686 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3689 &irecno, &flags, &dlen, &doff))
3690 return NULL;
3692 CHECK_CURSOR_NOT_CLOSED(self);
3694 CLEAR_DBT(key);
3695 recno = (db_recno_t) irecno;
3696 /* use allocated space so DB will be able to realloc room for the real
3697 * key */
3698 key.data = malloc(sizeof(db_recno_t));
3699 if (key.data == NULL) {
3700 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3701 return NULL;
3703 key.size = sizeof(db_recno_t);
3704 key.ulen = key.size;
3705 memcpy(key.data, &recno, sizeof(db_recno_t));
3706 key.flags = DB_DBT_REALLOC;
3708 CLEAR_DBT(data);
3709 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3711 data.flags = DB_DBT_MALLOC;
3713 if (!add_partial_dbt(&data, dlen, doff)) {
3714 FREE_DBT(key);
3715 return NULL;
3718 MYDB_BEGIN_ALLOW_THREADS;
3719 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3720 MYDB_END_ALLOW_THREADS;
3721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3722 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3723 Py_INCREF(Py_None);
3724 retval = Py_None;
3726 else if (makeDBError(err)) {
3727 retval = NULL;
3729 else { /* Can only be used for BTrees, so no need to return int key */
3730 retval = Py_BuildValue("s#s#", key.data, key.size,
3731 data.data, data.size);
3732 FREE_DBT(data);
3734 FREE_DBT(key);
3736 return retval;
3740 static PyObject*
3741 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3743 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3747 static PyObject*
3748 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3750 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3754 static PyObject*
3755 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3757 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3761 static PyObject*
3762 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3764 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3768 static PyObject*
3769 DBC_join_item(DBCursorObject* self, PyObject* args)
3771 int err, flags=0;
3772 DBT key, data;
3773 PyObject* retval;
3775 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3776 return NULL;
3778 CHECK_CURSOR_NOT_CLOSED(self);
3780 CLEAR_DBT(key);
3781 CLEAR_DBT(data);
3782 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3783 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3784 key.flags = DB_DBT_MALLOC;
3787 MYDB_BEGIN_ALLOW_THREADS;
3788 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3789 MYDB_END_ALLOW_THREADS;
3790 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3791 && self->mydb->moduleFlags.getReturnsNone) {
3792 Py_INCREF(Py_None);
3793 retval = Py_None;
3795 else if (makeDBError(err)) {
3796 retval = NULL;
3798 else {
3799 retval = Py_BuildValue("s#", key.data, key.size);
3800 FREE_DBT(key);
3803 return retval;
3808 /* --------------------------------------------------------------------- */
3809 /* DBEnv methods */
3812 static PyObject*
3813 DBEnv_close(DBEnvObject* self, PyObject* args)
3815 int err, flags = 0;
3817 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3818 return NULL;
3819 if (!self->closed) { /* Don't close more than once */
3820 MYDB_BEGIN_ALLOW_THREADS;
3821 err = self->db_env->close(self->db_env, flags);
3822 MYDB_END_ALLOW_THREADS;
3823 /* after calling DBEnv->close, regardless of error, this DBEnv
3824 * may not be accessed again (BerkeleyDB docs). */
3825 self->closed = 1;
3826 self->db_env = NULL;
3827 RETURN_IF_ERR();
3829 RETURN_NONE();
3833 static PyObject*
3834 DBEnv_open(DBEnvObject* self, PyObject* args)
3836 int err, flags=0, mode=0660;
3837 char *db_home;
3839 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3840 return NULL;
3842 CHECK_ENV_NOT_CLOSED(self);
3844 MYDB_BEGIN_ALLOW_THREADS;
3845 err = self->db_env->open(self->db_env, db_home, flags, mode);
3846 MYDB_END_ALLOW_THREADS;
3847 RETURN_IF_ERR();
3848 self->closed = 0;
3849 self->flags = flags;
3850 RETURN_NONE();
3854 static PyObject*
3855 DBEnv_remove(DBEnvObject* self, PyObject* args)
3857 int err, flags=0;
3858 char *db_home;
3860 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3861 return NULL;
3862 CHECK_ENV_NOT_CLOSED(self);
3863 MYDB_BEGIN_ALLOW_THREADS;
3864 err = self->db_env->remove(self->db_env, db_home, flags);
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 RETURN_NONE();
3870 #if (DBVER >= 41)
3871 static PyObject*
3872 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3874 int err;
3875 u_int32_t flags=0;
3876 char *file = NULL;
3877 char *database = NULL;
3878 PyObject *txnobj = NULL;
3879 DB_TXN *txn = NULL;
3880 static char* kwnames[] = { "file", "database", "txn", "flags",
3881 NULL };
3883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
3884 &file, &database, &txnobj, &flags)) {
3885 return NULL;
3887 if (!checkTxnObj(txnobj, &txn)) {
3888 return NULL;
3890 CHECK_ENV_NOT_CLOSED(self);
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3893 MYDB_END_ALLOW_THREADS;
3894 RETURN_IF_ERR();
3895 RETURN_NONE();
3898 static PyObject*
3899 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3901 int err;
3902 u_int32_t flags=0;
3903 char *file = NULL;
3904 char *database = NULL;
3905 char *newname = NULL;
3906 PyObject *txnobj = NULL;
3907 DB_TXN *txn = NULL;
3908 static char* kwnames[] = { "file", "database", "newname", "txn",
3909 "flags", NULL };
3911 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
3912 &file, &database, &newname, &txnobj, &flags)) {
3913 return NULL;
3915 if (!checkTxnObj(txnobj, &txn)) {
3916 return NULL;
3918 CHECK_ENV_NOT_CLOSED(self);
3919 MYDB_BEGIN_ALLOW_THREADS;
3920 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3921 flags);
3922 MYDB_END_ALLOW_THREADS;
3923 RETURN_IF_ERR();
3924 RETURN_NONE();
3927 static PyObject*
3928 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3930 int err;
3931 u_int32_t flags=0;
3932 char *passwd = NULL;
3933 static char* kwnames[] = { "passwd", "flags", NULL };
3935 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3936 &passwd, &flags)) {
3937 return NULL;
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3942 MYDB_END_ALLOW_THREADS;
3944 RETURN_IF_ERR();
3945 RETURN_NONE();
3947 #endif /* DBVER >= 41 */
3949 #if (DBVER >= 40)
3950 static PyObject*
3951 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3953 int err;
3954 u_int32_t flags=0;
3955 u_int32_t timeout = 0;
3956 static char* kwnames[] = { "timeout", "flags", NULL };
3958 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3959 &timeout, &flags)) {
3960 return NULL;
3963 MYDB_BEGIN_ALLOW_THREADS;
3964 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3965 MYDB_END_ALLOW_THREADS;
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3970 #endif /* DBVER >= 40 */
3972 static PyObject*
3973 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3975 int err;
3976 long shm_key = 0;
3978 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3979 return NULL;
3980 CHECK_ENV_NOT_CLOSED(self);
3982 err = self->db_env->set_shm_key(self->db_env, shm_key);
3983 RETURN_IF_ERR();
3984 RETURN_NONE();
3987 static PyObject*
3988 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3990 int err, gbytes=0, bytes=0, ncache=0;
3992 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3993 &gbytes, &bytes, &ncache))
3994 return NULL;
3995 CHECK_ENV_NOT_CLOSED(self);
3997 MYDB_BEGIN_ALLOW_THREADS;
3998 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3999 MYDB_END_ALLOW_THREADS;
4000 RETURN_IF_ERR();
4001 RETURN_NONE();
4005 #if (DBVER >= 32)
4006 static PyObject*
4007 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4009 int err, flags=0, onoff=0;
4011 if (!PyArg_ParseTuple(args, "ii:set_flags",
4012 &flags, &onoff))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_flags(self->db_env, flags, onoff);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4022 #endif
4025 static PyObject*
4026 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4028 int err;
4029 char *dir;
4031 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_data_dir(self->db_env, dir);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4043 static PyObject*
4044 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4046 int err, lg_bsize;
4048 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4049 return NULL;
4050 CHECK_ENV_NOT_CLOSED(self);
4052 MYDB_BEGIN_ALLOW_THREADS;
4053 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4054 MYDB_END_ALLOW_THREADS;
4055 RETURN_IF_ERR();
4056 RETURN_NONE();
4060 static PyObject*
4061 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4063 int err;
4064 char *dir;
4066 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_dir(self->db_env, dir);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4077 static PyObject*
4078 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4080 int err, lg_max;
4082 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4083 return NULL;
4084 CHECK_ENV_NOT_CLOSED(self);
4086 MYDB_BEGIN_ALLOW_THREADS;
4087 err = self->db_env->set_lg_max(self->db_env, lg_max);
4088 MYDB_END_ALLOW_THREADS;
4089 RETURN_IF_ERR();
4090 RETURN_NONE();
4094 #if (DBVER >= 33)
4095 static PyObject*
4096 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4098 int err, lg_max;
4100 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4101 return NULL;
4102 CHECK_ENV_NOT_CLOSED(self);
4104 MYDB_BEGIN_ALLOW_THREADS;
4105 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4106 MYDB_END_ALLOW_THREADS;
4107 RETURN_IF_ERR();
4108 RETURN_NONE();
4110 #endif
4113 static PyObject*
4114 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4116 int err, lk_detect;
4118 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4119 return NULL;
4120 CHECK_ENV_NOT_CLOSED(self);
4122 MYDB_BEGIN_ALLOW_THREADS;
4123 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4124 MYDB_END_ALLOW_THREADS;
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4130 #if (DBVER < 45)
4131 static PyObject*
4132 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4134 int err, max;
4136 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4137 return NULL;
4138 CHECK_ENV_NOT_CLOSED(self);
4140 MYDB_BEGIN_ALLOW_THREADS;
4141 err = self->db_env->set_lk_max(self->db_env, max);
4142 MYDB_END_ALLOW_THREADS;
4143 RETURN_IF_ERR();
4144 RETURN_NONE();
4146 #endif
4149 #if (DBVER >= 32)
4151 static PyObject*
4152 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4154 int err, max;
4156 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4157 return NULL;
4158 CHECK_ENV_NOT_CLOSED(self);
4160 MYDB_BEGIN_ALLOW_THREADS;
4161 err = self->db_env->set_lk_max_locks(self->db_env, max);
4162 MYDB_END_ALLOW_THREADS;
4163 RETURN_IF_ERR();
4164 RETURN_NONE();
4168 static PyObject*
4169 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4171 int err, max;
4173 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4174 return NULL;
4175 CHECK_ENV_NOT_CLOSED(self);
4177 MYDB_BEGIN_ALLOW_THREADS;
4178 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4181 RETURN_NONE();
4185 static PyObject*
4186 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4188 int err, max;
4190 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4191 return NULL;
4192 CHECK_ENV_NOT_CLOSED(self);
4194 MYDB_BEGIN_ALLOW_THREADS;
4195 err = self->db_env->set_lk_max_objects(self->db_env, max);
4196 MYDB_END_ALLOW_THREADS;
4197 RETURN_IF_ERR();
4198 RETURN_NONE();
4201 #endif
4204 static PyObject*
4205 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4207 int err, mp_mmapsize;
4209 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4221 static PyObject*
4222 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4224 int err;
4225 char *dir;
4227 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4228 return NULL;
4229 CHECK_ENV_NOT_CLOSED(self);
4231 MYDB_BEGIN_ALLOW_THREADS;
4232 err = self->db_env->set_tmp_dir(self->db_env, dir);
4233 MYDB_END_ALLOW_THREADS;
4234 RETURN_IF_ERR();
4235 RETURN_NONE();
4239 static PyObject*
4240 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4242 int flags = 0;
4243 PyObject* txnobj = NULL;
4244 DB_TXN *txn = NULL;
4245 static char* kwnames[] = { "parent", "flags", NULL };
4247 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4248 &txnobj, &flags))
4249 return NULL;
4251 if (!checkTxnObj(txnobj, &txn))
4252 return NULL;
4253 CHECK_ENV_NOT_CLOSED(self);
4255 return (PyObject*)newDBTxnObject(self, txn, flags);
4259 static PyObject*
4260 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4262 int err, kbyte=0, min=0, flags=0;
4264 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4265 return NULL;
4266 CHECK_ENV_NOT_CLOSED(self);
4268 MYDB_BEGIN_ALLOW_THREADS;
4269 #if (DBVER >= 40)
4270 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4271 #else
4272 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4273 #endif
4274 MYDB_END_ALLOW_THREADS;
4275 RETURN_IF_ERR();
4276 RETURN_NONE();
4280 static PyObject*
4281 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4283 int err, max;
4285 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4286 return NULL;
4287 CHECK_ENV_NOT_CLOSED(self);
4289 err = self->db_env->set_tx_max(self->db_env, max);
4290 RETURN_IF_ERR();
4291 RETURN_NONE();
4295 static PyObject*
4296 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4298 int err;
4299 long stamp;
4300 time_t timestamp;
4302 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4303 return NULL;
4304 CHECK_ENV_NOT_CLOSED(self);
4305 timestamp = (time_t)stamp;
4306 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4307 RETURN_IF_ERR();
4308 RETURN_NONE();
4312 static PyObject*
4313 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4315 int err, atype, flags=0;
4316 int aborted = 0;
4318 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4319 return NULL;
4320 CHECK_ENV_NOT_CLOSED(self);
4322 MYDB_BEGIN_ALLOW_THREADS;
4323 #if (DBVER >= 40)
4324 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4325 #else
4326 err = lock_detect(self->db_env, flags, atype, &aborted);
4327 #endif
4328 MYDB_END_ALLOW_THREADS;
4329 RETURN_IF_ERR();
4330 return PyInt_FromLong(aborted);
4334 static PyObject*
4335 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4337 int flags=0;
4338 int locker, lock_mode;
4339 DBT obj;
4340 PyObject* objobj;
4342 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4343 return NULL;
4346 if (!make_dbt(objobj, &obj))
4347 return NULL;
4349 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4353 static PyObject*
4354 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4356 int err;
4357 u_int32_t theID;
4359 if (!PyArg_ParseTuple(args, ":lock_id"))
4360 return NULL;
4362 CHECK_ENV_NOT_CLOSED(self);
4363 MYDB_BEGIN_ALLOW_THREADS;
4364 #if (DBVER >= 40)
4365 err = self->db_env->lock_id(self->db_env, &theID);
4366 #else
4367 err = lock_id(self->db_env, &theID);
4368 #endif
4369 MYDB_END_ALLOW_THREADS;
4370 RETURN_IF_ERR();
4372 return PyInt_FromLong((long)theID);
4376 static PyObject*
4377 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4379 int err;
4380 DBLockObject* dblockobj;
4382 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4383 return NULL;
4385 CHECK_ENV_NOT_CLOSED(self);
4386 MYDB_BEGIN_ALLOW_THREADS;
4387 #if (DBVER >= 40)
4388 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4389 #else
4390 err = lock_put(self->db_env, &dblockobj->lock);
4391 #endif
4392 MYDB_END_ALLOW_THREADS;
4393 RETURN_IF_ERR();
4394 RETURN_NONE();
4397 #if (DBVER >= 44)
4398 static PyObject*
4399 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4401 int err;
4402 char *file;
4403 u_int32_t flags = 0;
4404 static char* kwnames[] = { "file", "flags", NULL};
4406 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4407 &file, &flags))
4408 return NULL;
4409 CHECK_ENV_NOT_CLOSED(self);
4411 MYDB_BEGIN_ALLOW_THREADS;
4412 err = self->db_env->lsn_reset(self->db_env, file, flags);
4413 MYDB_END_ALLOW_THREADS;
4414 RETURN_IF_ERR();
4415 RETURN_NONE();
4417 #endif /* DBVER >= 4.4 */
4419 #if (DBVER >= 40)
4420 static PyObject*
4421 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4423 int err;
4424 DB_LOG_STAT* statp = NULL;
4425 PyObject* d = NULL;
4426 u_int32_t flags = 0;
4428 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4429 return NULL;
4430 CHECK_ENV_NOT_CLOSED(self);
4432 MYDB_BEGIN_ALLOW_THREADS;
4433 err = self->db_env->log_stat(self->db_env, &statp, flags);
4434 MYDB_END_ALLOW_THREADS;
4435 RETURN_IF_ERR();
4437 /* Turn the stat structure into a dictionary */
4438 d = PyDict_New();
4439 if (d == NULL) {
4440 if (statp)
4441 free(statp);
4442 return NULL;
4445 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4447 MAKE_ENTRY(magic);
4448 MAKE_ENTRY(version);
4449 MAKE_ENTRY(mode);
4450 MAKE_ENTRY(lg_bsize);
4451 #if (DBVER >= 44)
4452 MAKE_ENTRY(lg_size);
4453 MAKE_ENTRY(record);
4454 #endif
4455 #if (DBVER <= 40)
4456 MAKE_ENTRY(lg_max);
4457 #endif
4458 MAKE_ENTRY(w_mbytes);
4459 MAKE_ENTRY(w_bytes);
4460 MAKE_ENTRY(wc_mbytes);
4461 MAKE_ENTRY(wc_bytes);
4462 MAKE_ENTRY(wcount);
4463 MAKE_ENTRY(wcount_fill);
4464 #if (DBVER >= 44)
4465 MAKE_ENTRY(rcount);
4466 #endif
4467 MAKE_ENTRY(scount);
4468 MAKE_ENTRY(cur_file);
4469 MAKE_ENTRY(cur_offset);
4470 MAKE_ENTRY(disk_file);
4471 MAKE_ENTRY(disk_offset);
4472 MAKE_ENTRY(maxcommitperflush);
4473 MAKE_ENTRY(mincommitperflush);
4474 MAKE_ENTRY(regsize);
4475 MAKE_ENTRY(region_wait);
4476 MAKE_ENTRY(region_nowait);
4478 #undef MAKE_ENTRY
4479 free(statp);
4480 return d;
4481 } /* DBEnv_log_stat */
4482 #endif /* DBVER >= 4.0 for log_stat method */
4485 static PyObject*
4486 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4488 int err;
4489 DB_LOCK_STAT* sp;
4490 PyObject* d = NULL;
4491 u_int32_t flags = 0;
4493 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4494 return NULL;
4495 CHECK_ENV_NOT_CLOSED(self);
4497 MYDB_BEGIN_ALLOW_THREADS;
4498 #if (DBVER >= 40)
4499 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4500 #else
4501 #if (DBVER >= 33)
4502 err = lock_stat(self->db_env, &sp);
4503 #else
4504 err = lock_stat(self->db_env, &sp, NULL);
4505 #endif
4506 #endif
4507 MYDB_END_ALLOW_THREADS;
4508 RETURN_IF_ERR();
4510 /* Turn the stat structure into a dictionary */
4511 d = PyDict_New();
4512 if (d == NULL) {
4513 free(sp);
4514 return NULL;
4517 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4519 #if (DBVER < 41)
4520 MAKE_ENTRY(lastid);
4521 #endif
4522 MAKE_ENTRY(nmodes);
4523 #if (DBVER >= 32)
4524 MAKE_ENTRY(maxlocks);
4525 MAKE_ENTRY(maxlockers);
4526 MAKE_ENTRY(maxobjects);
4527 MAKE_ENTRY(nlocks);
4528 MAKE_ENTRY(maxnlocks);
4529 #endif
4530 MAKE_ENTRY(nlockers);
4531 MAKE_ENTRY(maxnlockers);
4532 #if (DBVER >= 32)
4533 MAKE_ENTRY(nobjects);
4534 MAKE_ENTRY(maxnobjects);
4535 #endif
4536 MAKE_ENTRY(nrequests);
4537 MAKE_ENTRY(nreleases);
4538 #if (DBVER < 44)
4539 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4540 MAKE_ENTRY(nconflicts);
4541 #else
4542 MAKE_ENTRY(lock_nowait);
4543 MAKE_ENTRY(lock_wait);
4544 #endif
4545 MAKE_ENTRY(ndeadlocks);
4546 MAKE_ENTRY(regsize);
4547 MAKE_ENTRY(region_wait);
4548 MAKE_ENTRY(region_nowait);
4550 #undef MAKE_ENTRY
4551 free(sp);
4552 return d;
4556 static PyObject*
4557 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4559 int flags=0;
4560 int err;
4561 char **log_list = NULL;
4562 PyObject* list;
4563 PyObject* item = NULL;
4565 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4566 return NULL;
4568 CHECK_ENV_NOT_CLOSED(self);
4569 MYDB_BEGIN_ALLOW_THREADS;
4570 #if (DBVER >= 40)
4571 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4572 #elif (DBVER == 33)
4573 err = log_archive(self->db_env, &log_list, flags);
4574 #else
4575 err = log_archive(self->db_env, &log_list, flags, NULL);
4576 #endif
4577 MYDB_END_ALLOW_THREADS;
4578 RETURN_IF_ERR();
4580 list = PyList_New(0);
4581 if (list == NULL) {
4582 if (log_list)
4583 free(log_list);
4584 return NULL;
4587 if (log_list) {
4588 char **log_list_start;
4589 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4590 item = PyString_FromString (*log_list);
4591 if (item == NULL) {
4592 Py_DECREF(list);
4593 list = NULL;
4594 break;
4596 PyList_Append(list, item);
4597 Py_DECREF(item);
4599 free(log_list_start);
4601 return list;
4605 static PyObject*
4606 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4608 int err;
4609 DB_TXN_STAT* sp;
4610 PyObject* d = NULL;
4611 u_int32_t flags=0;
4613 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4614 return NULL;
4615 CHECK_ENV_NOT_CLOSED(self);
4617 MYDB_BEGIN_ALLOW_THREADS;
4618 #if (DBVER >= 40)
4619 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4620 #elif (DBVER == 33)
4621 err = txn_stat(self->db_env, &sp);
4622 #else
4623 err = txn_stat(self->db_env, &sp, NULL);
4624 #endif
4625 MYDB_END_ALLOW_THREADS;
4626 RETURN_IF_ERR();
4628 /* Turn the stat structure into a dictionary */
4629 d = PyDict_New();
4630 if (d == NULL) {
4631 free(sp);
4632 return NULL;
4635 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4637 MAKE_ENTRY(time_ckp);
4638 MAKE_ENTRY(last_txnid);
4639 MAKE_ENTRY(maxtxns);
4640 MAKE_ENTRY(nactive);
4641 MAKE_ENTRY(maxnactive);
4642 MAKE_ENTRY(nbegins);
4643 MAKE_ENTRY(naborts);
4644 MAKE_ENTRY(ncommits);
4645 MAKE_ENTRY(regsize);
4646 MAKE_ENTRY(region_wait);
4647 MAKE_ENTRY(region_nowait);
4649 #undef MAKE_ENTRY
4650 free(sp);
4651 return d;
4655 static PyObject*
4656 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4658 int flags=0;
4659 int oldValue=0;
4661 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4662 return NULL;
4663 CHECK_ENV_NOT_CLOSED(self);
4665 if (self->moduleFlags.getReturnsNone)
4666 ++oldValue;
4667 if (self->moduleFlags.cursorSetReturnsNone)
4668 ++oldValue;
4669 self->moduleFlags.getReturnsNone = (flags >= 1);
4670 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4671 return PyInt_FromLong(oldValue);
4675 /* --------------------------------------------------------------------- */
4676 /* DBTxn methods */
4679 static PyObject*
4680 DBTxn_commit(DBTxnObject* self, PyObject* args)
4682 int flags=0, err;
4683 DB_TXN *txn;
4685 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4686 return NULL;
4688 if (!self->txn) {
4689 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4690 "after txn_commit or txn_abort");
4691 PyErr_SetObject(DBError, t);
4692 Py_DECREF(t);
4693 return NULL;
4695 txn = self->txn;
4696 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4697 MYDB_BEGIN_ALLOW_THREADS;
4698 #if (DBVER >= 40)
4699 err = txn->commit(txn, flags);
4700 #else
4701 err = txn_commit(txn, flags);
4702 #endif
4703 MYDB_END_ALLOW_THREADS;
4704 RETURN_IF_ERR();
4705 RETURN_NONE();
4708 static PyObject*
4709 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4711 #if (DBVER >= 33)
4712 int err;
4713 char* gid=NULL;
4714 int gid_size=0;
4716 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4717 return NULL;
4719 if (gid_size != DB_XIDDATASIZE) {
4720 PyErr_SetString(PyExc_TypeError,
4721 "gid must be DB_XIDDATASIZE bytes long");
4722 return NULL;
4725 if (!self->txn) {
4726 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4727 "after txn_commit or txn_abort");
4728 PyErr_SetObject(DBError, t);
4729 Py_DECREF(t);
4730 return NULL;
4732 MYDB_BEGIN_ALLOW_THREADS;
4733 #if (DBVER >= 40)
4734 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4735 #else
4736 err = txn_prepare(self->txn, (u_int8_t*)gid);
4737 #endif
4738 MYDB_END_ALLOW_THREADS;
4739 RETURN_IF_ERR();
4740 RETURN_NONE();
4741 #else
4742 int err;
4744 if (!PyArg_ParseTuple(args, ":prepare"))
4745 return NULL;
4747 if (!self->txn) {
4748 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4749 "after txn_commit or txn_abort");
4750 PyErr_SetObject(DBError, t);
4751 Py_DECREF(t);
4752 return NULL;
4754 MYDB_BEGIN_ALLOW_THREADS;
4755 err = txn_prepare(self->txn);
4756 MYDB_END_ALLOW_THREADS;
4757 RETURN_IF_ERR();
4758 RETURN_NONE();
4759 #endif
4763 static PyObject*
4764 DBTxn_abort(DBTxnObject* self, PyObject* args)
4766 int err;
4767 DB_TXN *txn;
4769 if (!PyArg_ParseTuple(args, ":abort"))
4770 return NULL;
4772 if (!self->txn) {
4773 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4774 "after txn_commit or txn_abort");
4775 PyErr_SetObject(DBError, t);
4776 Py_DECREF(t);
4777 return NULL;
4779 txn = self->txn;
4780 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4781 MYDB_BEGIN_ALLOW_THREADS;
4782 #if (DBVER >= 40)
4783 err = txn->abort(txn);
4784 #else
4785 err = txn_abort(txn);
4786 #endif
4787 MYDB_END_ALLOW_THREADS;
4788 RETURN_IF_ERR();
4789 RETURN_NONE();
4793 static PyObject*
4794 DBTxn_id(DBTxnObject* self, PyObject* args)
4796 int id;
4798 if (!PyArg_ParseTuple(args, ":id"))
4799 return NULL;
4801 if (!self->txn) {
4802 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4803 "after txn_commit or txn_abort");
4804 PyErr_SetObject(DBError, t);
4805 Py_DECREF(t);
4806 return NULL;
4808 MYDB_BEGIN_ALLOW_THREADS;
4809 #if (DBVER >= 40)
4810 id = self->txn->id(self->txn);
4811 #else
4812 id = txn_id(self->txn);
4813 #endif
4814 MYDB_END_ALLOW_THREADS;
4815 return PyInt_FromLong(id);
4818 #if (DBVER >= 43)
4819 /* --------------------------------------------------------------------- */
4820 /* DBSequence methods */
4823 static PyObject*
4824 DBSequence_close(DBSequenceObject* self, PyObject* args)
4826 int err, flags=0;
4827 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4828 return NULL;
4829 CHECK_SEQUENCE_NOT_CLOSED(self)
4831 MYDB_BEGIN_ALLOW_THREADS
4832 err = self->sequence->close(self->sequence, flags);
4833 self->sequence = NULL;
4834 MYDB_END_ALLOW_THREADS
4836 RETURN_IF_ERR();
4838 RETURN_NONE();
4841 static PyObject*
4842 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4844 int err, flags = 0;
4845 int delta = 1;
4846 db_seq_t value;
4847 PyObject *txnobj = NULL;
4848 DB_TXN *txn = NULL;
4849 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4850 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4851 return NULL;
4852 CHECK_SEQUENCE_NOT_CLOSED(self)
4854 if (!checkTxnObj(txnobj, &txn))
4855 return NULL;
4857 MYDB_BEGIN_ALLOW_THREADS
4858 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4859 MYDB_END_ALLOW_THREADS
4861 RETURN_IF_ERR();
4862 return PyLong_FromLongLong(value);
4866 static PyObject*
4867 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4869 if (!PyArg_ParseTuple(args,":get_dbp"))
4870 return NULL;
4871 CHECK_SEQUENCE_NOT_CLOSED(self)
4872 Py_INCREF(self->mydb);
4873 return (PyObject* )self->mydb;
4876 static PyObject*
4877 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4879 int err;
4880 DBT key;
4881 CHECK_SEQUENCE_NOT_CLOSED(self)
4882 MYDB_BEGIN_ALLOW_THREADS
4883 err = self->sequence->get_key(self->sequence, &key);
4884 MYDB_END_ALLOW_THREADS
4886 RETURN_IF_ERR();
4888 return PyString_FromStringAndSize(key.data, key.size);
4891 static PyObject*
4892 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4894 int err;
4895 db_seq_t value;
4896 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4897 return NULL;
4898 CHECK_SEQUENCE_NOT_CLOSED(self)
4900 MYDB_BEGIN_ALLOW_THREADS
4901 err = self->sequence->initial_value(self->sequence, value);
4902 MYDB_END_ALLOW_THREADS
4904 RETURN_IF_ERR();
4906 RETURN_NONE();
4909 static PyObject*
4910 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4912 int err, flags = 0;
4913 PyObject* keyobj;
4914 PyObject *txnobj = NULL;
4915 DB_TXN *txn = NULL;
4916 DBT key;
4918 static char* kwnames[] = {"key", "txn", "flags", NULL };
4919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4920 return NULL;
4922 if (!checkTxnObj(txnobj, &txn))
4923 return NULL;
4925 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4926 return NULL;
4928 MYDB_BEGIN_ALLOW_THREADS
4929 err = self->sequence->open(self->sequence, txn, &key, flags);
4930 MYDB_END_ALLOW_THREADS
4932 CLEAR_DBT(key);
4933 RETURN_IF_ERR();
4935 RETURN_NONE();
4938 static PyObject*
4939 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4941 int err, flags = 0;
4942 PyObject *txnobj = NULL;
4943 DB_TXN *txn = NULL;
4945 static char* kwnames[] = {"txn", "flags", NULL };
4946 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4947 return NULL;
4949 if (!checkTxnObj(txnobj, &txn))
4950 return NULL;
4952 CHECK_SEQUENCE_NOT_CLOSED(self)
4954 MYDB_BEGIN_ALLOW_THREADS
4955 err = self->sequence->remove(self->sequence, txn, flags);
4956 MYDB_END_ALLOW_THREADS
4958 RETURN_IF_ERR();
4959 RETURN_NONE();
4962 static PyObject*
4963 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4965 int err, size;
4966 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4967 return NULL;
4968 CHECK_SEQUENCE_NOT_CLOSED(self)
4970 MYDB_BEGIN_ALLOW_THREADS
4971 err = self->sequence->set_cachesize(self->sequence, size);
4972 MYDB_END_ALLOW_THREADS
4974 RETURN_IF_ERR();
4975 RETURN_NONE();
4978 static PyObject*
4979 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4981 int err, size;
4982 if (!PyArg_ParseTuple(args,":get_cachesize"))
4983 return NULL;
4984 CHECK_SEQUENCE_NOT_CLOSED(self)
4986 MYDB_BEGIN_ALLOW_THREADS
4987 err = self->sequence->get_cachesize(self->sequence, &size);
4988 MYDB_END_ALLOW_THREADS
4990 RETURN_IF_ERR();
4991 return PyInt_FromLong(size);
4994 static PyObject*
4995 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4997 int err, flags = 0;
4998 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4999 return NULL;
5000 CHECK_SEQUENCE_NOT_CLOSED(self)
5002 MYDB_BEGIN_ALLOW_THREADS
5003 err = self->sequence->set_flags(self->sequence, flags);
5004 MYDB_END_ALLOW_THREADS
5006 RETURN_IF_ERR();
5007 RETURN_NONE();
5011 static PyObject*
5012 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5014 unsigned int flags;
5015 int err;
5016 if (!PyArg_ParseTuple(args,":get_flags"))
5017 return NULL;
5018 CHECK_SEQUENCE_NOT_CLOSED(self)
5020 MYDB_BEGIN_ALLOW_THREADS
5021 err = self->sequence->get_flags(self->sequence, &flags);
5022 MYDB_END_ALLOW_THREADS
5024 RETURN_IF_ERR();
5025 return PyInt_FromLong((int)flags);
5028 static PyObject*
5029 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5031 int err;
5032 db_seq_t min, max;
5033 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5034 return NULL;
5035 CHECK_SEQUENCE_NOT_CLOSED(self)
5037 MYDB_BEGIN_ALLOW_THREADS
5038 err = self->sequence->set_range(self->sequence, min, max);
5039 MYDB_END_ALLOW_THREADS
5041 RETURN_IF_ERR();
5042 RETURN_NONE();
5045 static PyObject*
5046 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5048 int err;
5049 db_seq_t min, max;
5050 if (!PyArg_ParseTuple(args,":get_range"))
5051 return NULL;
5052 CHECK_SEQUENCE_NOT_CLOSED(self)
5054 MYDB_BEGIN_ALLOW_THREADS
5055 err = self->sequence->get_range(self->sequence, &min, &max);
5056 MYDB_END_ALLOW_THREADS
5058 RETURN_IF_ERR();
5059 return Py_BuildValue("(LL)", min, max);
5062 static PyObject*
5063 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5065 int err, flags = 0;
5066 DB_SEQUENCE_STAT* sp = NULL;
5067 PyObject* dict_stat;
5068 static char* kwnames[] = {"flags", NULL };
5069 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5070 return NULL;
5071 CHECK_SEQUENCE_NOT_CLOSED(self);
5073 MYDB_BEGIN_ALLOW_THREADS;
5074 err = self->sequence->stat(self->sequence, &sp, flags);
5075 MYDB_END_ALLOW_THREADS;
5076 RETURN_IF_ERR();
5078 if ((dict_stat = PyDict_New()) == NULL) {
5079 free(sp);
5080 return NULL;
5084 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5085 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5087 MAKE_INT_ENTRY(wait);
5088 MAKE_INT_ENTRY(nowait);
5089 MAKE_LONG_LONG_ENTRY(current);
5090 MAKE_LONG_LONG_ENTRY(value);
5091 MAKE_LONG_LONG_ENTRY(last_value);
5092 MAKE_LONG_LONG_ENTRY(min);
5093 MAKE_LONG_LONG_ENTRY(max);
5094 MAKE_INT_ENTRY(cache_size);
5095 MAKE_INT_ENTRY(flags);
5097 #undef MAKE_INT_ENTRY
5098 #undef MAKE_LONG_LONG_ENTRY
5100 free(sp);
5101 return dict_stat;
5103 #endif
5106 /* --------------------------------------------------------------------- */
5107 /* Method definition tables and type objects */
5109 static PyMethodDef DB_methods[] = {
5110 {"append", (PyCFunction)DB_append, METH_VARARGS},
5111 #if (DBVER >= 33)
5112 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5113 #endif
5114 {"close", (PyCFunction)DB_close, METH_VARARGS},
5115 #if (DBVER >= 32)
5116 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5117 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5118 #endif
5119 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5120 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5121 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5122 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5123 #if (DBVER >= 33)
5124 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5125 #endif
5126 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5127 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5128 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5129 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5130 {"join", (PyCFunction)DB_join, METH_VARARGS},
5131 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5132 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5133 {"items", (PyCFunction)DB_items, METH_VARARGS},
5134 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5135 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5136 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5137 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5138 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5139 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5140 #if (DBVER >= 33)
5141 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5142 #endif
5143 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5144 #if (DBVER >= 41)
5145 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5146 #endif
5147 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5148 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5149 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5150 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5151 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5152 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5153 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5154 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5155 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5156 #if (DBVER >= 32)
5157 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5158 #endif
5159 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5160 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5161 #if (DBVER >= 33)
5162 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5163 #endif
5164 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5165 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5166 {"values", (PyCFunction)DB_values, METH_VARARGS},
5167 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5168 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5169 {NULL, NULL} /* sentinel */
5173 static PyMappingMethods DB_mapping = {
5174 DB_length, /*mp_length*/
5175 (binaryfunc)DB_subscript, /*mp_subscript*/
5176 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5180 static PyMethodDef DBCursor_methods[] = {
5181 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5182 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5183 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5184 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5185 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5186 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5187 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5188 #if (DBVER >= 33)
5189 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5190 #endif
5191 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5192 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5193 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5194 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5195 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5196 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5197 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5198 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5199 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5200 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5201 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5202 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5203 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5204 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5205 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5206 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5207 {NULL, NULL} /* sentinel */
5211 static PyMethodDef DBEnv_methods[] = {
5212 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5213 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5214 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5215 #if (DBVER >= 41)
5216 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5217 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5218 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5219 #endif
5220 #if (DBVER >= 40)
5221 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5222 #endif
5223 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5224 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5225 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5226 #if (DBVER >= 32)
5227 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5228 #endif
5229 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5230 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5231 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5232 #if (DBVER >= 33)
5233 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5234 #endif
5235 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5236 #if (DBVER < 45)
5237 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5238 #endif
5239 #if (DBVER >= 32)
5240 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5241 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5242 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5243 #endif
5244 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5245 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5246 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5247 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5248 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5249 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5250 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5251 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5252 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5253 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5254 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5255 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5256 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5257 #if (DBVER >= 40)
5258 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5259 #endif
5260 #if (DBVER >= 44)
5261 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5262 #endif
5263 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5264 {NULL, NULL} /* sentinel */
5268 static PyMethodDef DBTxn_methods[] = {
5269 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5270 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5271 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5272 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5273 {NULL, NULL} /* sentinel */
5277 #if (DBVER >= 43)
5278 static PyMethodDef DBSequence_methods[] = {
5279 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5280 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5281 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5282 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5283 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5284 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5285 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5286 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5287 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5288 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5289 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5290 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5291 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5292 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5293 {NULL, NULL} /* sentinel */
5295 #endif
5298 static PyObject*
5299 DB_getattr(DBObject* self, char *name)
5301 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5305 static PyObject*
5306 DBEnv_getattr(DBEnvObject* self, char *name)
5308 if (!strcmp(name, "db_home")) {
5309 CHECK_ENV_NOT_CLOSED(self);
5310 if (self->db_env->db_home == NULL) {
5311 RETURN_NONE();
5313 return PyString_FromString(self->db_env->db_home);
5316 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5320 static PyObject*
5321 DBCursor_getattr(DBCursorObject* self, char *name)
5323 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5326 static PyObject*
5327 DBTxn_getattr(DBTxnObject* self, char *name)
5329 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5332 static PyObject*
5333 DBLock_getattr(DBLockObject* self, char *name)
5335 return NULL;
5338 #if (DBVER >= 43)
5339 static PyObject*
5340 DBSequence_getattr(DBSequenceObject* self, char *name)
5342 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5344 #endif
5346 statichere PyTypeObject DB_Type = {
5347 PyObject_HEAD_INIT(NULL)
5348 0, /*ob_size*/
5349 "DB", /*tp_name*/
5350 sizeof(DBObject), /*tp_basicsize*/
5351 0, /*tp_itemsize*/
5352 /* methods */
5353 (destructor)DB_dealloc, /*tp_dealloc*/
5354 0, /*tp_print*/
5355 (getattrfunc)DB_getattr, /*tp_getattr*/
5356 0, /*tp_setattr*/
5357 0, /*tp_compare*/
5358 0, /*tp_repr*/
5359 0, /*tp_as_number*/
5360 0, /*tp_as_sequence*/
5361 &DB_mapping,/*tp_as_mapping*/
5362 0, /*tp_hash*/
5363 #ifdef HAVE_WEAKREF
5364 0, /* tp_call */
5365 0, /* tp_str */
5366 0, /* tp_getattro */
5367 0, /* tp_setattro */
5368 0, /* tp_as_buffer */
5369 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5370 0, /* tp_doc */
5371 0, /* tp_traverse */
5372 0, /* tp_clear */
5373 0, /* tp_richcompare */
5374 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5375 #endif
5379 statichere PyTypeObject DBCursor_Type = {
5380 PyObject_HEAD_INIT(NULL)
5381 0, /*ob_size*/
5382 "DBCursor", /*tp_name*/
5383 sizeof(DBCursorObject), /*tp_basicsize*/
5384 0, /*tp_itemsize*/
5385 /* methods */
5386 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5387 0, /*tp_print*/
5388 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5389 0, /*tp_setattr*/
5390 0, /*tp_compare*/
5391 0, /*tp_repr*/
5392 0, /*tp_as_number*/
5393 0, /*tp_as_sequence*/
5394 0, /*tp_as_mapping*/
5395 0, /*tp_hash*/
5396 #ifdef HAVE_WEAKREF
5397 0, /* tp_call */
5398 0, /* tp_str */
5399 0, /* tp_getattro */
5400 0, /* tp_setattro */
5401 0, /* tp_as_buffer */
5402 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5403 0, /* tp_doc */
5404 0, /* tp_traverse */
5405 0, /* tp_clear */
5406 0, /* tp_richcompare */
5407 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5408 #endif
5412 statichere PyTypeObject DBEnv_Type = {
5413 PyObject_HEAD_INIT(NULL)
5414 0, /*ob_size*/
5415 "DBEnv", /*tp_name*/
5416 sizeof(DBEnvObject), /*tp_basicsize*/
5417 0, /*tp_itemsize*/
5418 /* methods */
5419 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5420 0, /*tp_print*/
5421 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5422 0, /*tp_setattr*/
5423 0, /*tp_compare*/
5424 0, /*tp_repr*/
5425 0, /*tp_as_number*/
5426 0, /*tp_as_sequence*/
5427 0, /*tp_as_mapping*/
5428 0, /*tp_hash*/
5429 #ifdef HAVE_WEAKREF
5430 0, /* tp_call */
5431 0, /* tp_str */
5432 0, /* tp_getattro */
5433 0, /* tp_setattro */
5434 0, /* tp_as_buffer */
5435 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5436 0, /* tp_doc */
5437 0, /* tp_traverse */
5438 0, /* tp_clear */
5439 0, /* tp_richcompare */
5440 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5441 #endif
5444 statichere PyTypeObject DBTxn_Type = {
5445 PyObject_HEAD_INIT(NULL)
5446 0, /*ob_size*/
5447 "DBTxn", /*tp_name*/
5448 sizeof(DBTxnObject), /*tp_basicsize*/
5449 0, /*tp_itemsize*/
5450 /* methods */
5451 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5452 0, /*tp_print*/
5453 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5454 0, /*tp_setattr*/
5455 0, /*tp_compare*/
5456 0, /*tp_repr*/
5457 0, /*tp_as_number*/
5458 0, /*tp_as_sequence*/
5459 0, /*tp_as_mapping*/
5460 0, /*tp_hash*/
5461 #ifdef HAVE_WEAKREF
5462 0, /* tp_call */
5463 0, /* tp_str */
5464 0, /* tp_getattro */
5465 0, /* tp_setattro */
5466 0, /* tp_as_buffer */
5467 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5468 0, /* tp_doc */
5469 0, /* tp_traverse */
5470 0, /* tp_clear */
5471 0, /* tp_richcompare */
5472 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5473 #endif
5477 statichere PyTypeObject DBLock_Type = {
5478 PyObject_HEAD_INIT(NULL)
5479 0, /*ob_size*/
5480 "DBLock", /*tp_name*/
5481 sizeof(DBLockObject), /*tp_basicsize*/
5482 0, /*tp_itemsize*/
5483 /* methods */
5484 (destructor)DBLock_dealloc, /*tp_dealloc*/
5485 0, /*tp_print*/
5486 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5487 0, /*tp_setattr*/
5488 0, /*tp_compare*/
5489 0, /*tp_repr*/
5490 0, /*tp_as_number*/
5491 0, /*tp_as_sequence*/
5492 0, /*tp_as_mapping*/
5493 0, /*tp_hash*/
5494 #ifdef HAVE_WEAKREF
5495 0, /* tp_call */
5496 0, /* tp_str */
5497 0, /* tp_getattro */
5498 0, /* tp_setattro */
5499 0, /* tp_as_buffer */
5500 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5501 0, /* tp_doc */
5502 0, /* tp_traverse */
5503 0, /* tp_clear */
5504 0, /* tp_richcompare */
5505 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5506 #endif
5509 #if (DBVER >= 43)
5510 statichere PyTypeObject DBSequence_Type = {
5511 PyObject_HEAD_INIT(NULL)
5512 0, /*ob_size*/
5513 "DBSequence", /*tp_name*/
5514 sizeof(DBSequenceObject), /*tp_basicsize*/
5515 0, /*tp_itemsize*/
5516 /* methods */
5517 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5518 0, /*tp_print*/
5519 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5520 0, /*tp_setattr*/
5521 0, /*tp_compare*/
5522 0, /*tp_repr*/
5523 0, /*tp_as_number*/
5524 0, /*tp_as_sequence*/
5525 0, /*tp_as_mapping*/
5526 0, /*tp_hash*/
5527 #ifdef HAVE_WEAKREF
5528 0, /* tp_call */
5529 0, /* tp_str */
5530 0, /* tp_getattro */
5531 0, /* tp_setattro */
5532 0, /* tp_as_buffer */
5533 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5534 0, /* tp_doc */
5535 0, /* tp_traverse */
5536 0, /* tp_clear */
5537 0, /* tp_richcompare */
5538 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5539 #endif
5541 #endif
5543 /* --------------------------------------------------------------------- */
5544 /* Module-level functions */
5546 static PyObject*
5547 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5549 PyObject* dbenvobj = NULL;
5550 int flags = 0;
5551 static char* kwnames[] = { "dbEnv", "flags", NULL};
5553 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5554 &dbenvobj, &flags))
5555 return NULL;
5556 if (dbenvobj == Py_None)
5557 dbenvobj = NULL;
5558 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5559 makeTypeError("DBEnv", dbenvobj);
5560 return NULL;
5563 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5567 static PyObject*
5568 DBEnv_construct(PyObject* self, PyObject* args)
5570 int flags = 0;
5571 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5572 return (PyObject* )newDBEnvObject(flags);
5575 #if (DBVER >= 43)
5576 static PyObject*
5577 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5579 PyObject* dbobj;
5580 int flags = 0;
5581 static char* kwnames[] = { "db", "flags", NULL};
5583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5584 return NULL;
5585 if (!DBObject_Check(dbobj)) {
5586 makeTypeError("DB", dbobj);
5587 return NULL;
5589 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5591 #endif
5593 static char bsddb_version_doc[] =
5594 "Returns a tuple of major, minor, and patch release numbers of the\n\
5595 underlying DB library.";
5597 static PyObject*
5598 bsddb_version(PyObject* self, PyObject* args)
5600 int major, minor, patch;
5602 if (!PyArg_ParseTuple(args, ":version"))
5603 return NULL;
5604 db_version(&major, &minor, &patch);
5605 return Py_BuildValue("(iii)", major, minor, patch);
5609 /* List of functions defined in the module */
5611 static PyMethodDef bsddb_methods[] = {
5612 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5613 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5614 #if (DBVER >= 43)
5615 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5616 #endif
5617 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5618 {NULL, NULL} /* sentinel */
5622 /* --------------------------------------------------------------------- */
5623 /* Module initialization */
5626 /* Convenience routine to export an integer value.
5627 * Errors are silently ignored, for better or for worse...
5629 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5631 #define MODULE_NAME_MAX_LEN 11
5632 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5634 DL_EXPORT(void) init_bsddb(void)
5636 PyObject* m;
5637 PyObject* d;
5638 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5639 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5640 PyObject* cvsid_s = PyString_FromString( rcs_id );
5642 /* Initialize the type of the new type objects here; doing it here
5643 is required for portability to Windows without requiring C++. */
5644 DB_Type.ob_type = &PyType_Type;
5645 DBCursor_Type.ob_type = &PyType_Type;
5646 DBEnv_Type.ob_type = &PyType_Type;
5647 DBTxn_Type.ob_type = &PyType_Type;
5648 DBLock_Type.ob_type = &PyType_Type;
5649 #if (DBVER >= 43)
5650 DBSequence_Type.ob_type = &PyType_Type;
5651 #endif
5654 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5655 /* Save the current interpreter, so callbacks can do the right thing. */
5656 _db_interpreterState = PyThreadState_GET()->interp;
5657 #endif
5659 /* Create the module and add the functions */
5660 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5661 if (m == NULL)
5662 return;
5664 /* Add some symbolic constants to the module */
5665 d = PyModule_GetDict(m);
5666 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5667 PyDict_SetItemString(d, "cvsid", cvsid_s);
5668 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5669 Py_DECREF(pybsddb_version_s);
5670 pybsddb_version_s = NULL;
5671 Py_DECREF(cvsid_s);
5672 cvsid_s = NULL;
5673 Py_DECREF(db_version_s);
5674 db_version_s = NULL;
5676 ADD_INT(d, DB_VERSION_MAJOR);
5677 ADD_INT(d, DB_VERSION_MINOR);
5678 ADD_INT(d, DB_VERSION_PATCH);
5680 ADD_INT(d, DB_MAX_PAGES);
5681 ADD_INT(d, DB_MAX_RECORDS);
5683 #if (DBVER >= 42)
5684 ADD_INT(d, DB_RPCCLIENT);
5685 #else
5686 ADD_INT(d, DB_CLIENT);
5687 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5688 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5689 #endif
5690 ADD_INT(d, DB_XA_CREATE);
5692 ADD_INT(d, DB_CREATE);
5693 ADD_INT(d, DB_NOMMAP);
5694 ADD_INT(d, DB_THREAD);
5696 ADD_INT(d, DB_FORCE);
5697 ADD_INT(d, DB_INIT_CDB);
5698 ADD_INT(d, DB_INIT_LOCK);
5699 ADD_INT(d, DB_INIT_LOG);
5700 ADD_INT(d, DB_INIT_MPOOL);
5701 ADD_INT(d, DB_INIT_TXN);
5702 #if (DBVER >= 32)
5703 ADD_INT(d, DB_JOINENV);
5704 #endif
5706 ADD_INT(d, DB_RECOVER);
5707 ADD_INT(d, DB_RECOVER_FATAL);
5708 ADD_INT(d, DB_TXN_NOSYNC);
5709 ADD_INT(d, DB_USE_ENVIRON);
5710 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5712 ADD_INT(d, DB_LOCKDOWN);
5713 ADD_INT(d, DB_PRIVATE);
5714 ADD_INT(d, DB_SYSTEM_MEM);
5716 ADD_INT(d, DB_TXN_SYNC);
5717 ADD_INT(d, DB_TXN_NOWAIT);
5719 ADD_INT(d, DB_EXCL);
5720 ADD_INT(d, DB_FCNTL_LOCKING);
5721 ADD_INT(d, DB_ODDFILESIZE);
5722 ADD_INT(d, DB_RDWRMASTER);
5723 ADD_INT(d, DB_RDONLY);
5724 ADD_INT(d, DB_TRUNCATE);
5725 #if (DBVER >= 32)
5726 ADD_INT(d, DB_EXTENT);
5727 ADD_INT(d, DB_CDB_ALLDB);
5728 ADD_INT(d, DB_VERIFY);
5729 #endif
5730 ADD_INT(d, DB_UPGRADE);
5732 ADD_INT(d, DB_AGGRESSIVE);
5733 ADD_INT(d, DB_NOORDERCHK);
5734 ADD_INT(d, DB_ORDERCHKONLY);
5735 ADD_INT(d, DB_PR_PAGE);
5736 #if ! (DBVER >= 33)
5737 ADD_INT(d, DB_VRFY_FLAGMASK);
5738 ADD_INT(d, DB_PR_HEADERS);
5739 #endif
5740 ADD_INT(d, DB_PR_RECOVERYTEST);
5741 ADD_INT(d, DB_SALVAGE);
5743 ADD_INT(d, DB_LOCK_NORUN);
5744 ADD_INT(d, DB_LOCK_DEFAULT);
5745 ADD_INT(d, DB_LOCK_OLDEST);
5746 ADD_INT(d, DB_LOCK_RANDOM);
5747 ADD_INT(d, DB_LOCK_YOUNGEST);
5748 #if (DBVER >= 33)
5749 ADD_INT(d, DB_LOCK_MAXLOCKS);
5750 ADD_INT(d, DB_LOCK_MINLOCKS);
5751 ADD_INT(d, DB_LOCK_MINWRITE);
5752 #endif
5755 #if (DBVER >= 33)
5756 /* docs say to use zero instead */
5757 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5758 #else
5759 ADD_INT(d, DB_LOCK_CONFLICT);
5760 #endif
5762 ADD_INT(d, DB_LOCK_DUMP);
5763 ADD_INT(d, DB_LOCK_GET);
5764 ADD_INT(d, DB_LOCK_INHERIT);
5765 ADD_INT(d, DB_LOCK_PUT);
5766 ADD_INT(d, DB_LOCK_PUT_ALL);
5767 ADD_INT(d, DB_LOCK_PUT_OBJ);
5769 ADD_INT(d, DB_LOCK_NG);
5770 ADD_INT(d, DB_LOCK_READ);
5771 ADD_INT(d, DB_LOCK_WRITE);
5772 ADD_INT(d, DB_LOCK_NOWAIT);
5773 #if (DBVER >= 32)
5774 ADD_INT(d, DB_LOCK_WAIT);
5775 #endif
5776 ADD_INT(d, DB_LOCK_IWRITE);
5777 ADD_INT(d, DB_LOCK_IREAD);
5778 ADD_INT(d, DB_LOCK_IWR);
5779 #if (DBVER >= 33)
5780 #if (DBVER < 44)
5781 ADD_INT(d, DB_LOCK_DIRTY);
5782 #else
5783 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5784 #endif
5785 ADD_INT(d, DB_LOCK_WWRITE);
5786 #endif
5788 ADD_INT(d, DB_LOCK_RECORD);
5789 ADD_INT(d, DB_LOCK_UPGRADE);
5790 #if (DBVER >= 32)
5791 ADD_INT(d, DB_LOCK_SWITCH);
5792 #endif
5793 #if (DBVER >= 33)
5794 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5795 #endif
5797 ADD_INT(d, DB_LOCK_NOWAIT);
5798 ADD_INT(d, DB_LOCK_RECORD);
5799 ADD_INT(d, DB_LOCK_UPGRADE);
5801 #if (DBVER >= 33)
5802 ADD_INT(d, DB_LSTAT_ABORTED);
5803 #if (DBVER < 43)
5804 ADD_INT(d, DB_LSTAT_ERR);
5805 #endif
5806 ADD_INT(d, DB_LSTAT_FREE);
5807 ADD_INT(d, DB_LSTAT_HELD);
5808 #if (DBVER == 33)
5809 ADD_INT(d, DB_LSTAT_NOGRANT);
5810 #endif
5811 ADD_INT(d, DB_LSTAT_PENDING);
5812 ADD_INT(d, DB_LSTAT_WAITING);
5813 #endif
5815 ADD_INT(d, DB_ARCH_ABS);
5816 ADD_INT(d, DB_ARCH_DATA);
5817 ADD_INT(d, DB_ARCH_LOG);
5818 #if (DBVER >= 42)
5819 ADD_INT(d, DB_ARCH_REMOVE);
5820 #endif
5822 ADD_INT(d, DB_BTREE);
5823 ADD_INT(d, DB_HASH);
5824 ADD_INT(d, DB_RECNO);
5825 ADD_INT(d, DB_QUEUE);
5826 ADD_INT(d, DB_UNKNOWN);
5828 ADD_INT(d, DB_DUP);
5829 ADD_INT(d, DB_DUPSORT);
5830 ADD_INT(d, DB_RECNUM);
5831 ADD_INT(d, DB_RENUMBER);
5832 ADD_INT(d, DB_REVSPLITOFF);
5833 ADD_INT(d, DB_SNAPSHOT);
5835 ADD_INT(d, DB_JOIN_NOSORT);
5837 ADD_INT(d, DB_AFTER);
5838 ADD_INT(d, DB_APPEND);
5839 ADD_INT(d, DB_BEFORE);
5840 #if (DBVER < 45)
5841 ADD_INT(d, DB_CACHED_COUNTS);
5842 #endif
5843 #if (DBVER >= 41)
5844 _addIntToDict(d, "DB_CHECKPOINT", 0);
5845 #else
5846 ADD_INT(d, DB_CHECKPOINT);
5847 ADD_INT(d, DB_CURLSN);
5848 #endif
5849 #if ((DBVER >= 33) && (DBVER <= 41))
5850 ADD_INT(d, DB_COMMIT);
5851 #endif
5852 ADD_INT(d, DB_CONSUME);
5853 #if (DBVER >= 32)
5854 ADD_INT(d, DB_CONSUME_WAIT);
5855 #endif
5856 ADD_INT(d, DB_CURRENT);
5857 #if (DBVER >= 33)
5858 ADD_INT(d, DB_FAST_STAT);
5859 #endif
5860 ADD_INT(d, DB_FIRST);
5861 ADD_INT(d, DB_FLUSH);
5862 ADD_INT(d, DB_GET_BOTH);
5863 ADD_INT(d, DB_GET_RECNO);
5864 ADD_INT(d, DB_JOIN_ITEM);
5865 ADD_INT(d, DB_KEYFIRST);
5866 ADD_INT(d, DB_KEYLAST);
5867 ADD_INT(d, DB_LAST);
5868 ADD_INT(d, DB_NEXT);
5869 ADD_INT(d, DB_NEXT_DUP);
5870 ADD_INT(d, DB_NEXT_NODUP);
5871 ADD_INT(d, DB_NODUPDATA);
5872 ADD_INT(d, DB_NOOVERWRITE);
5873 ADD_INT(d, DB_NOSYNC);
5874 ADD_INT(d, DB_POSITION);
5875 ADD_INT(d, DB_PREV);
5876 ADD_INT(d, DB_PREV_NODUP);
5877 #if (DBVER < 45)
5878 ADD_INT(d, DB_RECORDCOUNT);
5879 #endif
5880 ADD_INT(d, DB_SET);
5881 ADD_INT(d, DB_SET_RANGE);
5882 ADD_INT(d, DB_SET_RECNO);
5883 ADD_INT(d, DB_WRITECURSOR);
5885 ADD_INT(d, DB_OPFLAGS_MASK);
5886 ADD_INT(d, DB_RMW);
5887 #if (DBVER >= 33)
5888 ADD_INT(d, DB_DIRTY_READ);
5889 ADD_INT(d, DB_MULTIPLE);
5890 ADD_INT(d, DB_MULTIPLE_KEY);
5891 #endif
5893 #if (DBVER >= 44)
5894 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5895 ADD_INT(d, DB_READ_COMMITTED);
5896 #endif
5898 #if (DBVER >= 33)
5899 ADD_INT(d, DB_DONOTINDEX);
5900 #endif
5902 #if (DBVER >= 41)
5903 _addIntToDict(d, "DB_INCOMPLETE", 0);
5904 #else
5905 ADD_INT(d, DB_INCOMPLETE);
5906 #endif
5907 ADD_INT(d, DB_KEYEMPTY);
5908 ADD_INT(d, DB_KEYEXIST);
5909 ADD_INT(d, DB_LOCK_DEADLOCK);
5910 ADD_INT(d, DB_LOCK_NOTGRANTED);
5911 ADD_INT(d, DB_NOSERVER);
5912 ADD_INT(d, DB_NOSERVER_HOME);
5913 ADD_INT(d, DB_NOSERVER_ID);
5914 ADD_INT(d, DB_NOTFOUND);
5915 ADD_INT(d, DB_OLD_VERSION);
5916 ADD_INT(d, DB_RUNRECOVERY);
5917 ADD_INT(d, DB_VERIFY_BAD);
5918 #if (DBVER >= 33)
5919 ADD_INT(d, DB_PAGE_NOTFOUND);
5920 ADD_INT(d, DB_SECONDARY_BAD);
5921 #endif
5922 #if (DBVER >= 40)
5923 ADD_INT(d, DB_STAT_CLEAR);
5924 ADD_INT(d, DB_REGION_INIT);
5925 ADD_INT(d, DB_NOLOCKING);
5926 ADD_INT(d, DB_YIELDCPU);
5927 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5928 ADD_INT(d, DB_NOPANIC);
5929 #endif
5931 #if (DBVER >= 42)
5932 ADD_INT(d, DB_TIME_NOTGRANTED);
5933 ADD_INT(d, DB_TXN_NOT_DURABLE);
5934 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5935 ADD_INT(d, DB_LOG_AUTOREMOVE);
5936 ADD_INT(d, DB_DIRECT_LOG);
5937 ADD_INT(d, DB_DIRECT_DB);
5938 ADD_INT(d, DB_INIT_REP);
5939 ADD_INT(d, DB_ENCRYPT);
5940 ADD_INT(d, DB_CHKSUM);
5941 #endif
5943 #if (DBVER >= 43)
5944 ADD_INT(d, DB_LOG_INMEMORY);
5945 ADD_INT(d, DB_BUFFER_SMALL);
5946 ADD_INT(d, DB_SEQ_DEC);
5947 ADD_INT(d, DB_SEQ_INC);
5948 ADD_INT(d, DB_SEQ_WRAP);
5949 #endif
5951 #if (DBVER >= 41)
5952 ADD_INT(d, DB_ENCRYPT_AES);
5953 ADD_INT(d, DB_AUTO_COMMIT);
5954 #else
5955 /* allow berkeleydb 4.1 aware apps to run on older versions */
5956 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5957 #endif
5959 ADD_INT(d, EINVAL);
5960 ADD_INT(d, EACCES);
5961 ADD_INT(d, ENOSPC);
5962 ADD_INT(d, ENOMEM);
5963 ADD_INT(d, EAGAIN);
5964 ADD_INT(d, EBUSY);
5965 ADD_INT(d, EEXIST);
5966 ADD_INT(d, ENOENT);
5967 ADD_INT(d, EPERM);
5969 #if (DBVER >= 40)
5970 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5971 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5972 #endif
5974 /* The exception name must be correct for pickled exception *
5975 * objects to unpickle properly. */
5976 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5977 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5978 #else
5979 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5980 #endif
5982 /* All the rest of the exceptions derive only from DBError */
5983 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5984 PyDict_SetItemString(d, #name, name)
5986 /* The base exception class is DBError */
5987 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5988 MAKE_EX(DBError);
5990 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5991 * from both DBError and KeyError, since the API only supports
5992 * using one base class. */
5993 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5994 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5995 "class DBKeyEmptyError(DBError, KeyError): pass",
5996 Py_file_input, d, d);
5997 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5998 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5999 PyDict_DelItemString(d, "KeyError");
6002 #if !INCOMPLETE_IS_WARNING
6003 MAKE_EX(DBIncompleteError);
6004 #endif
6005 MAKE_EX(DBCursorClosedError);
6006 MAKE_EX(DBKeyEmptyError);
6007 MAKE_EX(DBKeyExistError);
6008 MAKE_EX(DBLockDeadlockError);
6009 MAKE_EX(DBLockNotGrantedError);
6010 MAKE_EX(DBOldVersionError);
6011 MAKE_EX(DBRunRecoveryError);
6012 MAKE_EX(DBVerifyBadError);
6013 MAKE_EX(DBNoServerError);
6014 MAKE_EX(DBNoServerHomeError);
6015 MAKE_EX(DBNoServerIDError);
6016 #if (DBVER >= 33)
6017 MAKE_EX(DBPageNotFoundError);
6018 MAKE_EX(DBSecondaryBadError);
6019 #endif
6021 MAKE_EX(DBInvalidArgError);
6022 MAKE_EX(DBAccessError);
6023 MAKE_EX(DBNoSpaceError);
6024 MAKE_EX(DBNoMemoryError);
6025 MAKE_EX(DBAgainError);
6026 MAKE_EX(DBBusyError);
6027 MAKE_EX(DBFileExistsError);
6028 MAKE_EX(DBNoSuchFileError);
6029 MAKE_EX(DBPermissionsError);
6031 #undef MAKE_EX
6033 /* Check for errors */
6034 if (PyErr_Occurred()) {
6035 PyErr_Print();
6036 Py_FatalError("can't initialize module _bsddb");
6040 /* allow this module to be named _pybsddb so that it can be installed
6041 * and imported on top of python >= 2.3 that includes its own older
6042 * copy of the library named _bsddb without importing the old version. */
6043 DL_EXPORT(void) init_pybsddb(void)
6045 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6046 init_bsddb();