Updates of recent changes to logging.
[python.git] / Modules / _bsddb.c
blobed7eb68607890e6d5f6bf815e8569741a7b3b19a
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);
753 /* The same, when the value is a time_t */
754 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
756 PyObject* v;
757 /* if the value fits in regular int, use that. */
758 #ifdef HAVE_LONG_LONG
759 if (sizeof(time_t) > sizeof(long))
760 v = PyLong_FromLongLong((PY_LONG_LONG) value);
761 else
762 #endif
763 v = PyInt_FromLong((long) value);
764 if (!v || PyDict_SetItemString(dict, name, v))
765 PyErr_Clear();
767 Py_XDECREF(v);
770 #if (DBVER >= 43)
771 /* add an db_seq_t to a dictionary using the given name as a key */
772 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
774 PyObject* v = PyLong_FromLongLong(value);
775 if (!v || PyDict_SetItemString(dict, name, v))
776 PyErr_Clear();
778 Py_XDECREF(v);
780 #endif
784 /* --------------------------------------------------------------------- */
785 /* Allocators and deallocators */
787 static DBObject*
788 newDBObject(DBEnvObject* arg, int flags)
790 DBObject* self;
791 DB_ENV* db_env = NULL;
792 int err;
794 self = PyObject_New(DBObject, &DB_Type);
795 if (self == NULL)
796 return NULL;
798 self->haveStat = 0;
799 self->flags = 0;
800 self->setflags = 0;
801 self->myenvobj = NULL;
802 #if (DBVER >= 33)
803 self->associateCallback = NULL;
804 self->btCompareCallback = NULL;
805 self->primaryDBType = 0;
806 #endif
807 #ifdef HAVE_WEAKREF
808 self->in_weakreflist = NULL;
809 #endif
811 /* keep a reference to our python DBEnv object */
812 if (arg) {
813 Py_INCREF(arg);
814 self->myenvobj = arg;
815 db_env = arg->db_env;
818 if (self->myenvobj)
819 self->moduleFlags = self->myenvobj->moduleFlags;
820 else
821 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
822 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
824 MYDB_BEGIN_ALLOW_THREADS;
825 err = db_create(&self->db, db_env, flags);
826 if (self->db != NULL) {
827 self->db->set_errcall(self->db, _db_errorCallback);
828 #if (DBVER >= 33)
829 self->db->app_private = (void*)self;
830 #endif
832 MYDB_END_ALLOW_THREADS;
833 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
834 * list so that a DBEnv can refuse to close without aborting any open
835 * DBTxns and closing any open DBs first. */
836 if (makeDBError(err)) {
837 if (self->myenvobj) {
838 Py_DECREF(self->myenvobj);
839 self->myenvobj = NULL;
841 PyObject_Del(self);
842 self = NULL;
844 return self;
848 static void
849 DB_dealloc(DBObject* self)
851 if (self->db != NULL) {
852 /* avoid closing a DB when its DBEnv has been closed out from under
853 * it */
854 if (!self->myenvobj ||
855 (self->myenvobj && self->myenvobj->db_env))
857 MYDB_BEGIN_ALLOW_THREADS;
858 self->db->close(self->db, 0);
859 MYDB_END_ALLOW_THREADS;
860 #ifdef HAVE_WARNINGS
861 } else {
862 PyErr_Warn(PyExc_RuntimeWarning,
863 "DB could not be closed in destructor: DBEnv already closed");
864 #endif
866 self->db = NULL;
868 #ifdef HAVE_WEAKREF
869 if (self->in_weakreflist != NULL) {
870 PyObject_ClearWeakRefs((PyObject *) self);
872 #endif
873 if (self->myenvobj) {
874 Py_DECREF(self->myenvobj);
875 self->myenvobj = NULL;
877 #if (DBVER >= 33)
878 if (self->associateCallback != NULL) {
879 Py_DECREF(self->associateCallback);
880 self->associateCallback = NULL;
882 if (self->btCompareCallback != NULL) {
883 Py_DECREF(self->btCompareCallback);
884 self->btCompareCallback = NULL;
886 #endif
887 PyObject_Del(self);
891 static DBCursorObject*
892 newDBCursorObject(DBC* dbc, DBObject* db)
894 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
895 if (self == NULL)
896 return NULL;
898 self->dbc = dbc;
899 self->mydb = db;
900 #ifdef HAVE_WEAKREF
901 self->in_weakreflist = NULL;
902 #endif
903 Py_INCREF(self->mydb);
904 return self;
908 static void
909 DBCursor_dealloc(DBCursorObject* self)
911 int err;
913 #ifdef HAVE_WEAKREF
914 if (self->in_weakreflist != NULL) {
915 PyObject_ClearWeakRefs((PyObject *) self);
917 #endif
919 if (self->dbc != NULL) {
920 MYDB_BEGIN_ALLOW_THREADS;
921 /* If the underlying database has been closed, we don't
922 need to do anything. If the environment has been closed
923 we need to leak, as BerkeleyDB will crash trying to access
924 the environment. There was an exception when the
925 user closed the environment even though there still was
926 a database open. */
927 if (self->mydb->db && self->mydb->myenvobj &&
928 !self->mydb->myenvobj->closed)
929 err = self->dbc->c_close(self->dbc);
930 self->dbc = NULL;
931 MYDB_END_ALLOW_THREADS;
933 Py_XDECREF( self->mydb );
934 PyObject_Del(self);
938 static DBEnvObject*
939 newDBEnvObject(int flags)
941 int err;
942 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
943 if (self == NULL)
944 return NULL;
946 self->closed = 1;
947 self->flags = flags;
948 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
949 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
950 #ifdef HAVE_WEAKREF
951 self->in_weakreflist = NULL;
952 #endif
954 MYDB_BEGIN_ALLOW_THREADS;
955 err = db_env_create(&self->db_env, flags);
956 MYDB_END_ALLOW_THREADS;
957 if (makeDBError(err)) {
958 PyObject_Del(self);
959 self = NULL;
961 else {
962 self->db_env->set_errcall(self->db_env, _db_errorCallback);
964 return self;
968 static void
969 DBEnv_dealloc(DBEnvObject* self)
971 #ifdef HAVE_WEAKREF
972 if (self->in_weakreflist != NULL) {
973 PyObject_ClearWeakRefs((PyObject *) self);
975 #endif
977 if (self->db_env && !self->closed) {
978 MYDB_BEGIN_ALLOW_THREADS;
979 self->db_env->close(self->db_env, 0);
980 MYDB_END_ALLOW_THREADS;
982 PyObject_Del(self);
986 static DBTxnObject*
987 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
989 int err;
990 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
991 if (self == NULL)
992 return NULL;
993 Py_INCREF(myenv);
994 self->env = (PyObject*)myenv;
995 #ifdef HAVE_WEAKREF
996 self->in_weakreflist = NULL;
997 #endif
999 MYDB_BEGIN_ALLOW_THREADS;
1000 #if (DBVER >= 40)
1001 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
1002 #else
1003 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
1004 #endif
1005 MYDB_END_ALLOW_THREADS;
1006 if (makeDBError(err)) {
1007 Py_DECREF(self->env);
1008 PyObject_Del(self);
1009 self = NULL;
1011 return self;
1015 static void
1016 DBTxn_dealloc(DBTxnObject* self)
1018 #ifdef HAVE_WEAKREF
1019 if (self->in_weakreflist != NULL) {
1020 PyObject_ClearWeakRefs((PyObject *) self);
1022 #endif
1024 #ifdef HAVE_WARNINGS
1025 if (self->txn) {
1026 /* it hasn't been finalized, abort it! */
1027 MYDB_BEGIN_ALLOW_THREADS;
1028 #if (DBVER >= 40)
1029 self->txn->abort(self->txn);
1030 #else
1031 txn_abort(self->txn);
1032 #endif
1033 MYDB_END_ALLOW_THREADS;
1034 PyErr_Warn(PyExc_RuntimeWarning,
1035 "DBTxn aborted in destructor. No prior commit() or abort().");
1037 #endif
1039 Py_DECREF(self->env);
1040 PyObject_Del(self);
1044 static DBLockObject*
1045 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1046 db_lockmode_t lock_mode, int flags)
1048 int err;
1049 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1050 if (self == NULL)
1051 return NULL;
1052 #ifdef HAVE_WEAKREF
1053 self->in_weakreflist = NULL;
1054 #endif
1056 MYDB_BEGIN_ALLOW_THREADS;
1057 #if (DBVER >= 40)
1058 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1059 &self->lock);
1060 #else
1061 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1062 #endif
1063 MYDB_END_ALLOW_THREADS;
1064 if (makeDBError(err)) {
1065 PyObject_Del(self);
1066 self = NULL;
1069 return self;
1073 static void
1074 DBLock_dealloc(DBLockObject* self)
1076 #ifdef HAVE_WEAKREF
1077 if (self->in_weakreflist != NULL) {
1078 PyObject_ClearWeakRefs((PyObject *) self);
1080 #endif
1081 /* TODO: is this lock held? should we release it? */
1083 PyObject_Del(self);
1087 #if (DBVER >= 43)
1088 static DBSequenceObject*
1089 newDBSequenceObject(DBObject* mydb, int flags)
1091 int err;
1092 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1093 if (self == NULL)
1094 return NULL;
1095 Py_INCREF(mydb);
1096 self->mydb = mydb;
1097 #ifdef HAVE_WEAKREF
1098 self->in_weakreflist = NULL;
1099 #endif
1102 MYDB_BEGIN_ALLOW_THREADS;
1103 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1104 MYDB_END_ALLOW_THREADS;
1105 if (makeDBError(err)) {
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1108 self = NULL;
1111 return self;
1115 static void
1116 DBSequence_dealloc(DBSequenceObject* self)
1118 #ifdef HAVE_WEAKREF
1119 if (self->in_weakreflist != NULL) {
1120 PyObject_ClearWeakRefs((PyObject *) self);
1122 #endif
1124 Py_DECREF(self->mydb);
1125 PyObject_Del(self);
1127 #endif
1129 /* --------------------------------------------------------------------- */
1130 /* DB methods */
1132 static PyObject*
1133 DB_append(DBObject* self, PyObject* args)
1135 PyObject* txnobj = NULL;
1136 PyObject* dataobj;
1137 db_recno_t recno;
1138 DBT key, data;
1139 DB_TXN *txn = NULL;
1141 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1142 return NULL;
1144 CHECK_DB_NOT_CLOSED(self);
1146 /* make a dummy key out of a recno */
1147 recno = 0;
1148 CLEAR_DBT(key);
1149 key.data = &recno;
1150 key.size = sizeof(recno);
1151 key.ulen = key.size;
1152 key.flags = DB_DBT_USERMEM;
1154 if (!make_dbt(dataobj, &data)) return NULL;
1155 if (!checkTxnObj(txnobj, &txn)) return NULL;
1157 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1158 return NULL;
1160 return PyInt_FromLong(recno);
1164 #if (DBVER >= 33)
1166 static int
1167 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1168 DBT* secKey)
1170 int retval = DB_DONOTINDEX;
1171 DBObject* secondaryDB = (DBObject*)db->app_private;
1172 PyObject* callback = secondaryDB->associateCallback;
1173 int type = secondaryDB->primaryDBType;
1174 PyObject* args;
1175 PyObject* result = NULL;
1178 if (callback != NULL) {
1179 MYDB_BEGIN_BLOCK_THREADS;
1181 if (type == DB_RECNO || type == DB_QUEUE)
1182 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1183 priData->data, priData->size);
1184 else
1185 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1186 priData->data, priData->size);
1187 if (args != NULL) {
1188 result = PyEval_CallObject(callback, args);
1190 if (args == NULL || result == NULL) {
1191 PyErr_Print();
1193 else if (result == Py_None) {
1194 retval = DB_DONOTINDEX;
1196 else if (PyInt_Check(result)) {
1197 retval = PyInt_AsLong(result);
1199 else if (PyString_Check(result)) {
1200 char* data;
1201 Py_ssize_t size;
1203 CLEAR_DBT(*secKey);
1204 #if PYTHON_API_VERSION <= 1007
1205 /* 1.5 compatibility */
1206 size = PyString_Size(result);
1207 data = PyString_AsString(result);
1208 #else
1209 PyString_AsStringAndSize(result, &data, &size);
1210 #endif
1211 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1212 secKey->data = malloc(size); /* TODO, check this */
1213 if (secKey->data) {
1214 memcpy(secKey->data, data, size);
1215 secKey->size = size;
1216 retval = 0;
1218 else {
1219 PyErr_SetString(PyExc_MemoryError,
1220 "malloc failed in _db_associateCallback");
1221 PyErr_Print();
1224 else {
1225 PyErr_SetString(
1226 PyExc_TypeError,
1227 "DB associate callback should return DB_DONOTINDEX or string.");
1228 PyErr_Print();
1231 Py_XDECREF(args);
1232 Py_XDECREF(result);
1234 MYDB_END_BLOCK_THREADS;
1236 return retval;
1240 static PyObject*
1241 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1243 int err, flags=0;
1244 DBObject* secondaryDB;
1245 PyObject* callback;
1246 #if (DBVER >= 41)
1247 PyObject *txnobj = NULL;
1248 DB_TXN *txn = NULL;
1249 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1250 NULL};
1251 #else
1252 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1253 #endif
1255 #if (DBVER >= 41)
1256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1257 &secondaryDB, &callback, &flags,
1258 &txnobj)) {
1259 #else
1260 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1261 &secondaryDB, &callback, &flags)) {
1262 #endif
1263 return NULL;
1266 #if (DBVER >= 41)
1267 if (!checkTxnObj(txnobj, &txn)) return NULL;
1268 #endif
1270 CHECK_DB_NOT_CLOSED(self);
1271 if (!DBObject_Check(secondaryDB)) {
1272 makeTypeError("DB", (PyObject*)secondaryDB);
1273 return NULL;
1275 CHECK_DB_NOT_CLOSED(secondaryDB);
1276 if (callback == Py_None) {
1277 callback = NULL;
1279 else if (!PyCallable_Check(callback)) {
1280 makeTypeError("Callable", callback);
1281 return NULL;
1284 /* Save a reference to the callback in the secondary DB. */
1285 Py_XDECREF(secondaryDB->associateCallback);
1286 Py_XINCREF(callback);
1287 secondaryDB->associateCallback = callback;
1288 secondaryDB->primaryDBType = _DB_get_type(self);
1290 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1291 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1292 * The global interepreter lock is not initialized until the first
1293 * thread is created using thread.start_new_thread() or fork() is
1294 * called. that would cause the ALLOW_THREADS here to segfault due
1295 * to a null pointer reference if no threads or child processes
1296 * have been created. This works around that and is a no-op if
1297 * threads have already been initialized.
1298 * (see pybsddb-users mailing list post on 2002-08-07)
1300 #ifdef WITH_THREAD
1301 PyEval_InitThreads();
1302 #endif
1303 MYDB_BEGIN_ALLOW_THREADS;
1304 #if (DBVER >= 41)
1305 err = self->db->associate(self->db,
1306 txn,
1307 secondaryDB->db,
1308 _db_associateCallback,
1309 flags);
1310 #else
1311 err = self->db->associate(self->db,
1312 secondaryDB->db,
1313 _db_associateCallback,
1314 flags);
1315 #endif
1316 MYDB_END_ALLOW_THREADS;
1318 if (err) {
1319 Py_XDECREF(secondaryDB->associateCallback);
1320 secondaryDB->associateCallback = NULL;
1321 secondaryDB->primaryDBType = 0;
1324 RETURN_IF_ERR();
1325 RETURN_NONE();
1329 #endif
1332 static PyObject*
1333 DB_close(DBObject* self, PyObject* args)
1335 int err, flags=0;
1336 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1337 return NULL;
1338 if (self->db != NULL) {
1339 if (self->myenvobj)
1340 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1341 err = self->db->close(self->db, flags);
1342 self->db = NULL;
1343 RETURN_IF_ERR();
1345 RETURN_NONE();
1349 #if (DBVER >= 32)
1350 static PyObject*
1351 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1353 int err, flags=0, type;
1354 PyObject* txnobj = NULL;
1355 PyObject* retval = NULL;
1356 DBT key, data;
1357 DB_TXN *txn = NULL;
1358 static char* kwnames[] = { "txn", "flags", NULL };
1360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1361 &txnobj, &flags))
1362 return NULL;
1364 CHECK_DB_NOT_CLOSED(self);
1365 type = _DB_get_type(self);
1366 if (type == -1)
1367 return NULL;
1368 if (type != DB_QUEUE) {
1369 PyErr_SetString(PyExc_TypeError,
1370 "Consume methods only allowed for Queue DB's");
1371 return NULL;
1373 if (!checkTxnObj(txnobj, &txn))
1374 return NULL;
1376 CLEAR_DBT(key);
1377 CLEAR_DBT(data);
1378 if (CHECK_DBFLAG(self, DB_THREAD)) {
1379 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1380 data.flags = DB_DBT_MALLOC;
1381 key.flags = DB_DBT_MALLOC;
1384 MYDB_BEGIN_ALLOW_THREADS;
1385 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1386 MYDB_END_ALLOW_THREADS;
1388 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1389 && self->moduleFlags.getReturnsNone) {
1390 err = 0;
1391 Py_INCREF(Py_None);
1392 retval = Py_None;
1394 else if (!err) {
1395 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1396 data.size);
1397 FREE_DBT(key);
1398 FREE_DBT(data);
1401 RETURN_IF_ERR();
1402 return retval;
1405 static PyObject*
1406 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1408 return _DB_consume(self, args, kwargs, DB_CONSUME);
1411 static PyObject*
1412 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1413 int consume_flag)
1415 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1417 #endif
1421 static PyObject*
1422 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1424 int err, flags=0;
1425 DBC* dbc;
1426 PyObject* txnobj = NULL;
1427 DB_TXN *txn = NULL;
1428 static char* kwnames[] = { "txn", "flags", NULL };
1430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1431 &txnobj, &flags))
1432 return NULL;
1433 CHECK_DB_NOT_CLOSED(self);
1434 if (!checkTxnObj(txnobj, &txn))
1435 return NULL;
1437 MYDB_BEGIN_ALLOW_THREADS;
1438 err = self->db->cursor(self->db, txn, &dbc, flags);
1439 MYDB_END_ALLOW_THREADS;
1440 RETURN_IF_ERR();
1441 return (PyObject*) newDBCursorObject(dbc, self);
1445 static PyObject*
1446 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1448 PyObject* txnobj = NULL;
1449 int flags = 0;
1450 PyObject* keyobj;
1451 DBT key;
1452 DB_TXN *txn = NULL;
1453 static char* kwnames[] = { "key", "txn", "flags", NULL };
1455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1456 &keyobj, &txnobj, &flags))
1457 return NULL;
1458 CHECK_DB_NOT_CLOSED(self);
1459 if (!make_key_dbt(self, keyobj, &key, NULL))
1460 return NULL;
1461 if (!checkTxnObj(txnobj, &txn)) {
1462 FREE_DBT(key);
1463 return NULL;
1466 if (-1 == _DB_delete(self, txn, &key, 0)) {
1467 FREE_DBT(key);
1468 return NULL;
1471 FREE_DBT(key);
1472 RETURN_NONE();
1476 static PyObject*
1477 DB_fd(DBObject* self, PyObject* args)
1479 int err, the_fd;
1481 if (!PyArg_ParseTuple(args,":fd"))
1482 return NULL;
1483 CHECK_DB_NOT_CLOSED(self);
1485 MYDB_BEGIN_ALLOW_THREADS;
1486 err = self->db->fd(self->db, &the_fd);
1487 MYDB_END_ALLOW_THREADS;
1488 RETURN_IF_ERR();
1489 return PyInt_FromLong(the_fd);
1493 static PyObject*
1494 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1496 int err, flags=0;
1497 PyObject* txnobj = NULL;
1498 PyObject* keyobj;
1499 PyObject* dfltobj = NULL;
1500 PyObject* retval = NULL;
1501 int dlen = -1;
1502 int doff = -1;
1503 DBT key, data;
1504 DB_TXN *txn = NULL;
1505 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1506 "doff", NULL};
1508 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1509 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1510 &doff))
1511 return NULL;
1513 CHECK_DB_NOT_CLOSED(self);
1514 if (!make_key_dbt(self, keyobj, &key, &flags))
1515 return NULL;
1516 if (!checkTxnObj(txnobj, &txn)) {
1517 FREE_DBT(key);
1518 return NULL;
1521 CLEAR_DBT(data);
1522 if (CHECK_DBFLAG(self, DB_THREAD)) {
1523 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1524 data.flags = DB_DBT_MALLOC;
1526 if (!add_partial_dbt(&data, dlen, doff)) {
1527 FREE_DBT(key);
1528 return NULL;
1531 MYDB_BEGIN_ALLOW_THREADS;
1532 err = self->db->get(self->db, txn, &key, &data, flags);
1533 MYDB_END_ALLOW_THREADS;
1535 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1536 err = 0;
1537 Py_INCREF(dfltobj);
1538 retval = dfltobj;
1540 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1541 && self->moduleFlags.getReturnsNone) {
1542 err = 0;
1543 Py_INCREF(Py_None);
1544 retval = Py_None;
1546 else if (!err) {
1547 if (flags & DB_SET_RECNO) /* return both key and data */
1548 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1549 data.size);
1550 else /* return just the data */
1551 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1552 FREE_DBT(data);
1554 FREE_DBT(key);
1556 RETURN_IF_ERR();
1557 return retval;
1560 #if (DBVER >= 33)
1561 static PyObject*
1562 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1564 int err, flags=0;
1565 PyObject* txnobj = NULL;
1566 PyObject* keyobj;
1567 PyObject* dfltobj = NULL;
1568 PyObject* retval = NULL;
1569 int dlen = -1;
1570 int doff = -1;
1571 DBT key, pkey, data;
1572 DB_TXN *txn = NULL;
1573 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1574 "doff", NULL};
1576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1577 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1578 &doff))
1579 return NULL;
1581 CHECK_DB_NOT_CLOSED(self);
1582 if (!make_key_dbt(self, keyobj, &key, &flags))
1583 return NULL;
1584 if (!checkTxnObj(txnobj, &txn)) {
1585 FREE_DBT(key);
1586 return NULL;
1589 CLEAR_DBT(data);
1590 if (CHECK_DBFLAG(self, DB_THREAD)) {
1591 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1592 data.flags = DB_DBT_MALLOC;
1594 if (!add_partial_dbt(&data, dlen, doff)) {
1595 FREE_DBT(key);
1596 return NULL;
1599 CLEAR_DBT(pkey);
1600 pkey.flags = DB_DBT_MALLOC;
1602 MYDB_BEGIN_ALLOW_THREADS;
1603 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1604 MYDB_END_ALLOW_THREADS;
1606 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1607 err = 0;
1608 Py_INCREF(dfltobj);
1609 retval = dfltobj;
1611 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1612 && self->moduleFlags.getReturnsNone) {
1613 err = 0;
1614 Py_INCREF(Py_None);
1615 retval = Py_None;
1617 else if (!err) {
1618 PyObject *pkeyObj;
1619 PyObject *dataObj;
1620 dataObj = PyString_FromStringAndSize(data.data, data.size);
1622 if (self->primaryDBType == DB_RECNO ||
1623 self->primaryDBType == DB_QUEUE)
1624 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1625 else
1626 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1628 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1630 PyObject *keyObj;
1631 int type = _DB_get_type(self);
1632 if (type == DB_RECNO || type == DB_QUEUE)
1633 keyObj = PyInt_FromLong(*(int *)key.data);
1634 else
1635 keyObj = PyString_FromStringAndSize(key.data, key.size);
1636 #if (PY_VERSION_HEX >= 0x02040000)
1637 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1638 #else
1639 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1640 #endif
1641 Py_DECREF(keyObj);
1643 else /* return just the pkey and data */
1645 #if (PY_VERSION_HEX >= 0x02040000)
1646 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1647 #else
1648 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1649 #endif
1651 Py_DECREF(dataObj);
1652 Py_DECREF(pkeyObj);
1653 FREE_DBT(pkey);
1654 FREE_DBT(data);
1656 FREE_DBT(key);
1658 RETURN_IF_ERR();
1659 return retval;
1661 #endif
1664 /* Return size of entry */
1665 static PyObject*
1666 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1668 int err, flags=0;
1669 PyObject* txnobj = NULL;
1670 PyObject* keyobj;
1671 PyObject* retval = NULL;
1672 DBT key, data;
1673 DB_TXN *txn = NULL;
1674 static char* kwnames[] = { "key", "txn", NULL };
1676 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1677 &keyobj, &txnobj))
1678 return NULL;
1679 CHECK_DB_NOT_CLOSED(self);
1680 if (!make_key_dbt(self, keyobj, &key, &flags))
1681 return NULL;
1682 if (!checkTxnObj(txnobj, &txn)) {
1683 FREE_DBT(key);
1684 return NULL;
1686 CLEAR_DBT(data);
1688 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1689 thus getting the record size. */
1690 data.flags = DB_DBT_USERMEM;
1691 data.ulen = 0;
1692 MYDB_BEGIN_ALLOW_THREADS;
1693 err = self->db->get(self->db, txn, &key, &data, flags);
1694 MYDB_END_ALLOW_THREADS;
1695 if (err == DB_BUFFER_SMALL) {
1696 retval = PyInt_FromLong((long)data.size);
1697 err = 0;
1700 FREE_DBT(key);
1701 FREE_DBT(data);
1702 RETURN_IF_ERR();
1703 return retval;
1707 static PyObject*
1708 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1710 int err, flags=0;
1711 PyObject* txnobj = NULL;
1712 PyObject* keyobj;
1713 PyObject* dataobj;
1714 PyObject* retval = NULL;
1715 DBT key, data;
1716 DB_TXN *txn = NULL;
1717 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1720 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1721 &keyobj, &dataobj, &txnobj, &flags))
1722 return NULL;
1724 CHECK_DB_NOT_CLOSED(self);
1725 if (!make_key_dbt(self, keyobj, &key, NULL))
1726 return NULL;
1727 if ( !make_dbt(dataobj, &data) ||
1728 !checkTxnObj(txnobj, &txn) )
1730 FREE_DBT(key);
1731 return NULL;
1734 flags |= DB_GET_BOTH;
1736 if (CHECK_DBFLAG(self, DB_THREAD)) {
1737 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1738 data.flags = DB_DBT_MALLOC;
1739 /* TODO: Is this flag needed? We're passing a data object that should
1740 match what's in the DB, so there should be no need to malloc.
1741 We run the risk of freeing something twice! Check this. */
1744 MYDB_BEGIN_ALLOW_THREADS;
1745 err = self->db->get(self->db, txn, &key, &data, flags);
1746 MYDB_END_ALLOW_THREADS;
1748 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1749 && self->moduleFlags.getReturnsNone) {
1750 err = 0;
1751 Py_INCREF(Py_None);
1752 retval = Py_None;
1754 else if (!err) {
1755 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1756 FREE_DBT(data); /* Only if retrieval was successful */
1759 FREE_DBT(key);
1760 RETURN_IF_ERR();
1761 return retval;
1765 static PyObject*
1766 DB_get_byteswapped(DBObject* self, PyObject* args)
1768 #if (DBVER >= 33)
1769 int err = 0;
1770 #endif
1771 int retval = -1;
1773 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1774 return NULL;
1775 CHECK_DB_NOT_CLOSED(self);
1777 #if (DBVER >= 33)
1778 MYDB_BEGIN_ALLOW_THREADS;
1779 err = self->db->get_byteswapped(self->db, &retval);
1780 MYDB_END_ALLOW_THREADS;
1781 RETURN_IF_ERR();
1782 #else
1783 MYDB_BEGIN_ALLOW_THREADS;
1784 retval = self->db->get_byteswapped(self->db);
1785 MYDB_END_ALLOW_THREADS;
1786 #endif
1787 return PyInt_FromLong(retval);
1791 static PyObject*
1792 DB_get_type(DBObject* self, PyObject* args)
1794 int type;
1796 if (!PyArg_ParseTuple(args,":get_type"))
1797 return NULL;
1798 CHECK_DB_NOT_CLOSED(self);
1800 type = _DB_get_type(self);
1801 if (type == -1)
1802 return NULL;
1803 return PyInt_FromLong(type);
1807 static PyObject*
1808 DB_join(DBObject* self, PyObject* args)
1810 int err, flags=0;
1811 int length, x;
1812 PyObject* cursorsObj;
1813 DBC** cursors;
1814 DBC* dbc;
1816 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1817 return NULL;
1819 CHECK_DB_NOT_CLOSED(self);
1821 if (!PySequence_Check(cursorsObj)) {
1822 PyErr_SetString(PyExc_TypeError,
1823 "Sequence of DBCursor objects expected");
1824 return NULL;
1827 length = PyObject_Length(cursorsObj);
1828 cursors = malloc((length+1) * sizeof(DBC*));
1829 if (!cursors) {
1830 PyErr_NoMemory();
1831 return NULL;
1834 cursors[length] = NULL;
1835 for (x=0; x<length; x++) {
1836 PyObject* item = PySequence_GetItem(cursorsObj, x);
1837 if (item == NULL) {
1838 free(cursors);
1839 return NULL;
1841 if (!DBCursorObject_Check(item)) {
1842 PyErr_SetString(PyExc_TypeError,
1843 "Sequence of DBCursor objects expected");
1844 free(cursors);
1845 return NULL;
1847 cursors[x] = ((DBCursorObject*)item)->dbc;
1848 Py_DECREF(item);
1851 MYDB_BEGIN_ALLOW_THREADS;
1852 err = self->db->join(self->db, cursors, &dbc, flags);
1853 MYDB_END_ALLOW_THREADS;
1854 free(cursors);
1855 RETURN_IF_ERR();
1857 /* FIXME: this is a buggy interface. The returned cursor
1858 contains internal references to the passed in cursors
1859 but does not hold python references to them or prevent
1860 them from being closed prematurely. This can cause
1861 python to crash when things are done in the wrong order. */
1862 return (PyObject*) newDBCursorObject(dbc, self);
1866 static PyObject*
1867 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1869 int err, flags=0;
1870 PyObject* txnobj = NULL;
1871 PyObject* keyobj;
1872 DBT key;
1873 DB_TXN *txn = NULL;
1874 DB_KEY_RANGE range;
1875 static char* kwnames[] = { "key", "txn", "flags", NULL };
1877 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1878 &keyobj, &txnobj, &flags))
1879 return NULL;
1880 CHECK_DB_NOT_CLOSED(self);
1881 if (!make_dbt(keyobj, &key))
1882 /* BTree only, don't need to allow for an int key */
1883 return NULL;
1884 if (!checkTxnObj(txnobj, &txn))
1885 return NULL;
1887 MYDB_BEGIN_ALLOW_THREADS;
1888 err = self->db->key_range(self->db, txn, &key, &range, flags);
1889 MYDB_END_ALLOW_THREADS;
1891 RETURN_IF_ERR();
1892 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1896 static PyObject*
1897 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1899 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1900 char* filename = NULL;
1901 char* dbname = NULL;
1902 #if (DBVER >= 41)
1903 PyObject *txnobj = NULL;
1904 DB_TXN *txn = NULL;
1905 /* with dbname */
1906 static char* kwnames[] = {
1907 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1908 /* without dbname */
1909 static char* kwnames_basic[] = {
1910 "filename", "dbtype", "flags", "mode", "txn", NULL};
1911 #else
1912 /* with dbname */
1913 static char* kwnames[] = {
1914 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1915 /* without dbname */
1916 static char* kwnames_basic[] = {
1917 "filename", "dbtype", "flags", "mode", NULL};
1918 #endif
1920 #if (DBVER >= 41)
1921 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1922 &filename, &dbname, &type, &flags, &mode,
1923 &txnobj))
1924 #else
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1926 &filename, &dbname, &type, &flags,
1927 &mode))
1928 #endif
1930 PyErr_Clear();
1931 type = DB_UNKNOWN; flags = 0; mode = 0660;
1932 filename = NULL; dbname = NULL;
1933 #if (DBVER >= 41)
1934 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1935 kwnames_basic,
1936 &filename, &type, &flags, &mode,
1937 &txnobj))
1938 return NULL;
1939 #else
1940 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1941 kwnames_basic,
1942 &filename, &type, &flags, &mode))
1943 return NULL;
1944 #endif
1947 #if (DBVER >= 41)
1948 if (!checkTxnObj(txnobj, &txn)) return NULL;
1949 #endif
1951 if (NULL == self->db) {
1952 PyObject *t = Py_BuildValue("(is)", 0,
1953 "Cannot call open() twice for DB object");
1954 PyErr_SetObject(DBError, t);
1955 Py_DECREF(t);
1956 return NULL;
1959 #if 0 && (DBVER >= 41)
1960 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1961 && (self->myenvobj->flags & DB_INIT_TXN))
1963 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1964 * explicitly passed) but we are in a transaction ready environment:
1965 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1966 * to work on BerkeleyDB 4.1 without needing to modify their
1967 * DBEnv or DB open calls.
1968 * TODO make this behaviour of the library configurable.
1970 flags |= DB_AUTO_COMMIT;
1972 #endif
1974 MYDB_BEGIN_ALLOW_THREADS;
1975 #if (DBVER >= 41)
1976 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1977 #else
1978 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1979 #endif
1980 MYDB_END_ALLOW_THREADS;
1981 if (makeDBError(err)) {
1982 self->db->close(self->db, 0);
1983 self->db = NULL;
1984 return NULL;
1987 self->flags = flags;
1988 RETURN_NONE();
1992 static PyObject*
1993 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1995 int flags=0;
1996 PyObject* txnobj = NULL;
1997 int dlen = -1;
1998 int doff = -1;
1999 PyObject* keyobj, *dataobj, *retval;
2000 DBT key, data;
2001 DB_TXN *txn = NULL;
2002 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
2003 "doff", NULL };
2005 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2006 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2007 return NULL;
2009 CHECK_DB_NOT_CLOSED(self);
2010 if (!make_key_dbt(self, keyobj, &key, NULL))
2011 return NULL;
2012 if ( !make_dbt(dataobj, &data) ||
2013 !add_partial_dbt(&data, dlen, doff) ||
2014 !checkTxnObj(txnobj, &txn) )
2016 FREE_DBT(key);
2017 return NULL;
2020 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2021 FREE_DBT(key);
2022 return NULL;
2025 if (flags & DB_APPEND)
2026 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2027 else {
2028 retval = Py_None;
2029 Py_INCREF(retval);
2031 FREE_DBT(key);
2032 return retval;
2037 static PyObject*
2038 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2040 char* filename;
2041 char* database = NULL;
2042 int err, flags=0;
2043 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2045 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2046 &filename, &database, &flags))
2047 return NULL;
2048 CHECK_DB_NOT_CLOSED(self);
2050 err = self->db->remove(self->db, filename, database, flags);
2051 self->db = NULL;
2052 RETURN_IF_ERR();
2053 RETURN_NONE();
2058 static PyObject*
2059 DB_rename(DBObject* self, PyObject* args)
2061 char* filename;
2062 char* database;
2063 char* newname;
2064 int err, flags=0;
2066 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2067 &flags))
2068 return NULL;
2069 CHECK_DB_NOT_CLOSED(self);
2071 MYDB_BEGIN_ALLOW_THREADS;
2072 err = self->db->rename(self->db, filename, database, newname, flags);
2073 MYDB_END_ALLOW_THREADS;
2074 RETURN_IF_ERR();
2075 RETURN_NONE();
2079 static PyObject*
2080 DB_set_bt_minkey(DBObject* self, PyObject* args)
2082 int err, minkey;
2084 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2085 return NULL;
2086 CHECK_DB_NOT_CLOSED(self);
2088 MYDB_BEGIN_ALLOW_THREADS;
2089 err = self->db->set_bt_minkey(self->db, minkey);
2090 MYDB_END_ALLOW_THREADS;
2091 RETURN_IF_ERR();
2092 RETURN_NONE();
2095 #if (DBVER >= 33)
2096 static int
2097 _default_cmp(const DBT *leftKey,
2098 const DBT *rightKey)
2100 int res;
2101 int lsize = leftKey->size, rsize = rightKey->size;
2103 res = memcmp(leftKey->data, rightKey->data,
2104 lsize < rsize ? lsize : rsize);
2106 if (res == 0) {
2107 if (lsize < rsize) {
2108 res = -1;
2110 else if (lsize > rsize) {
2111 res = 1;
2114 return res;
2117 static int
2118 _db_compareCallback(DB* db,
2119 const DBT *leftKey,
2120 const DBT *rightKey)
2122 int res = 0;
2123 PyObject *args;
2124 PyObject *result = NULL;
2125 DBObject *self = (DBObject *)db->app_private;
2127 if (self == NULL || self->btCompareCallback == NULL) {
2128 MYDB_BEGIN_BLOCK_THREADS;
2129 PyErr_SetString(PyExc_TypeError,
2130 (self == 0
2131 ? "DB_bt_compare db is NULL."
2132 : "DB_bt_compare callback is NULL."));
2133 /* we're in a callback within the DB code, we can't raise */
2134 PyErr_Print();
2135 res = _default_cmp(leftKey, rightKey);
2136 MYDB_END_BLOCK_THREADS;
2137 } else {
2138 MYDB_BEGIN_BLOCK_THREADS;
2140 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2141 rightKey->data, rightKey->size);
2142 if (args != NULL) {
2143 /* XXX(twouters) I highly doubt this INCREF is correct */
2144 Py_INCREF(self);
2145 result = PyEval_CallObject(self->btCompareCallback, args);
2147 if (args == NULL || result == NULL) {
2148 /* we're in a callback within the DB code, we can't raise */
2149 PyErr_Print();
2150 res = _default_cmp(leftKey, rightKey);
2151 } else if (PyInt_Check(result)) {
2152 res = PyInt_AsLong(result);
2153 } else {
2154 PyErr_SetString(PyExc_TypeError,
2155 "DB_bt_compare callback MUST return an int.");
2156 /* we're in a callback within the DB code, we can't raise */
2157 PyErr_Print();
2158 res = _default_cmp(leftKey, rightKey);
2161 Py_XDECREF(args);
2162 Py_XDECREF(result);
2164 MYDB_END_BLOCK_THREADS;
2166 return res;
2169 static PyObject*
2170 DB_set_bt_compare(DBObject* self, PyObject* args)
2172 int err;
2173 PyObject *comparator;
2174 PyObject *tuple, *result;
2176 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2177 return NULL;
2179 CHECK_DB_NOT_CLOSED(self);
2181 if (!PyCallable_Check(comparator)) {
2182 makeTypeError("Callable", comparator);
2183 return NULL;
2187 * Perform a test call of the comparator function with two empty
2188 * string objects here. verify that it returns an int (0).
2189 * err if not.
2191 tuple = Py_BuildValue("(ss)", "", "");
2192 result = PyEval_CallObject(comparator, tuple);
2193 Py_DECREF(tuple);
2194 if (result == NULL)
2195 return NULL;
2196 if (!PyInt_Check(result)) {
2197 PyErr_SetString(PyExc_TypeError,
2198 "callback MUST return an int");
2199 return NULL;
2200 } else if (PyInt_AsLong(result) != 0) {
2201 PyErr_SetString(PyExc_TypeError,
2202 "callback failed to return 0 on two empty strings");
2203 return NULL;
2205 Py_DECREF(result);
2207 /* We don't accept multiple set_bt_compare operations, in order to
2208 * simplify the code. This would have no real use, as one cannot
2209 * change the function once the db is opened anyway */
2210 if (self->btCompareCallback != NULL) {
2211 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2212 return NULL;
2215 Py_INCREF(comparator);
2216 self->btCompareCallback = comparator;
2218 /* This is to workaround a problem with un-initialized threads (see
2219 comment in DB_associate) */
2220 #ifdef WITH_THREAD
2221 PyEval_InitThreads();
2222 #endif
2224 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2226 if (err) {
2227 /* restore the old state in case of error */
2228 Py_DECREF(comparator);
2229 self->btCompareCallback = NULL;
2232 RETURN_IF_ERR();
2233 RETURN_NONE();
2235 #endif /* DBVER >= 33 */
2238 static PyObject*
2239 DB_set_cachesize(DBObject* self, PyObject* args)
2241 int err;
2242 int gbytes = 0, bytes = 0, ncache = 0;
2244 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2245 &gbytes,&bytes,&ncache))
2246 return NULL;
2247 CHECK_DB_NOT_CLOSED(self);
2249 MYDB_BEGIN_ALLOW_THREADS;
2250 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2251 MYDB_END_ALLOW_THREADS;
2252 RETURN_IF_ERR();
2253 RETURN_NONE();
2257 static PyObject*
2258 DB_set_flags(DBObject* self, PyObject* args)
2260 int err, flags;
2262 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2263 return NULL;
2264 CHECK_DB_NOT_CLOSED(self);
2266 MYDB_BEGIN_ALLOW_THREADS;
2267 err = self->db->set_flags(self->db, flags);
2268 MYDB_END_ALLOW_THREADS;
2269 RETURN_IF_ERR();
2271 self->setflags |= flags;
2272 RETURN_NONE();
2276 static PyObject*
2277 DB_set_h_ffactor(DBObject* self, PyObject* args)
2279 int err, ffactor;
2281 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2282 return NULL;
2283 CHECK_DB_NOT_CLOSED(self);
2285 MYDB_BEGIN_ALLOW_THREADS;
2286 err = self->db->set_h_ffactor(self->db, ffactor);
2287 MYDB_END_ALLOW_THREADS;
2288 RETURN_IF_ERR();
2289 RETURN_NONE();
2293 static PyObject*
2294 DB_set_h_nelem(DBObject* self, PyObject* args)
2296 int err, nelem;
2298 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2299 return NULL;
2300 CHECK_DB_NOT_CLOSED(self);
2302 MYDB_BEGIN_ALLOW_THREADS;
2303 err = self->db->set_h_nelem(self->db, nelem);
2304 MYDB_END_ALLOW_THREADS;
2305 RETURN_IF_ERR();
2306 RETURN_NONE();
2310 static PyObject*
2311 DB_set_lorder(DBObject* self, PyObject* args)
2313 int err, lorder;
2315 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2316 return NULL;
2317 CHECK_DB_NOT_CLOSED(self);
2319 MYDB_BEGIN_ALLOW_THREADS;
2320 err = self->db->set_lorder(self->db, lorder);
2321 MYDB_END_ALLOW_THREADS;
2322 RETURN_IF_ERR();
2323 RETURN_NONE();
2327 static PyObject*
2328 DB_set_pagesize(DBObject* self, PyObject* args)
2330 int err, pagesize;
2332 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2333 return NULL;
2334 CHECK_DB_NOT_CLOSED(self);
2336 MYDB_BEGIN_ALLOW_THREADS;
2337 err = self->db->set_pagesize(self->db, pagesize);
2338 MYDB_END_ALLOW_THREADS;
2339 RETURN_IF_ERR();
2340 RETURN_NONE();
2344 static PyObject*
2345 DB_set_re_delim(DBObject* self, PyObject* args)
2347 int err;
2348 char delim;
2350 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2351 PyErr_Clear();
2352 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2353 return NULL;
2356 CHECK_DB_NOT_CLOSED(self);
2358 MYDB_BEGIN_ALLOW_THREADS;
2359 err = self->db->set_re_delim(self->db, delim);
2360 MYDB_END_ALLOW_THREADS;
2361 RETURN_IF_ERR();
2362 RETURN_NONE();
2365 static PyObject*
2366 DB_set_re_len(DBObject* self, PyObject* args)
2368 int err, len;
2370 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2371 return NULL;
2372 CHECK_DB_NOT_CLOSED(self);
2374 MYDB_BEGIN_ALLOW_THREADS;
2375 err = self->db->set_re_len(self->db, len);
2376 MYDB_END_ALLOW_THREADS;
2377 RETURN_IF_ERR();
2378 RETURN_NONE();
2382 static PyObject*
2383 DB_set_re_pad(DBObject* self, PyObject* args)
2385 int err;
2386 char pad;
2388 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2389 PyErr_Clear();
2390 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2391 return NULL;
2393 CHECK_DB_NOT_CLOSED(self);
2395 MYDB_BEGIN_ALLOW_THREADS;
2396 err = self->db->set_re_pad(self->db, pad);
2397 MYDB_END_ALLOW_THREADS;
2398 RETURN_IF_ERR();
2399 RETURN_NONE();
2403 static PyObject*
2404 DB_set_re_source(DBObject* self, PyObject* args)
2406 int err;
2407 char *re_source;
2409 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2410 return NULL;
2411 CHECK_DB_NOT_CLOSED(self);
2413 MYDB_BEGIN_ALLOW_THREADS;
2414 err = self->db->set_re_source(self->db, re_source);
2415 MYDB_END_ALLOW_THREADS;
2416 RETURN_IF_ERR();
2417 RETURN_NONE();
2421 #if (DBVER >= 32)
2422 static PyObject*
2423 DB_set_q_extentsize(DBObject* self, PyObject* args)
2425 int err;
2426 int extentsize;
2428 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2429 return NULL;
2430 CHECK_DB_NOT_CLOSED(self);
2432 MYDB_BEGIN_ALLOW_THREADS;
2433 err = self->db->set_q_extentsize(self->db, extentsize);
2434 MYDB_END_ALLOW_THREADS;
2435 RETURN_IF_ERR();
2436 RETURN_NONE();
2438 #endif
2440 static PyObject*
2441 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2443 int err, flags = 0, type;
2444 void* sp;
2445 PyObject* d;
2446 #if (DBVER >= 43)
2447 PyObject* txnobj = NULL;
2448 DB_TXN *txn = NULL;
2449 static char* kwnames[] = { "flags", "txn", NULL };
2450 #else
2451 static char* kwnames[] = { "flags", NULL };
2452 #endif
2454 #if (DBVER >= 43)
2455 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2456 &flags, &txnobj))
2457 return NULL;
2458 if (!checkTxnObj(txnobj, &txn))
2459 return NULL;
2460 #else
2461 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2462 return NULL;
2463 #endif
2464 CHECK_DB_NOT_CLOSED(self);
2466 MYDB_BEGIN_ALLOW_THREADS;
2467 #if (DBVER >= 43)
2468 err = self->db->stat(self->db, txn, &sp, flags);
2469 #elif (DBVER >= 33)
2470 err = self->db->stat(self->db, &sp, flags);
2471 #else
2472 err = self->db->stat(self->db, &sp, NULL, flags);
2473 #endif
2474 MYDB_END_ALLOW_THREADS;
2475 RETURN_IF_ERR();
2477 self->haveStat = 1;
2479 /* Turn the stat structure into a dictionary */
2480 type = _DB_get_type(self);
2481 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2482 free(sp);
2483 return NULL;
2486 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2487 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2488 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2490 switch (type) {
2491 case DB_HASH:
2492 MAKE_HASH_ENTRY(magic);
2493 MAKE_HASH_ENTRY(version);
2494 MAKE_HASH_ENTRY(nkeys);
2495 MAKE_HASH_ENTRY(ndata);
2496 MAKE_HASH_ENTRY(pagesize);
2497 #if (DBVER < 41)
2498 MAKE_HASH_ENTRY(nelem);
2499 #endif
2500 MAKE_HASH_ENTRY(ffactor);
2501 MAKE_HASH_ENTRY(buckets);
2502 MAKE_HASH_ENTRY(free);
2503 MAKE_HASH_ENTRY(bfree);
2504 MAKE_HASH_ENTRY(bigpages);
2505 MAKE_HASH_ENTRY(big_bfree);
2506 MAKE_HASH_ENTRY(overflows);
2507 MAKE_HASH_ENTRY(ovfl_free);
2508 MAKE_HASH_ENTRY(dup);
2509 MAKE_HASH_ENTRY(dup_free);
2510 break;
2512 case DB_BTREE:
2513 case DB_RECNO:
2514 MAKE_BT_ENTRY(magic);
2515 MAKE_BT_ENTRY(version);
2516 MAKE_BT_ENTRY(nkeys);
2517 MAKE_BT_ENTRY(ndata);
2518 MAKE_BT_ENTRY(pagesize);
2519 MAKE_BT_ENTRY(minkey);
2520 MAKE_BT_ENTRY(re_len);
2521 MAKE_BT_ENTRY(re_pad);
2522 MAKE_BT_ENTRY(levels);
2523 MAKE_BT_ENTRY(int_pg);
2524 MAKE_BT_ENTRY(leaf_pg);
2525 MAKE_BT_ENTRY(dup_pg);
2526 MAKE_BT_ENTRY(over_pg);
2527 MAKE_BT_ENTRY(free);
2528 MAKE_BT_ENTRY(int_pgfree);
2529 MAKE_BT_ENTRY(leaf_pgfree);
2530 MAKE_BT_ENTRY(dup_pgfree);
2531 MAKE_BT_ENTRY(over_pgfree);
2532 break;
2534 case DB_QUEUE:
2535 MAKE_QUEUE_ENTRY(magic);
2536 MAKE_QUEUE_ENTRY(version);
2537 MAKE_QUEUE_ENTRY(nkeys);
2538 MAKE_QUEUE_ENTRY(ndata);
2539 MAKE_QUEUE_ENTRY(pagesize);
2540 MAKE_QUEUE_ENTRY(pages);
2541 MAKE_QUEUE_ENTRY(re_len);
2542 MAKE_QUEUE_ENTRY(re_pad);
2543 MAKE_QUEUE_ENTRY(pgfree);
2544 #if (DBVER == 31)
2545 MAKE_QUEUE_ENTRY(start);
2546 #endif
2547 MAKE_QUEUE_ENTRY(first_recno);
2548 MAKE_QUEUE_ENTRY(cur_recno);
2549 break;
2551 default:
2552 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2553 Py_DECREF(d);
2554 d = NULL;
2557 #undef MAKE_HASH_ENTRY
2558 #undef MAKE_BT_ENTRY
2559 #undef MAKE_QUEUE_ENTRY
2561 free(sp);
2562 return d;
2565 static PyObject*
2566 DB_sync(DBObject* self, PyObject* args)
2568 int err;
2569 int flags = 0;
2571 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2572 return NULL;
2573 CHECK_DB_NOT_CLOSED(self);
2575 MYDB_BEGIN_ALLOW_THREADS;
2576 err = self->db->sync(self->db, flags);
2577 MYDB_END_ALLOW_THREADS;
2578 RETURN_IF_ERR();
2579 RETURN_NONE();
2583 #if (DBVER >= 33)
2584 static PyObject*
2585 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2587 int err, flags=0;
2588 u_int32_t count=0;
2589 PyObject* txnobj = NULL;
2590 DB_TXN *txn = NULL;
2591 static char* kwnames[] = { "txn", "flags", NULL };
2593 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2594 &txnobj, &flags))
2595 return NULL;
2596 CHECK_DB_NOT_CLOSED(self);
2597 if (!checkTxnObj(txnobj, &txn))
2598 return NULL;
2600 MYDB_BEGIN_ALLOW_THREADS;
2601 err = self->db->truncate(self->db, txn, &count, flags);
2602 MYDB_END_ALLOW_THREADS;
2603 RETURN_IF_ERR();
2604 return PyInt_FromLong(count);
2606 #endif
2609 static PyObject*
2610 DB_upgrade(DBObject* self, PyObject* args)
2612 int err, flags=0;
2613 char *filename;
2615 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2616 return NULL;
2617 CHECK_DB_NOT_CLOSED(self);
2619 MYDB_BEGIN_ALLOW_THREADS;
2620 err = self->db->upgrade(self->db, filename, flags);
2621 MYDB_END_ALLOW_THREADS;
2622 RETURN_IF_ERR();
2623 RETURN_NONE();
2627 static PyObject*
2628 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2630 int err, flags=0;
2631 char* fileName;
2632 char* dbName=NULL;
2633 char* outFileName=NULL;
2634 FILE* outFile=NULL;
2635 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2636 NULL };
2638 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2639 &fileName, &dbName, &outFileName, &flags))
2640 return NULL;
2642 CHECK_DB_NOT_CLOSED(self);
2643 if (outFileName)
2644 outFile = fopen(outFileName, "w");
2645 /* XXX(nnorwitz): it should probably be an exception if outFile
2646 can't be opened. */
2648 MYDB_BEGIN_ALLOW_THREADS;
2649 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2650 MYDB_END_ALLOW_THREADS;
2651 if (outFile)
2652 fclose(outFile);
2654 /* DB.verify acts as a DB handle destructor (like close); this was
2655 * documented in BerkeleyDB 4.2 but had the undocumented effect
2656 * of not being safe in prior versions while still requiring an explicit
2657 * DB.close call afterwards. Lets call close for the user to emulate
2658 * the safe 4.2 behaviour. */
2659 #if (DBVER <= 41)
2660 self->db->close(self->db, 0);
2661 #endif
2662 self->db = NULL;
2664 RETURN_IF_ERR();
2665 RETURN_NONE();
2669 static PyObject*
2670 DB_set_get_returns_none(DBObject* self, PyObject* args)
2672 int flags=0;
2673 int oldValue=0;
2675 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2676 return NULL;
2677 CHECK_DB_NOT_CLOSED(self);
2679 if (self->moduleFlags.getReturnsNone)
2680 ++oldValue;
2681 if (self->moduleFlags.cursorSetReturnsNone)
2682 ++oldValue;
2683 self->moduleFlags.getReturnsNone = (flags >= 1);
2684 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2685 return PyInt_FromLong(oldValue);
2688 #if (DBVER >= 41)
2689 static PyObject*
2690 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2692 int err;
2693 u_int32_t flags=0;
2694 char *passwd = NULL;
2695 static char* kwnames[] = { "passwd", "flags", NULL };
2697 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2698 &passwd, &flags)) {
2699 return NULL;
2702 MYDB_BEGIN_ALLOW_THREADS;
2703 err = self->db->set_encrypt(self->db, passwd, flags);
2704 MYDB_END_ALLOW_THREADS;
2706 RETURN_IF_ERR();
2707 RETURN_NONE();
2709 #endif /* DBVER >= 41 */
2712 /*-------------------------------------------------------------- */
2713 /* Mapping and Dictionary-like access routines */
2715 Py_ssize_t DB_length(PyObject* _self)
2717 int err;
2718 Py_ssize_t size = 0;
2719 int flags = 0;
2720 void* sp;
2721 DBObject* self = (DBObject*)_self;
2723 if (self->db == NULL) {
2724 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2725 PyErr_SetObject(DBError, t);
2726 Py_DECREF(t);
2727 return -1;
2730 if (self->haveStat) { /* Has the stat function been called recently? If
2731 so, we can use the cached value. */
2732 flags = DB_FAST_STAT;
2735 MYDB_BEGIN_ALLOW_THREADS;
2736 redo_stat_for_length:
2737 #if (DBVER >= 43)
2738 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2739 #elif (DBVER >= 33)
2740 err = self->db->stat(self->db, &sp, flags);
2741 #else
2742 err = self->db->stat(self->db, &sp, NULL, flags);
2743 #endif
2745 /* All the stat structures have matching fields upto the ndata field,
2746 so we can use any of them for the type cast */
2747 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2749 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2750 * redo a full stat to make sure.
2751 * Fixes SF python bug 1493322, pybsddb bug 1184012
2753 if (size == 0 && (flags & DB_FAST_STAT)) {
2754 flags = 0;
2755 if (!err)
2756 free(sp);
2757 goto redo_stat_for_length;
2760 MYDB_END_ALLOW_THREADS;
2762 if (err)
2763 return -1;
2765 self->haveStat = 1;
2767 free(sp);
2768 return size;
2772 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2774 int err;
2775 PyObject* retval;
2776 DBT key;
2777 DBT data;
2779 CHECK_DB_NOT_CLOSED(self);
2780 if (!make_key_dbt(self, keyobj, &key, NULL))
2781 return NULL;
2783 CLEAR_DBT(data);
2784 if (CHECK_DBFLAG(self, DB_THREAD)) {
2785 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2786 data.flags = DB_DBT_MALLOC;
2788 MYDB_BEGIN_ALLOW_THREADS;
2789 err = self->db->get(self->db, NULL, &key, &data, 0);
2790 MYDB_END_ALLOW_THREADS;
2791 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2792 PyErr_SetObject(PyExc_KeyError, keyobj);
2793 retval = NULL;
2795 else if (makeDBError(err)) {
2796 retval = NULL;
2798 else {
2799 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2800 FREE_DBT(data);
2803 FREE_DBT(key);
2804 return retval;
2808 static int
2809 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2811 DBT key, data;
2812 int retval;
2813 int flags = 0;
2815 if (self->db == NULL) {
2816 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2817 PyErr_SetObject(DBError, t);
2818 Py_DECREF(t);
2819 return -1;
2822 if (!make_key_dbt(self, keyobj, &key, NULL))
2823 return -1;
2825 if (dataobj != NULL) {
2826 if (!make_dbt(dataobj, &data))
2827 retval = -1;
2828 else {
2829 if (self->setflags & (DB_DUP|DB_DUPSORT))
2830 /* dictionaries shouldn't have duplicate keys */
2831 flags = DB_NOOVERWRITE;
2832 retval = _DB_put(self, NULL, &key, &data, flags);
2834 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2835 /* try deleting any old record that matches and then PUT it
2836 * again... */
2837 _DB_delete(self, NULL, &key, 0);
2838 PyErr_Clear();
2839 retval = _DB_put(self, NULL, &key, &data, flags);
2843 else {
2844 /* dataobj == NULL, so delete the key */
2845 retval = _DB_delete(self, NULL, &key, 0);
2847 FREE_DBT(key);
2848 return retval;
2852 static PyObject*
2853 DB_has_key(DBObject* self, PyObject* args)
2855 int err;
2856 PyObject* keyobj;
2857 DBT key, data;
2858 PyObject* txnobj = NULL;
2859 DB_TXN *txn = NULL;
2861 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2862 return NULL;
2863 CHECK_DB_NOT_CLOSED(self);
2864 if (!make_key_dbt(self, keyobj, &key, NULL))
2865 return NULL;
2866 if (!checkTxnObj(txnobj, &txn)) {
2867 FREE_DBT(key);
2868 return NULL;
2871 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2872 it has a record but can't allocate a buffer for the data. This saves
2873 having to deal with data we won't be using.
2875 CLEAR_DBT(data);
2876 data.flags = DB_DBT_USERMEM;
2878 MYDB_BEGIN_ALLOW_THREADS;
2879 err = self->db->get(self->db, txn, &key, &data, 0);
2880 MYDB_END_ALLOW_THREADS;
2881 FREE_DBT(key);
2883 if (err == DB_BUFFER_SMALL || err == 0) {
2884 return PyInt_FromLong(1);
2885 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2886 return PyInt_FromLong(0);
2889 makeDBError(err);
2890 return NULL;
2894 #define _KEYS_LIST 1
2895 #define _VALUES_LIST 2
2896 #define _ITEMS_LIST 3
2898 static PyObject*
2899 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2901 int err, dbtype;
2902 DBT key;
2903 DBT data;
2904 DBC *cursor;
2905 PyObject* list;
2906 PyObject* item = NULL;
2908 CHECK_DB_NOT_CLOSED(self);
2909 CLEAR_DBT(key);
2910 CLEAR_DBT(data);
2912 dbtype = _DB_get_type(self);
2913 if (dbtype == -1)
2914 return NULL;
2916 list = PyList_New(0);
2917 if (list == NULL)
2918 return NULL;
2920 /* get a cursor */
2921 MYDB_BEGIN_ALLOW_THREADS;
2922 err = self->db->cursor(self->db, txn, &cursor, 0);
2923 MYDB_END_ALLOW_THREADS;
2924 if (makeDBError(err)) {
2925 Py_DECREF(list);
2926 return NULL;
2929 if (CHECK_DBFLAG(self, DB_THREAD)) {
2930 key.flags = DB_DBT_REALLOC;
2931 data.flags = DB_DBT_REALLOC;
2934 while (1) { /* use the cursor to traverse the DB, collecting items */
2935 MYDB_BEGIN_ALLOW_THREADS;
2936 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2937 MYDB_END_ALLOW_THREADS;
2939 if (err) {
2940 /* for any error, break out of the loop */
2941 break;
2944 switch (type) {
2945 case _KEYS_LIST:
2946 switch(dbtype) {
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
2950 item = PyString_FromStringAndSize((char*)key.data, key.size);
2951 break;
2952 case DB_RECNO:
2953 case DB_QUEUE:
2954 item = PyInt_FromLong(*((db_recno_t*)key.data));
2955 break;
2957 break;
2959 case _VALUES_LIST:
2960 item = PyString_FromStringAndSize((char*)data.data, data.size);
2961 break;
2963 case _ITEMS_LIST:
2964 switch(dbtype) {
2965 case DB_BTREE:
2966 case DB_HASH:
2967 default:
2968 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2969 data.size);
2970 break;
2971 case DB_RECNO:
2972 case DB_QUEUE:
2973 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2974 data.data, data.size);
2975 break;
2977 break;
2978 default:
2979 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2980 item = NULL;
2981 break;
2983 if (item == NULL) {
2984 Py_DECREF(list);
2985 list = NULL;
2986 goto done;
2988 PyList_Append(list, item);
2989 Py_DECREF(item);
2992 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2993 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2994 Py_DECREF(list);
2995 list = NULL;
2998 done:
2999 FREE_DBT(key);
3000 FREE_DBT(data);
3001 MYDB_BEGIN_ALLOW_THREADS;
3002 cursor->c_close(cursor);
3003 MYDB_END_ALLOW_THREADS;
3004 return list;
3008 static PyObject*
3009 DB_keys(DBObject* self, PyObject* args)
3011 PyObject* txnobj = NULL;
3012 DB_TXN *txn = NULL;
3014 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
3015 return NULL;
3016 if (!checkTxnObj(txnobj, &txn))
3017 return NULL;
3018 return _DB_make_list(self, txn, _KEYS_LIST);
3022 static PyObject*
3023 DB_items(DBObject* self, PyObject* args)
3025 PyObject* txnobj = NULL;
3026 DB_TXN *txn = NULL;
3028 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3029 return NULL;
3030 if (!checkTxnObj(txnobj, &txn))
3031 return NULL;
3032 return _DB_make_list(self, txn, _ITEMS_LIST);
3036 static PyObject*
3037 DB_values(DBObject* self, PyObject* args)
3039 PyObject* txnobj = NULL;
3040 DB_TXN *txn = NULL;
3042 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3043 return NULL;
3044 if (!checkTxnObj(txnobj, &txn))
3045 return NULL;
3046 return _DB_make_list(self, txn, _VALUES_LIST);
3049 /* --------------------------------------------------------------------- */
3050 /* DBCursor methods */
3053 static PyObject*
3054 DBC_close(DBCursorObject* self, PyObject* args)
3056 int err = 0;
3058 if (!PyArg_ParseTuple(args, ":close"))
3059 return NULL;
3061 if (self->dbc != NULL) {
3062 MYDB_BEGIN_ALLOW_THREADS;
3063 err = self->dbc->c_close(self->dbc);
3064 self->dbc = NULL;
3065 MYDB_END_ALLOW_THREADS;
3067 RETURN_IF_ERR();
3068 RETURN_NONE();
3072 static PyObject*
3073 DBC_count(DBCursorObject* self, PyObject* args)
3075 int err = 0;
3076 db_recno_t count;
3077 int flags = 0;
3079 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3080 return NULL;
3082 CHECK_CURSOR_NOT_CLOSED(self);
3084 MYDB_BEGIN_ALLOW_THREADS;
3085 err = self->dbc->c_count(self->dbc, &count, flags);
3086 MYDB_END_ALLOW_THREADS;
3087 RETURN_IF_ERR();
3089 return PyInt_FromLong(count);
3093 static PyObject*
3094 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3096 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3100 static PyObject*
3101 DBC_delete(DBCursorObject* self, PyObject* args)
3103 int err, flags=0;
3105 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3106 return NULL;
3108 CHECK_CURSOR_NOT_CLOSED(self);
3110 MYDB_BEGIN_ALLOW_THREADS;
3111 err = self->dbc->c_del(self->dbc, flags);
3112 MYDB_END_ALLOW_THREADS;
3113 RETURN_IF_ERR();
3115 self->mydb->haveStat = 0;
3116 RETURN_NONE();
3120 static PyObject*
3121 DBC_dup(DBCursorObject* self, PyObject* args)
3123 int err, flags =0;
3124 DBC* dbc = NULL;
3126 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3127 return NULL;
3129 CHECK_CURSOR_NOT_CLOSED(self);
3131 MYDB_BEGIN_ALLOW_THREADS;
3132 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3133 MYDB_END_ALLOW_THREADS;
3134 RETURN_IF_ERR();
3136 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3139 static PyObject*
3140 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3142 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3146 static PyObject*
3147 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3149 int err, flags=0;
3150 PyObject* keyobj = NULL;
3151 PyObject* dataobj = NULL;
3152 PyObject* retval = NULL;
3153 int dlen = -1;
3154 int doff = -1;
3155 DBT key, data;
3156 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3157 NULL };
3159 CLEAR_DBT(key);
3160 CLEAR_DBT(data);
3161 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3162 &flags, &dlen, &doff))
3164 PyErr_Clear();
3165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3166 &kwnames[1],
3167 &keyobj, &flags, &dlen, &doff))
3169 PyErr_Clear();
3170 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3171 kwnames, &keyobj, &dataobj,
3172 &flags, &dlen, &doff))
3174 return NULL;
3179 CHECK_CURSOR_NOT_CLOSED(self);
3181 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3182 return NULL;
3183 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3184 (!add_partial_dbt(&data, dlen, doff)) )
3186 FREE_DBT(key);
3187 return NULL;
3190 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3191 data.flags = DB_DBT_MALLOC;
3192 if (!(key.flags & DB_DBT_REALLOC)) {
3193 key.flags |= DB_DBT_MALLOC;
3197 MYDB_BEGIN_ALLOW_THREADS;
3198 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3199 MYDB_END_ALLOW_THREADS;
3201 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3202 && self->mydb->moduleFlags.getReturnsNone) {
3203 Py_INCREF(Py_None);
3204 retval = Py_None;
3206 else if (makeDBError(err)) {
3207 retval = NULL;
3209 else {
3210 switch (_DB_get_type(self->mydb)) {
3211 case -1:
3212 retval = NULL;
3213 break;
3214 case DB_BTREE:
3215 case DB_HASH:
3216 default:
3217 retval = Py_BuildValue("s#s#", key.data, key.size,
3218 data.data, data.size);
3219 break;
3220 case DB_RECNO:
3221 case DB_QUEUE:
3222 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3223 data.data, data.size);
3224 break;
3226 FREE_DBT(data);
3228 FREE_DBT(key);
3229 return retval;
3232 #if (DBVER >= 33)
3233 static PyObject*
3234 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3236 int err, flags=0;
3237 PyObject* keyobj = NULL;
3238 PyObject* dataobj = NULL;
3239 PyObject* retval = NULL;
3240 int dlen = -1;
3241 int doff = -1;
3242 DBT key, pkey, data;
3243 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3244 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3246 CLEAR_DBT(key);
3247 CLEAR_DBT(data);
3248 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3249 &flags, &dlen, &doff))
3251 PyErr_Clear();
3252 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3253 kwnames_keyOnly,
3254 &keyobj, &flags, &dlen, &doff))
3256 PyErr_Clear();
3257 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3258 kwnames, &keyobj, &dataobj,
3259 &flags, &dlen, &doff))
3261 return NULL;
3266 CHECK_CURSOR_NOT_CLOSED(self);
3268 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3269 return NULL;
3270 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3271 (!add_partial_dbt(&data, dlen, doff)) ) {
3272 FREE_DBT(key);
3273 return NULL;
3276 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3277 data.flags = DB_DBT_MALLOC;
3278 if (!(key.flags & DB_DBT_REALLOC)) {
3279 key.flags |= DB_DBT_MALLOC;
3283 CLEAR_DBT(pkey);
3284 pkey.flags = DB_DBT_MALLOC;
3286 MYDB_BEGIN_ALLOW_THREADS;
3287 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3288 MYDB_END_ALLOW_THREADS;
3290 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3291 && self->mydb->moduleFlags.getReturnsNone) {
3292 Py_INCREF(Py_None);
3293 retval = Py_None;
3295 else if (makeDBError(err)) {
3296 retval = NULL;
3298 else {
3299 PyObject *pkeyObj;
3300 PyObject *dataObj;
3301 dataObj = PyString_FromStringAndSize(data.data, data.size);
3303 if (self->mydb->primaryDBType == DB_RECNO ||
3304 self->mydb->primaryDBType == DB_QUEUE)
3305 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3306 else
3307 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3309 if (key.data && key.size) /* return key, pkey and data */
3311 PyObject *keyObj;
3312 int type = _DB_get_type(self->mydb);
3313 if (type == DB_RECNO || type == DB_QUEUE)
3314 keyObj = PyInt_FromLong(*(int *)key.data);
3315 else
3316 keyObj = PyString_FromStringAndSize(key.data, key.size);
3317 #if (PY_VERSION_HEX >= 0x02040000)
3318 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3319 #else
3320 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3321 #endif
3322 Py_DECREF(keyObj);
3323 FREE_DBT(key);
3325 else /* return just the pkey and data */
3327 #if (PY_VERSION_HEX >= 0x02040000)
3328 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3329 #else
3330 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3331 #endif
3333 Py_DECREF(dataObj);
3334 Py_DECREF(pkeyObj);
3335 FREE_DBT(pkey);
3336 FREE_DBT(data);
3338 /* the only time REALLOC should be set is if we used an integer
3339 * key that make_key_dbt malloc'd for us. always free these. */
3340 if (key.flags & DB_DBT_REALLOC) {
3341 FREE_DBT(key);
3343 return retval;
3345 #endif
3348 static PyObject*
3349 DBC_get_recno(DBCursorObject* self, PyObject* args)
3351 int err;
3352 db_recno_t recno;
3353 DBT key;
3354 DBT data;
3356 if (!PyArg_ParseTuple(args, ":get_recno"))
3357 return NULL;
3359 CHECK_CURSOR_NOT_CLOSED(self);
3361 CLEAR_DBT(key);
3362 CLEAR_DBT(data);
3363 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3364 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3365 data.flags = DB_DBT_MALLOC;
3366 key.flags = DB_DBT_MALLOC;
3369 MYDB_BEGIN_ALLOW_THREADS;
3370 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3371 MYDB_END_ALLOW_THREADS;
3372 RETURN_IF_ERR();
3374 recno = *((db_recno_t*)data.data);
3375 FREE_DBT(key);
3376 FREE_DBT(data);
3377 return PyInt_FromLong(recno);
3381 static PyObject*
3382 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3384 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3388 static PyObject*
3389 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3391 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3395 static PyObject*
3396 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3398 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3402 static PyObject*
3403 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3405 int err, flags = 0;
3406 PyObject* keyobj, *dataobj;
3407 DBT key, data;
3408 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3409 NULL };
3410 int dlen = -1;
3411 int doff = -1;
3413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3414 &keyobj, &dataobj, &flags, &dlen, &doff))
3415 return NULL;
3417 CHECK_CURSOR_NOT_CLOSED(self);
3419 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3420 return NULL;
3421 if (!make_dbt(dataobj, &data) ||
3422 !add_partial_dbt(&data, dlen, doff) )
3424 FREE_DBT(key);
3425 return NULL;
3428 MYDB_BEGIN_ALLOW_THREADS;
3429 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3430 MYDB_END_ALLOW_THREADS;
3431 FREE_DBT(key);
3432 RETURN_IF_ERR();
3433 self->mydb->haveStat = 0;
3434 RETURN_NONE();
3438 static PyObject*
3439 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3441 int err, flags = 0;
3442 DBT key, data;
3443 PyObject* retval, *keyobj;
3444 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3445 int dlen = -1;
3446 int doff = -1;
3448 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3449 &keyobj, &flags, &dlen, &doff))
3450 return NULL;
3452 CHECK_CURSOR_NOT_CLOSED(self);
3454 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3455 return NULL;
3457 CLEAR_DBT(data);
3458 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3459 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3460 data.flags = DB_DBT_MALLOC;
3462 if (!add_partial_dbt(&data, dlen, doff)) {
3463 FREE_DBT(key);
3464 return NULL;
3467 MYDB_BEGIN_ALLOW_THREADS;
3468 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3469 MYDB_END_ALLOW_THREADS;
3470 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3471 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3472 Py_INCREF(Py_None);
3473 retval = Py_None;
3475 else if (makeDBError(err)) {
3476 retval = NULL;
3478 else {
3479 switch (_DB_get_type(self->mydb)) {
3480 case -1:
3481 retval = NULL;
3482 break;
3483 case DB_BTREE:
3484 case DB_HASH:
3485 default:
3486 retval = Py_BuildValue("s#s#", key.data, key.size,
3487 data.data, data.size);
3488 break;
3489 case DB_RECNO:
3490 case DB_QUEUE:
3491 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3492 data.data, data.size);
3493 break;
3495 FREE_DBT(data);
3496 FREE_DBT(key);
3498 /* the only time REALLOC should be set is if we used an integer
3499 * key that make_key_dbt malloc'd for us. always free these. */
3500 if (key.flags & DB_DBT_REALLOC) {
3501 FREE_DBT(key);
3504 return retval;
3508 static PyObject*
3509 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3511 int err, flags = 0;
3512 DBT key, data;
3513 PyObject* retval, *keyobj;
3514 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3515 int dlen = -1;
3516 int doff = -1;
3518 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3519 &keyobj, &flags, &dlen, &doff))
3520 return NULL;
3522 CHECK_CURSOR_NOT_CLOSED(self);
3524 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3525 return NULL;
3527 CLEAR_DBT(data);
3528 if (!add_partial_dbt(&data, dlen, doff)) {
3529 FREE_DBT(key);
3530 return NULL;
3532 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3533 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3534 data.flags |= DB_DBT_MALLOC;
3535 /* only BTREE databases will return anything in the key */
3536 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3537 key.flags |= DB_DBT_MALLOC;
3540 MYDB_BEGIN_ALLOW_THREADS;
3541 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3542 MYDB_END_ALLOW_THREADS;
3543 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3544 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3545 Py_INCREF(Py_None);
3546 retval = Py_None;
3548 else if (makeDBError(err)) {
3549 retval = NULL;
3551 else {
3552 switch (_DB_get_type(self->mydb)) {
3553 case -1:
3554 retval = NULL;
3555 break;
3556 case DB_BTREE:
3557 case DB_HASH:
3558 default:
3559 retval = Py_BuildValue("s#s#", key.data, key.size,
3560 data.data, data.size);
3561 break;
3562 case DB_RECNO:
3563 case DB_QUEUE:
3564 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3565 data.data, data.size);
3566 break;
3568 FREE_DBT(key);
3569 FREE_DBT(data);
3571 /* the only time REALLOC should be set is if we used an integer
3572 * key that make_key_dbt malloc'd for us. always free these. */
3573 if (key.flags & DB_DBT_REALLOC) {
3574 FREE_DBT(key);
3577 return retval;
3580 static PyObject*
3581 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3582 int flags, unsigned int returnsNone)
3584 int err;
3585 DBT key, data;
3586 PyObject* retval;
3588 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3589 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3590 return NULL;
3591 if (!make_dbt(dataobj, &data)) {
3592 FREE_DBT(key);
3593 return NULL;
3596 MYDB_BEGIN_ALLOW_THREADS;
3597 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3598 MYDB_END_ALLOW_THREADS;
3599 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3600 Py_INCREF(Py_None);
3601 retval = Py_None;
3603 else if (makeDBError(err)) {
3604 retval = NULL;
3606 else {
3607 switch (_DB_get_type(self->mydb)) {
3608 case -1:
3609 retval = NULL;
3610 break;
3611 case DB_BTREE:
3612 case DB_HASH:
3613 default:
3614 retval = Py_BuildValue("s#s#", key.data, key.size,
3615 data.data, data.size);
3616 break;
3617 case DB_RECNO:
3618 case DB_QUEUE:
3619 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3620 data.data, data.size);
3621 break;
3625 FREE_DBT(key);
3626 return retval;
3629 static PyObject*
3630 DBC_get_both(DBCursorObject* self, PyObject* args)
3632 int flags=0;
3633 PyObject *keyobj, *dataobj;
3635 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3636 return NULL;
3638 /* if the cursor is closed, self->mydb may be invalid */
3639 CHECK_CURSOR_NOT_CLOSED(self);
3641 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3642 self->mydb->moduleFlags.getReturnsNone);
3645 /* Return size of entry */
3646 static PyObject*
3647 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3649 int err, flags=DB_CURRENT;
3650 PyObject* retval = NULL;
3651 DBT key, data;
3653 if (!PyArg_ParseTuple(args, ":get_current_size"))
3654 return NULL;
3655 CHECK_CURSOR_NOT_CLOSED(self);
3656 CLEAR_DBT(key);
3657 CLEAR_DBT(data);
3659 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3660 getting the record size. */
3661 data.flags = DB_DBT_USERMEM;
3662 data.ulen = 0;
3663 MYDB_BEGIN_ALLOW_THREADS;
3664 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3665 MYDB_END_ALLOW_THREADS;
3666 if (err == DB_BUFFER_SMALL || !err) {
3667 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3668 retval = PyInt_FromLong((long)data.size);
3669 err = 0;
3672 FREE_DBT(key);
3673 FREE_DBT(data);
3674 RETURN_IF_ERR();
3675 return retval;
3678 static PyObject*
3679 DBC_set_both(DBCursorObject* self, PyObject* args)
3681 int flags=0;
3682 PyObject *keyobj, *dataobj;
3684 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3685 return NULL;
3687 /* if the cursor is closed, self->mydb may be invalid */
3688 CHECK_CURSOR_NOT_CLOSED(self);
3690 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3691 self->mydb->moduleFlags.cursorSetReturnsNone);
3695 static PyObject*
3696 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3698 int err, irecno, flags=0;
3699 db_recno_t recno;
3700 DBT key, data;
3701 PyObject* retval;
3702 int dlen = -1;
3703 int doff = -1;
3704 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3706 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3707 &irecno, &flags, &dlen, &doff))
3708 return NULL;
3710 CHECK_CURSOR_NOT_CLOSED(self);
3712 CLEAR_DBT(key);
3713 recno = (db_recno_t) irecno;
3714 /* use allocated space so DB will be able to realloc room for the real
3715 * key */
3716 key.data = malloc(sizeof(db_recno_t));
3717 if (key.data == NULL) {
3718 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3719 return NULL;
3721 key.size = sizeof(db_recno_t);
3722 key.ulen = key.size;
3723 memcpy(key.data, &recno, sizeof(db_recno_t));
3724 key.flags = DB_DBT_REALLOC;
3726 CLEAR_DBT(data);
3727 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3728 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3729 data.flags = DB_DBT_MALLOC;
3731 if (!add_partial_dbt(&data, dlen, doff)) {
3732 FREE_DBT(key);
3733 return NULL;
3736 MYDB_BEGIN_ALLOW_THREADS;
3737 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3738 MYDB_END_ALLOW_THREADS;
3739 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3740 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3741 Py_INCREF(Py_None);
3742 retval = Py_None;
3744 else if (makeDBError(err)) {
3745 retval = NULL;
3747 else { /* Can only be used for BTrees, so no need to return int key */
3748 retval = Py_BuildValue("s#s#", key.data, key.size,
3749 data.data, data.size);
3750 FREE_DBT(data);
3752 FREE_DBT(key);
3754 return retval;
3758 static PyObject*
3759 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3761 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3765 static PyObject*
3766 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3768 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3772 static PyObject*
3773 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3775 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3779 static PyObject*
3780 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3782 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3786 static PyObject*
3787 DBC_join_item(DBCursorObject* self, PyObject* args)
3789 int err, flags=0;
3790 DBT key, data;
3791 PyObject* retval;
3793 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3794 return NULL;
3796 CHECK_CURSOR_NOT_CLOSED(self);
3798 CLEAR_DBT(key);
3799 CLEAR_DBT(data);
3800 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3801 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3802 key.flags = DB_DBT_MALLOC;
3805 MYDB_BEGIN_ALLOW_THREADS;
3806 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3807 MYDB_END_ALLOW_THREADS;
3808 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3809 && self->mydb->moduleFlags.getReturnsNone) {
3810 Py_INCREF(Py_None);
3811 retval = Py_None;
3813 else if (makeDBError(err)) {
3814 retval = NULL;
3816 else {
3817 retval = Py_BuildValue("s#", key.data, key.size);
3818 FREE_DBT(key);
3821 return retval;
3826 /* --------------------------------------------------------------------- */
3827 /* DBEnv methods */
3830 static PyObject*
3831 DBEnv_close(DBEnvObject* self, PyObject* args)
3833 int err, flags = 0;
3835 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3836 return NULL;
3837 if (!self->closed) { /* Don't close more than once */
3838 MYDB_BEGIN_ALLOW_THREADS;
3839 err = self->db_env->close(self->db_env, flags);
3840 MYDB_END_ALLOW_THREADS;
3841 /* after calling DBEnv->close, regardless of error, this DBEnv
3842 * may not be accessed again (BerkeleyDB docs). */
3843 self->closed = 1;
3844 self->db_env = NULL;
3845 RETURN_IF_ERR();
3847 RETURN_NONE();
3851 static PyObject*
3852 DBEnv_open(DBEnvObject* self, PyObject* args)
3854 int err, flags=0, mode=0660;
3855 char *db_home;
3857 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3858 return NULL;
3860 CHECK_ENV_NOT_CLOSED(self);
3862 MYDB_BEGIN_ALLOW_THREADS;
3863 err = self->db_env->open(self->db_env, db_home, flags, mode);
3864 MYDB_END_ALLOW_THREADS;
3865 RETURN_IF_ERR();
3866 self->closed = 0;
3867 self->flags = flags;
3868 RETURN_NONE();
3872 static PyObject*
3873 DBEnv_remove(DBEnvObject* self, PyObject* args)
3875 int err, flags=0;
3876 char *db_home;
3878 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3879 return NULL;
3880 CHECK_ENV_NOT_CLOSED(self);
3881 MYDB_BEGIN_ALLOW_THREADS;
3882 err = self->db_env->remove(self->db_env, db_home, flags);
3883 MYDB_END_ALLOW_THREADS;
3884 RETURN_IF_ERR();
3885 RETURN_NONE();
3888 #if (DBVER >= 41)
3889 static PyObject*
3890 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3892 int err;
3893 u_int32_t flags=0;
3894 char *file = NULL;
3895 char *database = NULL;
3896 PyObject *txnobj = NULL;
3897 DB_TXN *txn = NULL;
3898 static char* kwnames[] = { "file", "database", "txn", "flags",
3899 NULL };
3901 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
3902 &file, &database, &txnobj, &flags)) {
3903 return NULL;
3905 if (!checkTxnObj(txnobj, &txn)) {
3906 return NULL;
3908 CHECK_ENV_NOT_CLOSED(self);
3909 MYDB_BEGIN_ALLOW_THREADS;
3910 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3911 MYDB_END_ALLOW_THREADS;
3912 RETURN_IF_ERR();
3913 RETURN_NONE();
3916 static PyObject*
3917 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3919 int err;
3920 u_int32_t flags=0;
3921 char *file = NULL;
3922 char *database = NULL;
3923 char *newname = NULL;
3924 PyObject *txnobj = NULL;
3925 DB_TXN *txn = NULL;
3926 static char* kwnames[] = { "file", "database", "newname", "txn",
3927 "flags", NULL };
3929 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
3930 &file, &database, &newname, &txnobj, &flags)) {
3931 return NULL;
3933 if (!checkTxnObj(txnobj, &txn)) {
3934 return NULL;
3936 CHECK_ENV_NOT_CLOSED(self);
3937 MYDB_BEGIN_ALLOW_THREADS;
3938 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3939 flags);
3940 MYDB_END_ALLOW_THREADS;
3941 RETURN_IF_ERR();
3942 RETURN_NONE();
3945 static PyObject*
3946 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3948 int err;
3949 u_int32_t flags=0;
3950 char *passwd = NULL;
3951 static char* kwnames[] = { "passwd", "flags", NULL };
3953 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3954 &passwd, &flags)) {
3955 return NULL;
3958 MYDB_BEGIN_ALLOW_THREADS;
3959 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3960 MYDB_END_ALLOW_THREADS;
3962 RETURN_IF_ERR();
3963 RETURN_NONE();
3965 #endif /* DBVER >= 41 */
3967 #if (DBVER >= 40)
3968 static PyObject*
3969 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3971 int err;
3972 u_int32_t flags=0;
3973 u_int32_t timeout = 0;
3974 static char* kwnames[] = { "timeout", "flags", NULL };
3976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3977 &timeout, &flags)) {
3978 return NULL;
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3983 MYDB_END_ALLOW_THREADS;
3985 RETURN_IF_ERR();
3986 RETURN_NONE();
3988 #endif /* DBVER >= 40 */
3990 static PyObject*
3991 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3993 int err;
3994 long shm_key = 0;
3996 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3997 return NULL;
3998 CHECK_ENV_NOT_CLOSED(self);
4000 err = self->db_env->set_shm_key(self->db_env, shm_key);
4001 RETURN_IF_ERR();
4002 RETURN_NONE();
4005 static PyObject*
4006 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4008 int err, gbytes=0, bytes=0, ncache=0;
4010 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4011 &gbytes, &bytes, &ncache))
4012 return NULL;
4013 CHECK_ENV_NOT_CLOSED(self);
4015 MYDB_BEGIN_ALLOW_THREADS;
4016 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4017 MYDB_END_ALLOW_THREADS;
4018 RETURN_IF_ERR();
4019 RETURN_NONE();
4023 #if (DBVER >= 32)
4024 static PyObject*
4025 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4027 int err, flags=0, onoff=0;
4029 if (!PyArg_ParseTuple(args, "ii:set_flags",
4030 &flags, &onoff))
4031 return NULL;
4032 CHECK_ENV_NOT_CLOSED(self);
4034 MYDB_BEGIN_ALLOW_THREADS;
4035 err = self->db_env->set_flags(self->db_env, flags, onoff);
4036 MYDB_END_ALLOW_THREADS;
4037 RETURN_IF_ERR();
4038 RETURN_NONE();
4040 #endif
4043 static PyObject*
4044 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4046 int err;
4047 char *dir;
4049 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4050 return NULL;
4051 CHECK_ENV_NOT_CLOSED(self);
4053 MYDB_BEGIN_ALLOW_THREADS;
4054 err = self->db_env->set_data_dir(self->db_env, dir);
4055 MYDB_END_ALLOW_THREADS;
4056 RETURN_IF_ERR();
4057 RETURN_NONE();
4061 static PyObject*
4062 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4064 int err, lg_bsize;
4066 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4078 static PyObject*
4079 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4081 int err;
4082 char *dir;
4084 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lg_dir(self->db_env, dir);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4095 static PyObject*
4096 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4098 int err, lg_max;
4100 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4101 return NULL;
4102 CHECK_ENV_NOT_CLOSED(self);
4104 MYDB_BEGIN_ALLOW_THREADS;
4105 err = self->db_env->set_lg_max(self->db_env, lg_max);
4106 MYDB_END_ALLOW_THREADS;
4107 RETURN_IF_ERR();
4108 RETURN_NONE();
4112 #if (DBVER >= 33)
4113 static PyObject*
4114 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4116 int err, lg_max;
4118 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4119 return NULL;
4120 CHECK_ENV_NOT_CLOSED(self);
4122 MYDB_BEGIN_ALLOW_THREADS;
4123 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4124 MYDB_END_ALLOW_THREADS;
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4128 #endif
4131 static PyObject*
4132 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4134 int err, lk_detect;
4136 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4137 return NULL;
4138 CHECK_ENV_NOT_CLOSED(self);
4140 MYDB_BEGIN_ALLOW_THREADS;
4141 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4142 MYDB_END_ALLOW_THREADS;
4143 RETURN_IF_ERR();
4144 RETURN_NONE();
4148 #if (DBVER < 45)
4149 static PyObject*
4150 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4152 int err, max;
4154 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4155 return NULL;
4156 CHECK_ENV_NOT_CLOSED(self);
4158 MYDB_BEGIN_ALLOW_THREADS;
4159 err = self->db_env->set_lk_max(self->db_env, max);
4160 MYDB_END_ALLOW_THREADS;
4161 RETURN_IF_ERR();
4162 RETURN_NONE();
4164 #endif
4167 #if (DBVER >= 32)
4169 static PyObject*
4170 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4172 int err, max;
4174 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4178 MYDB_BEGIN_ALLOW_THREADS;
4179 err = self->db_env->set_lk_max_locks(self->db_env, max);
4180 MYDB_END_ALLOW_THREADS;
4181 RETURN_IF_ERR();
4182 RETURN_NONE();
4186 static PyObject*
4187 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4189 int err, max;
4191 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4195 MYDB_BEGIN_ALLOW_THREADS;
4196 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4197 MYDB_END_ALLOW_THREADS;
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4203 static PyObject*
4204 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4206 int err, max;
4208 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4209 return NULL;
4210 CHECK_ENV_NOT_CLOSED(self);
4212 MYDB_BEGIN_ALLOW_THREADS;
4213 err = self->db_env->set_lk_max_objects(self->db_env, max);
4214 MYDB_END_ALLOW_THREADS;
4215 RETURN_IF_ERR();
4216 RETURN_NONE();
4219 #endif
4222 static PyObject*
4223 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4225 int err, mp_mmapsize;
4227 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4228 return NULL;
4229 CHECK_ENV_NOT_CLOSED(self);
4231 MYDB_BEGIN_ALLOW_THREADS;
4232 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4233 MYDB_END_ALLOW_THREADS;
4234 RETURN_IF_ERR();
4235 RETURN_NONE();
4239 static PyObject*
4240 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4242 int err;
4243 char *dir;
4245 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4246 return NULL;
4247 CHECK_ENV_NOT_CLOSED(self);
4249 MYDB_BEGIN_ALLOW_THREADS;
4250 err = self->db_env->set_tmp_dir(self->db_env, dir);
4251 MYDB_END_ALLOW_THREADS;
4252 RETURN_IF_ERR();
4253 RETURN_NONE();
4257 static PyObject*
4258 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4260 int flags = 0;
4261 PyObject* txnobj = NULL;
4262 DB_TXN *txn = NULL;
4263 static char* kwnames[] = { "parent", "flags", NULL };
4265 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4266 &txnobj, &flags))
4267 return NULL;
4269 if (!checkTxnObj(txnobj, &txn))
4270 return NULL;
4271 CHECK_ENV_NOT_CLOSED(self);
4273 return (PyObject*)newDBTxnObject(self, txn, flags);
4277 static PyObject*
4278 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4280 int err, kbyte=0, min=0, flags=0;
4282 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4283 return NULL;
4284 CHECK_ENV_NOT_CLOSED(self);
4286 MYDB_BEGIN_ALLOW_THREADS;
4287 #if (DBVER >= 40)
4288 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4289 #else
4290 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4291 #endif
4292 MYDB_END_ALLOW_THREADS;
4293 RETURN_IF_ERR();
4294 RETURN_NONE();
4298 static PyObject*
4299 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4301 int err, max;
4303 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4304 return NULL;
4305 CHECK_ENV_NOT_CLOSED(self);
4307 err = self->db_env->set_tx_max(self->db_env, max);
4308 RETURN_IF_ERR();
4309 RETURN_NONE();
4313 static PyObject*
4314 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4316 int err;
4317 long stamp;
4318 time_t timestamp;
4320 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4321 return NULL;
4322 CHECK_ENV_NOT_CLOSED(self);
4323 timestamp = (time_t)stamp;
4324 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4325 RETURN_IF_ERR();
4326 RETURN_NONE();
4330 static PyObject*
4331 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4333 int err, atype, flags=0;
4334 int aborted = 0;
4336 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4337 return NULL;
4338 CHECK_ENV_NOT_CLOSED(self);
4340 MYDB_BEGIN_ALLOW_THREADS;
4341 #if (DBVER >= 40)
4342 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4343 #else
4344 err = lock_detect(self->db_env, flags, atype, &aborted);
4345 #endif
4346 MYDB_END_ALLOW_THREADS;
4347 RETURN_IF_ERR();
4348 return PyInt_FromLong(aborted);
4352 static PyObject*
4353 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4355 int flags=0;
4356 int locker, lock_mode;
4357 DBT obj;
4358 PyObject* objobj;
4360 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4361 return NULL;
4364 if (!make_dbt(objobj, &obj))
4365 return NULL;
4367 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4371 static PyObject*
4372 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4374 int err;
4375 u_int32_t theID;
4377 if (!PyArg_ParseTuple(args, ":lock_id"))
4378 return NULL;
4380 CHECK_ENV_NOT_CLOSED(self);
4381 MYDB_BEGIN_ALLOW_THREADS;
4382 #if (DBVER >= 40)
4383 err = self->db_env->lock_id(self->db_env, &theID);
4384 #else
4385 err = lock_id(self->db_env, &theID);
4386 #endif
4387 MYDB_END_ALLOW_THREADS;
4388 RETURN_IF_ERR();
4390 return PyInt_FromLong((long)theID);
4394 static PyObject*
4395 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4397 int err;
4398 DBLockObject* dblockobj;
4400 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4401 return NULL;
4403 CHECK_ENV_NOT_CLOSED(self);
4404 MYDB_BEGIN_ALLOW_THREADS;
4405 #if (DBVER >= 40)
4406 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4407 #else
4408 err = lock_put(self->db_env, &dblockobj->lock);
4409 #endif
4410 MYDB_END_ALLOW_THREADS;
4411 RETURN_IF_ERR();
4412 RETURN_NONE();
4415 #if (DBVER >= 44)
4416 static PyObject*
4417 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4419 int err;
4420 char *file;
4421 u_int32_t flags = 0;
4422 static char* kwnames[] = { "file", "flags", NULL};
4424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4425 &file, &flags))
4426 return NULL;
4427 CHECK_ENV_NOT_CLOSED(self);
4429 MYDB_BEGIN_ALLOW_THREADS;
4430 err = self->db_env->lsn_reset(self->db_env, file, flags);
4431 MYDB_END_ALLOW_THREADS;
4432 RETURN_IF_ERR();
4433 RETURN_NONE();
4435 #endif /* DBVER >= 4.4 */
4437 #if (DBVER >= 40)
4438 static PyObject*
4439 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4441 int err;
4442 DB_LOG_STAT* statp = NULL;
4443 PyObject* d = NULL;
4444 u_int32_t flags = 0;
4446 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4447 return NULL;
4448 CHECK_ENV_NOT_CLOSED(self);
4450 MYDB_BEGIN_ALLOW_THREADS;
4451 err = self->db_env->log_stat(self->db_env, &statp, flags);
4452 MYDB_END_ALLOW_THREADS;
4453 RETURN_IF_ERR();
4455 /* Turn the stat structure into a dictionary */
4456 d = PyDict_New();
4457 if (d == NULL) {
4458 if (statp)
4459 free(statp);
4460 return NULL;
4463 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4465 MAKE_ENTRY(magic);
4466 MAKE_ENTRY(version);
4467 MAKE_ENTRY(mode);
4468 MAKE_ENTRY(lg_bsize);
4469 #if (DBVER >= 44)
4470 MAKE_ENTRY(lg_size);
4471 MAKE_ENTRY(record);
4472 #endif
4473 #if (DBVER <= 40)
4474 MAKE_ENTRY(lg_max);
4475 #endif
4476 MAKE_ENTRY(w_mbytes);
4477 MAKE_ENTRY(w_bytes);
4478 MAKE_ENTRY(wc_mbytes);
4479 MAKE_ENTRY(wc_bytes);
4480 MAKE_ENTRY(wcount);
4481 MAKE_ENTRY(wcount_fill);
4482 #if (DBVER >= 44)
4483 MAKE_ENTRY(rcount);
4484 #endif
4485 MAKE_ENTRY(scount);
4486 MAKE_ENTRY(cur_file);
4487 MAKE_ENTRY(cur_offset);
4488 MAKE_ENTRY(disk_file);
4489 MAKE_ENTRY(disk_offset);
4490 MAKE_ENTRY(maxcommitperflush);
4491 MAKE_ENTRY(mincommitperflush);
4492 MAKE_ENTRY(regsize);
4493 MAKE_ENTRY(region_wait);
4494 MAKE_ENTRY(region_nowait);
4496 #undef MAKE_ENTRY
4497 free(statp);
4498 return d;
4499 } /* DBEnv_log_stat */
4500 #endif /* DBVER >= 4.0 for log_stat method */
4503 static PyObject*
4504 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4506 int err;
4507 DB_LOCK_STAT* sp;
4508 PyObject* d = NULL;
4509 u_int32_t flags = 0;
4511 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4512 return NULL;
4513 CHECK_ENV_NOT_CLOSED(self);
4515 MYDB_BEGIN_ALLOW_THREADS;
4516 #if (DBVER >= 40)
4517 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4518 #else
4519 #if (DBVER >= 33)
4520 err = lock_stat(self->db_env, &sp);
4521 #else
4522 err = lock_stat(self->db_env, &sp, NULL);
4523 #endif
4524 #endif
4525 MYDB_END_ALLOW_THREADS;
4526 RETURN_IF_ERR();
4528 /* Turn the stat structure into a dictionary */
4529 d = PyDict_New();
4530 if (d == NULL) {
4531 free(sp);
4532 return NULL;
4535 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4537 #if (DBVER < 41)
4538 MAKE_ENTRY(lastid);
4539 #endif
4540 MAKE_ENTRY(nmodes);
4541 #if (DBVER >= 32)
4542 MAKE_ENTRY(maxlocks);
4543 MAKE_ENTRY(maxlockers);
4544 MAKE_ENTRY(maxobjects);
4545 MAKE_ENTRY(nlocks);
4546 MAKE_ENTRY(maxnlocks);
4547 #endif
4548 MAKE_ENTRY(nlockers);
4549 MAKE_ENTRY(maxnlockers);
4550 #if (DBVER >= 32)
4551 MAKE_ENTRY(nobjects);
4552 MAKE_ENTRY(maxnobjects);
4553 #endif
4554 MAKE_ENTRY(nrequests);
4555 MAKE_ENTRY(nreleases);
4556 #if (DBVER < 44)
4557 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4558 MAKE_ENTRY(nconflicts);
4559 #else
4560 MAKE_ENTRY(lock_nowait);
4561 MAKE_ENTRY(lock_wait);
4562 #endif
4563 MAKE_ENTRY(ndeadlocks);
4564 MAKE_ENTRY(regsize);
4565 MAKE_ENTRY(region_wait);
4566 MAKE_ENTRY(region_nowait);
4568 #undef MAKE_ENTRY
4569 free(sp);
4570 return d;
4574 static PyObject*
4575 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4577 int flags=0;
4578 int err;
4579 char **log_list = NULL;
4580 PyObject* list;
4581 PyObject* item = NULL;
4583 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4584 return NULL;
4586 CHECK_ENV_NOT_CLOSED(self);
4587 MYDB_BEGIN_ALLOW_THREADS;
4588 #if (DBVER >= 40)
4589 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4590 #elif (DBVER == 33)
4591 err = log_archive(self->db_env, &log_list, flags);
4592 #else
4593 err = log_archive(self->db_env, &log_list, flags, NULL);
4594 #endif
4595 MYDB_END_ALLOW_THREADS;
4596 RETURN_IF_ERR();
4598 list = PyList_New(0);
4599 if (list == NULL) {
4600 if (log_list)
4601 free(log_list);
4602 return NULL;
4605 if (log_list) {
4606 char **log_list_start;
4607 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4608 item = PyString_FromString (*log_list);
4609 if (item == NULL) {
4610 Py_DECREF(list);
4611 list = NULL;
4612 break;
4614 PyList_Append(list, item);
4615 Py_DECREF(item);
4617 free(log_list_start);
4619 return list;
4623 static PyObject*
4624 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4626 int err;
4627 DB_TXN_STAT* sp;
4628 PyObject* d = NULL;
4629 u_int32_t flags=0;
4631 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4632 return NULL;
4633 CHECK_ENV_NOT_CLOSED(self);
4635 MYDB_BEGIN_ALLOW_THREADS;
4636 #if (DBVER >= 40)
4637 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4638 #elif (DBVER == 33)
4639 err = txn_stat(self->db_env, &sp);
4640 #else
4641 err = txn_stat(self->db_env, &sp, NULL);
4642 #endif
4643 MYDB_END_ALLOW_THREADS;
4644 RETURN_IF_ERR();
4646 /* Turn the stat structure into a dictionary */
4647 d = PyDict_New();
4648 if (d == NULL) {
4649 free(sp);
4650 return NULL;
4653 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4654 #define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
4656 MAKE_TIME_T_ENTRY(time_ckp);
4657 MAKE_ENTRY(last_txnid);
4658 MAKE_ENTRY(maxtxns);
4659 MAKE_ENTRY(nactive);
4660 MAKE_ENTRY(maxnactive);
4661 MAKE_ENTRY(nbegins);
4662 MAKE_ENTRY(naborts);
4663 MAKE_ENTRY(ncommits);
4664 MAKE_ENTRY(regsize);
4665 MAKE_ENTRY(region_wait);
4666 MAKE_ENTRY(region_nowait);
4668 #undef MAKE_ENTRY
4669 #undef MAKE_TIME_T_ENTRY
4670 free(sp);
4671 return d;
4675 static PyObject*
4676 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4678 int flags=0;
4679 int oldValue=0;
4681 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4682 return NULL;
4683 CHECK_ENV_NOT_CLOSED(self);
4685 if (self->moduleFlags.getReturnsNone)
4686 ++oldValue;
4687 if (self->moduleFlags.cursorSetReturnsNone)
4688 ++oldValue;
4689 self->moduleFlags.getReturnsNone = (flags >= 1);
4690 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4691 return PyInt_FromLong(oldValue);
4695 /* --------------------------------------------------------------------- */
4696 /* DBTxn methods */
4699 static PyObject*
4700 DBTxn_commit(DBTxnObject* self, PyObject* args)
4702 int flags=0, err;
4703 DB_TXN *txn;
4705 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4706 return NULL;
4708 if (!self->txn) {
4709 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4710 "after txn_commit or txn_abort");
4711 PyErr_SetObject(DBError, t);
4712 Py_DECREF(t);
4713 return NULL;
4715 txn = self->txn;
4716 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4717 MYDB_BEGIN_ALLOW_THREADS;
4718 #if (DBVER >= 40)
4719 err = txn->commit(txn, flags);
4720 #else
4721 err = txn_commit(txn, flags);
4722 #endif
4723 MYDB_END_ALLOW_THREADS;
4724 RETURN_IF_ERR();
4725 RETURN_NONE();
4728 static PyObject*
4729 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4731 #if (DBVER >= 33)
4732 int err;
4733 char* gid=NULL;
4734 int gid_size=0;
4736 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4737 return NULL;
4739 if (gid_size != DB_XIDDATASIZE) {
4740 PyErr_SetString(PyExc_TypeError,
4741 "gid must be DB_XIDDATASIZE bytes long");
4742 return NULL;
4745 if (!self->txn) {
4746 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4747 "after txn_commit or txn_abort");
4748 PyErr_SetObject(DBError, t);
4749 Py_DECREF(t);
4750 return NULL;
4752 MYDB_BEGIN_ALLOW_THREADS;
4753 #if (DBVER >= 40)
4754 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4755 #else
4756 err = txn_prepare(self->txn, (u_int8_t*)gid);
4757 #endif
4758 MYDB_END_ALLOW_THREADS;
4759 RETURN_IF_ERR();
4760 RETURN_NONE();
4761 #else
4762 int err;
4764 if (!PyArg_ParseTuple(args, ":prepare"))
4765 return NULL;
4767 if (!self->txn) {
4768 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4769 "after txn_commit or txn_abort");
4770 PyErr_SetObject(DBError, t);
4771 Py_DECREF(t);
4772 return NULL;
4774 MYDB_BEGIN_ALLOW_THREADS;
4775 err = txn_prepare(self->txn);
4776 MYDB_END_ALLOW_THREADS;
4777 RETURN_IF_ERR();
4778 RETURN_NONE();
4779 #endif
4783 static PyObject*
4784 DBTxn_abort(DBTxnObject* self, PyObject* args)
4786 int err;
4787 DB_TXN *txn;
4789 if (!PyArg_ParseTuple(args, ":abort"))
4790 return NULL;
4792 if (!self->txn) {
4793 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4794 "after txn_commit or txn_abort");
4795 PyErr_SetObject(DBError, t);
4796 Py_DECREF(t);
4797 return NULL;
4799 txn = self->txn;
4800 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4801 MYDB_BEGIN_ALLOW_THREADS;
4802 #if (DBVER >= 40)
4803 err = txn->abort(txn);
4804 #else
4805 err = txn_abort(txn);
4806 #endif
4807 MYDB_END_ALLOW_THREADS;
4808 RETURN_IF_ERR();
4809 RETURN_NONE();
4813 static PyObject*
4814 DBTxn_id(DBTxnObject* self, PyObject* args)
4816 int id;
4818 if (!PyArg_ParseTuple(args, ":id"))
4819 return NULL;
4821 if (!self->txn) {
4822 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4823 "after txn_commit or txn_abort");
4824 PyErr_SetObject(DBError, t);
4825 Py_DECREF(t);
4826 return NULL;
4828 MYDB_BEGIN_ALLOW_THREADS;
4829 #if (DBVER >= 40)
4830 id = self->txn->id(self->txn);
4831 #else
4832 id = txn_id(self->txn);
4833 #endif
4834 MYDB_END_ALLOW_THREADS;
4835 return PyInt_FromLong(id);
4838 #if (DBVER >= 43)
4839 /* --------------------------------------------------------------------- */
4840 /* DBSequence methods */
4843 static PyObject*
4844 DBSequence_close(DBSequenceObject* self, PyObject* args)
4846 int err, flags=0;
4847 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4848 return NULL;
4849 CHECK_SEQUENCE_NOT_CLOSED(self)
4851 MYDB_BEGIN_ALLOW_THREADS
4852 err = self->sequence->close(self->sequence, flags);
4853 self->sequence = NULL;
4854 MYDB_END_ALLOW_THREADS
4856 RETURN_IF_ERR();
4858 RETURN_NONE();
4861 static PyObject*
4862 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4864 int err, flags = 0;
4865 int delta = 1;
4866 db_seq_t value;
4867 PyObject *txnobj = NULL;
4868 DB_TXN *txn = NULL;
4869 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4870 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4871 return NULL;
4872 CHECK_SEQUENCE_NOT_CLOSED(self)
4874 if (!checkTxnObj(txnobj, &txn))
4875 return NULL;
4877 MYDB_BEGIN_ALLOW_THREADS
4878 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4879 MYDB_END_ALLOW_THREADS
4881 RETURN_IF_ERR();
4882 return PyLong_FromLongLong(value);
4886 static PyObject*
4887 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4889 if (!PyArg_ParseTuple(args,":get_dbp"))
4890 return NULL;
4891 CHECK_SEQUENCE_NOT_CLOSED(self)
4892 Py_INCREF(self->mydb);
4893 return (PyObject* )self->mydb;
4896 static PyObject*
4897 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4899 int err;
4900 DBT key;
4901 CHECK_SEQUENCE_NOT_CLOSED(self)
4902 MYDB_BEGIN_ALLOW_THREADS
4903 err = self->sequence->get_key(self->sequence, &key);
4904 MYDB_END_ALLOW_THREADS
4906 RETURN_IF_ERR();
4908 return PyString_FromStringAndSize(key.data, key.size);
4911 static PyObject*
4912 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4914 int err;
4915 db_seq_t value;
4916 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4917 return NULL;
4918 CHECK_SEQUENCE_NOT_CLOSED(self)
4920 MYDB_BEGIN_ALLOW_THREADS
4921 err = self->sequence->initial_value(self->sequence, value);
4922 MYDB_END_ALLOW_THREADS
4924 RETURN_IF_ERR();
4926 RETURN_NONE();
4929 static PyObject*
4930 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4932 int err, flags = 0;
4933 PyObject* keyobj;
4934 PyObject *txnobj = NULL;
4935 DB_TXN *txn = NULL;
4936 DBT key;
4938 static char* kwnames[] = {"key", "txn", "flags", NULL };
4939 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4940 return NULL;
4942 if (!checkTxnObj(txnobj, &txn))
4943 return NULL;
4945 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4946 return NULL;
4948 MYDB_BEGIN_ALLOW_THREADS
4949 err = self->sequence->open(self->sequence, txn, &key, flags);
4950 MYDB_END_ALLOW_THREADS
4952 CLEAR_DBT(key);
4953 RETURN_IF_ERR();
4955 RETURN_NONE();
4958 static PyObject*
4959 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4961 int err, flags = 0;
4962 PyObject *txnobj = NULL;
4963 DB_TXN *txn = NULL;
4965 static char* kwnames[] = {"txn", "flags", NULL };
4966 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4967 return NULL;
4969 if (!checkTxnObj(txnobj, &txn))
4970 return NULL;
4972 CHECK_SEQUENCE_NOT_CLOSED(self)
4974 MYDB_BEGIN_ALLOW_THREADS
4975 err = self->sequence->remove(self->sequence, txn, flags);
4976 MYDB_END_ALLOW_THREADS
4978 RETURN_IF_ERR();
4979 RETURN_NONE();
4982 static PyObject*
4983 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4985 int err, size;
4986 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4987 return NULL;
4988 CHECK_SEQUENCE_NOT_CLOSED(self)
4990 MYDB_BEGIN_ALLOW_THREADS
4991 err = self->sequence->set_cachesize(self->sequence, size);
4992 MYDB_END_ALLOW_THREADS
4994 RETURN_IF_ERR();
4995 RETURN_NONE();
4998 static PyObject*
4999 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5001 int err, size;
5002 if (!PyArg_ParseTuple(args,":get_cachesize"))
5003 return NULL;
5004 CHECK_SEQUENCE_NOT_CLOSED(self)
5006 MYDB_BEGIN_ALLOW_THREADS
5007 err = self->sequence->get_cachesize(self->sequence, &size);
5008 MYDB_END_ALLOW_THREADS
5010 RETURN_IF_ERR();
5011 return PyInt_FromLong(size);
5014 static PyObject*
5015 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5017 int err, flags = 0;
5018 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
5019 return NULL;
5020 CHECK_SEQUENCE_NOT_CLOSED(self)
5022 MYDB_BEGIN_ALLOW_THREADS
5023 err = self->sequence->set_flags(self->sequence, flags);
5024 MYDB_END_ALLOW_THREADS
5026 RETURN_IF_ERR();
5027 RETURN_NONE();
5031 static PyObject*
5032 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5034 unsigned int flags;
5035 int err;
5036 if (!PyArg_ParseTuple(args,":get_flags"))
5037 return NULL;
5038 CHECK_SEQUENCE_NOT_CLOSED(self)
5040 MYDB_BEGIN_ALLOW_THREADS
5041 err = self->sequence->get_flags(self->sequence, &flags);
5042 MYDB_END_ALLOW_THREADS
5044 RETURN_IF_ERR();
5045 return PyInt_FromLong((int)flags);
5048 static PyObject*
5049 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5051 int err;
5052 db_seq_t min, max;
5053 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5054 return NULL;
5055 CHECK_SEQUENCE_NOT_CLOSED(self)
5057 MYDB_BEGIN_ALLOW_THREADS
5058 err = self->sequence->set_range(self->sequence, min, max);
5059 MYDB_END_ALLOW_THREADS
5061 RETURN_IF_ERR();
5062 RETURN_NONE();
5065 static PyObject*
5066 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5068 int err;
5069 db_seq_t min, max;
5070 if (!PyArg_ParseTuple(args,":get_range"))
5071 return NULL;
5072 CHECK_SEQUENCE_NOT_CLOSED(self)
5074 MYDB_BEGIN_ALLOW_THREADS
5075 err = self->sequence->get_range(self->sequence, &min, &max);
5076 MYDB_END_ALLOW_THREADS
5078 RETURN_IF_ERR();
5079 return Py_BuildValue("(LL)", min, max);
5082 static PyObject*
5083 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5085 int err, flags = 0;
5086 DB_SEQUENCE_STAT* sp = NULL;
5087 PyObject* dict_stat;
5088 static char* kwnames[] = {"flags", NULL };
5089 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5090 return NULL;
5091 CHECK_SEQUENCE_NOT_CLOSED(self);
5093 MYDB_BEGIN_ALLOW_THREADS;
5094 err = self->sequence->stat(self->sequence, &sp, flags);
5095 MYDB_END_ALLOW_THREADS;
5096 RETURN_IF_ERR();
5098 if ((dict_stat = PyDict_New()) == NULL) {
5099 free(sp);
5100 return NULL;
5104 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5105 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5107 MAKE_INT_ENTRY(wait);
5108 MAKE_INT_ENTRY(nowait);
5109 MAKE_LONG_LONG_ENTRY(current);
5110 MAKE_LONG_LONG_ENTRY(value);
5111 MAKE_LONG_LONG_ENTRY(last_value);
5112 MAKE_LONG_LONG_ENTRY(min);
5113 MAKE_LONG_LONG_ENTRY(max);
5114 MAKE_INT_ENTRY(cache_size);
5115 MAKE_INT_ENTRY(flags);
5117 #undef MAKE_INT_ENTRY
5118 #undef MAKE_LONG_LONG_ENTRY
5120 free(sp);
5121 return dict_stat;
5123 #endif
5126 /* --------------------------------------------------------------------- */
5127 /* Method definition tables and type objects */
5129 static PyMethodDef DB_methods[] = {
5130 {"append", (PyCFunction)DB_append, METH_VARARGS},
5131 #if (DBVER >= 33)
5132 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5133 #endif
5134 {"close", (PyCFunction)DB_close, METH_VARARGS},
5135 #if (DBVER >= 32)
5136 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5137 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5138 #endif
5139 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5140 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5141 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5142 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5143 #if (DBVER >= 33)
5144 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5145 #endif
5146 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5147 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5148 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5149 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5150 {"join", (PyCFunction)DB_join, METH_VARARGS},
5151 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5152 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5153 {"items", (PyCFunction)DB_items, METH_VARARGS},
5154 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5155 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5156 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5157 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5158 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5159 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5160 #if (DBVER >= 33)
5161 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5162 #endif
5163 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5164 #if (DBVER >= 41)
5165 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5166 #endif
5167 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5168 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5169 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5170 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5171 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5172 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5173 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5174 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5175 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5176 #if (DBVER >= 32)
5177 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5178 #endif
5179 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5180 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5181 #if (DBVER >= 33)
5182 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5183 #endif
5184 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5185 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5186 {"values", (PyCFunction)DB_values, METH_VARARGS},
5187 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5188 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5189 {NULL, NULL} /* sentinel */
5193 static PyMappingMethods DB_mapping = {
5194 DB_length, /*mp_length*/
5195 (binaryfunc)DB_subscript, /*mp_subscript*/
5196 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5200 static PyMethodDef DBCursor_methods[] = {
5201 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5202 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5203 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5204 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5205 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5206 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5207 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5208 #if (DBVER >= 33)
5209 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5210 #endif
5211 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5212 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5213 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5214 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5215 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5216 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5217 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5218 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5219 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5220 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5221 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5222 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5223 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5224 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5225 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5226 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5227 {NULL, NULL} /* sentinel */
5231 static PyMethodDef DBEnv_methods[] = {
5232 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5233 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5234 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5235 #if (DBVER >= 41)
5236 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5237 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5238 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5239 #endif
5240 #if (DBVER >= 40)
5241 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5242 #endif
5243 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5244 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5245 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5246 #if (DBVER >= 32)
5247 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5248 #endif
5249 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5250 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5251 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5252 #if (DBVER >= 33)
5253 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5254 #endif
5255 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5256 #if (DBVER < 45)
5257 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5258 #endif
5259 #if (DBVER >= 32)
5260 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5261 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5262 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5263 #endif
5264 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5265 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5266 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5267 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5268 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5269 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5270 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5271 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5272 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5273 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5274 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5275 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5276 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5277 #if (DBVER >= 40)
5278 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5279 #endif
5280 #if (DBVER >= 44)
5281 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5282 #endif
5283 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5284 {NULL, NULL} /* sentinel */
5288 static PyMethodDef DBTxn_methods[] = {
5289 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5290 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5291 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5292 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5293 {NULL, NULL} /* sentinel */
5297 #if (DBVER >= 43)
5298 static PyMethodDef DBSequence_methods[] = {
5299 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5300 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5301 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5302 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5303 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5304 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5305 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5306 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5307 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5308 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5309 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5310 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5311 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5312 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5313 {NULL, NULL} /* sentinel */
5315 #endif
5318 static PyObject*
5319 DB_getattr(DBObject* self, char *name)
5321 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5325 static PyObject*
5326 DBEnv_getattr(DBEnvObject* self, char *name)
5328 if (!strcmp(name, "db_home")) {
5329 CHECK_ENV_NOT_CLOSED(self);
5330 if (self->db_env->db_home == NULL) {
5331 RETURN_NONE();
5333 return PyString_FromString(self->db_env->db_home);
5336 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5340 static PyObject*
5341 DBCursor_getattr(DBCursorObject* self, char *name)
5343 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5346 static PyObject*
5347 DBTxn_getattr(DBTxnObject* self, char *name)
5349 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5352 static PyObject*
5353 DBLock_getattr(DBLockObject* self, char *name)
5355 return NULL;
5358 #if (DBVER >= 43)
5359 static PyObject*
5360 DBSequence_getattr(DBSequenceObject* self, char *name)
5362 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5364 #endif
5366 statichere PyTypeObject DB_Type = {
5367 PyObject_HEAD_INIT(NULL)
5368 0, /*ob_size*/
5369 "DB", /*tp_name*/
5370 sizeof(DBObject), /*tp_basicsize*/
5371 0, /*tp_itemsize*/
5372 /* methods */
5373 (destructor)DB_dealloc, /*tp_dealloc*/
5374 0, /*tp_print*/
5375 (getattrfunc)DB_getattr, /*tp_getattr*/
5376 0, /*tp_setattr*/
5377 0, /*tp_compare*/
5378 0, /*tp_repr*/
5379 0, /*tp_as_number*/
5380 0, /*tp_as_sequence*/
5381 &DB_mapping,/*tp_as_mapping*/
5382 0, /*tp_hash*/
5383 #ifdef HAVE_WEAKREF
5384 0, /* tp_call */
5385 0, /* tp_str */
5386 0, /* tp_getattro */
5387 0, /* tp_setattro */
5388 0, /* tp_as_buffer */
5389 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5390 0, /* tp_doc */
5391 0, /* tp_traverse */
5392 0, /* tp_clear */
5393 0, /* tp_richcompare */
5394 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5395 #endif
5399 statichere PyTypeObject DBCursor_Type = {
5400 PyObject_HEAD_INIT(NULL)
5401 0, /*ob_size*/
5402 "DBCursor", /*tp_name*/
5403 sizeof(DBCursorObject), /*tp_basicsize*/
5404 0, /*tp_itemsize*/
5405 /* methods */
5406 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5407 0, /*tp_print*/
5408 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5409 0, /*tp_setattr*/
5410 0, /*tp_compare*/
5411 0, /*tp_repr*/
5412 0, /*tp_as_number*/
5413 0, /*tp_as_sequence*/
5414 0, /*tp_as_mapping*/
5415 0, /*tp_hash*/
5416 #ifdef HAVE_WEAKREF
5417 0, /* tp_call */
5418 0, /* tp_str */
5419 0, /* tp_getattro */
5420 0, /* tp_setattro */
5421 0, /* tp_as_buffer */
5422 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5423 0, /* tp_doc */
5424 0, /* tp_traverse */
5425 0, /* tp_clear */
5426 0, /* tp_richcompare */
5427 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5428 #endif
5432 statichere PyTypeObject DBEnv_Type = {
5433 PyObject_HEAD_INIT(NULL)
5434 0, /*ob_size*/
5435 "DBEnv", /*tp_name*/
5436 sizeof(DBEnvObject), /*tp_basicsize*/
5437 0, /*tp_itemsize*/
5438 /* methods */
5439 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5440 0, /*tp_print*/
5441 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5442 0, /*tp_setattr*/
5443 0, /*tp_compare*/
5444 0, /*tp_repr*/
5445 0, /*tp_as_number*/
5446 0, /*tp_as_sequence*/
5447 0, /*tp_as_mapping*/
5448 0, /*tp_hash*/
5449 #ifdef HAVE_WEAKREF
5450 0, /* tp_call */
5451 0, /* tp_str */
5452 0, /* tp_getattro */
5453 0, /* tp_setattro */
5454 0, /* tp_as_buffer */
5455 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5456 0, /* tp_doc */
5457 0, /* tp_traverse */
5458 0, /* tp_clear */
5459 0, /* tp_richcompare */
5460 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5461 #endif
5464 statichere PyTypeObject DBTxn_Type = {
5465 PyObject_HEAD_INIT(NULL)
5466 0, /*ob_size*/
5467 "DBTxn", /*tp_name*/
5468 sizeof(DBTxnObject), /*tp_basicsize*/
5469 0, /*tp_itemsize*/
5470 /* methods */
5471 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5472 0, /*tp_print*/
5473 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5474 0, /*tp_setattr*/
5475 0, /*tp_compare*/
5476 0, /*tp_repr*/
5477 0, /*tp_as_number*/
5478 0, /*tp_as_sequence*/
5479 0, /*tp_as_mapping*/
5480 0, /*tp_hash*/
5481 #ifdef HAVE_WEAKREF
5482 0, /* tp_call */
5483 0, /* tp_str */
5484 0, /* tp_getattro */
5485 0, /* tp_setattro */
5486 0, /* tp_as_buffer */
5487 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5488 0, /* tp_doc */
5489 0, /* tp_traverse */
5490 0, /* tp_clear */
5491 0, /* tp_richcompare */
5492 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5493 #endif
5497 statichere PyTypeObject DBLock_Type = {
5498 PyObject_HEAD_INIT(NULL)
5499 0, /*ob_size*/
5500 "DBLock", /*tp_name*/
5501 sizeof(DBLockObject), /*tp_basicsize*/
5502 0, /*tp_itemsize*/
5503 /* methods */
5504 (destructor)DBLock_dealloc, /*tp_dealloc*/
5505 0, /*tp_print*/
5506 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5507 0, /*tp_setattr*/
5508 0, /*tp_compare*/
5509 0, /*tp_repr*/
5510 0, /*tp_as_number*/
5511 0, /*tp_as_sequence*/
5512 0, /*tp_as_mapping*/
5513 0, /*tp_hash*/
5514 #ifdef HAVE_WEAKREF
5515 0, /* tp_call */
5516 0, /* tp_str */
5517 0, /* tp_getattro */
5518 0, /* tp_setattro */
5519 0, /* tp_as_buffer */
5520 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5521 0, /* tp_doc */
5522 0, /* tp_traverse */
5523 0, /* tp_clear */
5524 0, /* tp_richcompare */
5525 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5526 #endif
5529 #if (DBVER >= 43)
5530 statichere PyTypeObject DBSequence_Type = {
5531 PyObject_HEAD_INIT(NULL)
5532 0, /*ob_size*/
5533 "DBSequence", /*tp_name*/
5534 sizeof(DBSequenceObject), /*tp_basicsize*/
5535 0, /*tp_itemsize*/
5536 /* methods */
5537 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5538 0, /*tp_print*/
5539 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5540 0, /*tp_setattr*/
5541 0, /*tp_compare*/
5542 0, /*tp_repr*/
5543 0, /*tp_as_number*/
5544 0, /*tp_as_sequence*/
5545 0, /*tp_as_mapping*/
5546 0, /*tp_hash*/
5547 #ifdef HAVE_WEAKREF
5548 0, /* tp_call */
5549 0, /* tp_str */
5550 0, /* tp_getattro */
5551 0, /* tp_setattro */
5552 0, /* tp_as_buffer */
5553 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5554 0, /* tp_doc */
5555 0, /* tp_traverse */
5556 0, /* tp_clear */
5557 0, /* tp_richcompare */
5558 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5559 #endif
5561 #endif
5563 /* --------------------------------------------------------------------- */
5564 /* Module-level functions */
5566 static PyObject*
5567 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5569 PyObject* dbenvobj = NULL;
5570 int flags = 0;
5571 static char* kwnames[] = { "dbEnv", "flags", NULL};
5573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5574 &dbenvobj, &flags))
5575 return NULL;
5576 if (dbenvobj == Py_None)
5577 dbenvobj = NULL;
5578 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5579 makeTypeError("DBEnv", dbenvobj);
5580 return NULL;
5583 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5587 static PyObject*
5588 DBEnv_construct(PyObject* self, PyObject* args)
5590 int flags = 0;
5591 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5592 return (PyObject* )newDBEnvObject(flags);
5595 #if (DBVER >= 43)
5596 static PyObject*
5597 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5599 PyObject* dbobj;
5600 int flags = 0;
5601 static char* kwnames[] = { "db", "flags", NULL};
5603 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5604 return NULL;
5605 if (!DBObject_Check(dbobj)) {
5606 makeTypeError("DB", dbobj);
5607 return NULL;
5609 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5611 #endif
5613 static char bsddb_version_doc[] =
5614 "Returns a tuple of major, minor, and patch release numbers of the\n\
5615 underlying DB library.";
5617 static PyObject*
5618 bsddb_version(PyObject* self, PyObject* args)
5620 int major, minor, patch;
5622 if (!PyArg_ParseTuple(args, ":version"))
5623 return NULL;
5624 db_version(&major, &minor, &patch);
5625 return Py_BuildValue("(iii)", major, minor, patch);
5629 /* List of functions defined in the module */
5631 static PyMethodDef bsddb_methods[] = {
5632 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5633 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5634 #if (DBVER >= 43)
5635 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5636 #endif
5637 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5638 {NULL, NULL} /* sentinel */
5642 /* --------------------------------------------------------------------- */
5643 /* Module initialization */
5646 /* Convenience routine to export an integer value.
5647 * Errors are silently ignored, for better or for worse...
5649 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5651 #define MODULE_NAME_MAX_LEN 11
5652 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5654 DL_EXPORT(void) init_bsddb(void)
5656 PyObject* m;
5657 PyObject* d;
5658 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5659 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5660 PyObject* cvsid_s = PyString_FromString( rcs_id );
5662 /* Initialize the type of the new type objects here; doing it here
5663 is required for portability to Windows without requiring C++. */
5664 DB_Type.ob_type = &PyType_Type;
5665 DBCursor_Type.ob_type = &PyType_Type;
5666 DBEnv_Type.ob_type = &PyType_Type;
5667 DBTxn_Type.ob_type = &PyType_Type;
5668 DBLock_Type.ob_type = &PyType_Type;
5669 #if (DBVER >= 43)
5670 DBSequence_Type.ob_type = &PyType_Type;
5671 #endif
5674 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5675 /* Save the current interpreter, so callbacks can do the right thing. */
5676 _db_interpreterState = PyThreadState_GET()->interp;
5677 #endif
5679 /* Create the module and add the functions */
5680 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5681 if (m == NULL)
5682 return;
5684 /* Add some symbolic constants to the module */
5685 d = PyModule_GetDict(m);
5686 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5687 PyDict_SetItemString(d, "cvsid", cvsid_s);
5688 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5689 Py_DECREF(pybsddb_version_s);
5690 pybsddb_version_s = NULL;
5691 Py_DECREF(cvsid_s);
5692 cvsid_s = NULL;
5693 Py_DECREF(db_version_s);
5694 db_version_s = NULL;
5696 ADD_INT(d, DB_VERSION_MAJOR);
5697 ADD_INT(d, DB_VERSION_MINOR);
5698 ADD_INT(d, DB_VERSION_PATCH);
5700 ADD_INT(d, DB_MAX_PAGES);
5701 ADD_INT(d, DB_MAX_RECORDS);
5703 #if (DBVER >= 42)
5704 ADD_INT(d, DB_RPCCLIENT);
5705 #else
5706 ADD_INT(d, DB_CLIENT);
5707 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5708 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5709 #endif
5710 ADD_INT(d, DB_XA_CREATE);
5712 ADD_INT(d, DB_CREATE);
5713 ADD_INT(d, DB_NOMMAP);
5714 ADD_INT(d, DB_THREAD);
5716 ADD_INT(d, DB_FORCE);
5717 ADD_INT(d, DB_INIT_CDB);
5718 ADD_INT(d, DB_INIT_LOCK);
5719 ADD_INT(d, DB_INIT_LOG);
5720 ADD_INT(d, DB_INIT_MPOOL);
5721 ADD_INT(d, DB_INIT_TXN);
5722 #if (DBVER >= 32)
5723 ADD_INT(d, DB_JOINENV);
5724 #endif
5726 ADD_INT(d, DB_RECOVER);
5727 ADD_INT(d, DB_RECOVER_FATAL);
5728 ADD_INT(d, DB_TXN_NOSYNC);
5729 ADD_INT(d, DB_USE_ENVIRON);
5730 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5732 ADD_INT(d, DB_LOCKDOWN);
5733 ADD_INT(d, DB_PRIVATE);
5734 ADD_INT(d, DB_SYSTEM_MEM);
5736 ADD_INT(d, DB_TXN_SYNC);
5737 ADD_INT(d, DB_TXN_NOWAIT);
5739 ADD_INT(d, DB_EXCL);
5740 ADD_INT(d, DB_FCNTL_LOCKING);
5741 ADD_INT(d, DB_ODDFILESIZE);
5742 ADD_INT(d, DB_RDWRMASTER);
5743 ADD_INT(d, DB_RDONLY);
5744 ADD_INT(d, DB_TRUNCATE);
5745 #if (DBVER >= 32)
5746 ADD_INT(d, DB_EXTENT);
5747 ADD_INT(d, DB_CDB_ALLDB);
5748 ADD_INT(d, DB_VERIFY);
5749 #endif
5750 ADD_INT(d, DB_UPGRADE);
5752 ADD_INT(d, DB_AGGRESSIVE);
5753 ADD_INT(d, DB_NOORDERCHK);
5754 ADD_INT(d, DB_ORDERCHKONLY);
5755 ADD_INT(d, DB_PR_PAGE);
5756 #if ! (DBVER >= 33)
5757 ADD_INT(d, DB_VRFY_FLAGMASK);
5758 ADD_INT(d, DB_PR_HEADERS);
5759 #endif
5760 ADD_INT(d, DB_PR_RECOVERYTEST);
5761 ADD_INT(d, DB_SALVAGE);
5763 ADD_INT(d, DB_LOCK_NORUN);
5764 ADD_INT(d, DB_LOCK_DEFAULT);
5765 ADD_INT(d, DB_LOCK_OLDEST);
5766 ADD_INT(d, DB_LOCK_RANDOM);
5767 ADD_INT(d, DB_LOCK_YOUNGEST);
5768 #if (DBVER >= 33)
5769 ADD_INT(d, DB_LOCK_MAXLOCKS);
5770 ADD_INT(d, DB_LOCK_MINLOCKS);
5771 ADD_INT(d, DB_LOCK_MINWRITE);
5772 #endif
5775 #if (DBVER >= 33)
5776 /* docs say to use zero instead */
5777 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5778 #else
5779 ADD_INT(d, DB_LOCK_CONFLICT);
5780 #endif
5782 ADD_INT(d, DB_LOCK_DUMP);
5783 ADD_INT(d, DB_LOCK_GET);
5784 ADD_INT(d, DB_LOCK_INHERIT);
5785 ADD_INT(d, DB_LOCK_PUT);
5786 ADD_INT(d, DB_LOCK_PUT_ALL);
5787 ADD_INT(d, DB_LOCK_PUT_OBJ);
5789 ADD_INT(d, DB_LOCK_NG);
5790 ADD_INT(d, DB_LOCK_READ);
5791 ADD_INT(d, DB_LOCK_WRITE);
5792 ADD_INT(d, DB_LOCK_NOWAIT);
5793 #if (DBVER >= 32)
5794 ADD_INT(d, DB_LOCK_WAIT);
5795 #endif
5796 ADD_INT(d, DB_LOCK_IWRITE);
5797 ADD_INT(d, DB_LOCK_IREAD);
5798 ADD_INT(d, DB_LOCK_IWR);
5799 #if (DBVER >= 33)
5800 #if (DBVER < 44)
5801 ADD_INT(d, DB_LOCK_DIRTY);
5802 #else
5803 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5804 #endif
5805 ADD_INT(d, DB_LOCK_WWRITE);
5806 #endif
5808 ADD_INT(d, DB_LOCK_RECORD);
5809 ADD_INT(d, DB_LOCK_UPGRADE);
5810 #if (DBVER >= 32)
5811 ADD_INT(d, DB_LOCK_SWITCH);
5812 #endif
5813 #if (DBVER >= 33)
5814 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5815 #endif
5817 ADD_INT(d, DB_LOCK_NOWAIT);
5818 ADD_INT(d, DB_LOCK_RECORD);
5819 ADD_INT(d, DB_LOCK_UPGRADE);
5821 #if (DBVER >= 33)
5822 ADD_INT(d, DB_LSTAT_ABORTED);
5823 #if (DBVER < 43)
5824 ADD_INT(d, DB_LSTAT_ERR);
5825 #endif
5826 ADD_INT(d, DB_LSTAT_FREE);
5827 ADD_INT(d, DB_LSTAT_HELD);
5828 #if (DBVER == 33)
5829 ADD_INT(d, DB_LSTAT_NOGRANT);
5830 #endif
5831 ADD_INT(d, DB_LSTAT_PENDING);
5832 ADD_INT(d, DB_LSTAT_WAITING);
5833 #endif
5835 ADD_INT(d, DB_ARCH_ABS);
5836 ADD_INT(d, DB_ARCH_DATA);
5837 ADD_INT(d, DB_ARCH_LOG);
5838 #if (DBVER >= 42)
5839 ADD_INT(d, DB_ARCH_REMOVE);
5840 #endif
5842 ADD_INT(d, DB_BTREE);
5843 ADD_INT(d, DB_HASH);
5844 ADD_INT(d, DB_RECNO);
5845 ADD_INT(d, DB_QUEUE);
5846 ADD_INT(d, DB_UNKNOWN);
5848 ADD_INT(d, DB_DUP);
5849 ADD_INT(d, DB_DUPSORT);
5850 ADD_INT(d, DB_RECNUM);
5851 ADD_INT(d, DB_RENUMBER);
5852 ADD_INT(d, DB_REVSPLITOFF);
5853 ADD_INT(d, DB_SNAPSHOT);
5855 ADD_INT(d, DB_JOIN_NOSORT);
5857 ADD_INT(d, DB_AFTER);
5858 ADD_INT(d, DB_APPEND);
5859 ADD_INT(d, DB_BEFORE);
5860 #if (DBVER < 45)
5861 ADD_INT(d, DB_CACHED_COUNTS);
5862 #endif
5863 #if (DBVER >= 41)
5864 _addIntToDict(d, "DB_CHECKPOINT", 0);
5865 #else
5866 ADD_INT(d, DB_CHECKPOINT);
5867 ADD_INT(d, DB_CURLSN);
5868 #endif
5869 #if ((DBVER >= 33) && (DBVER <= 41))
5870 ADD_INT(d, DB_COMMIT);
5871 #endif
5872 ADD_INT(d, DB_CONSUME);
5873 #if (DBVER >= 32)
5874 ADD_INT(d, DB_CONSUME_WAIT);
5875 #endif
5876 ADD_INT(d, DB_CURRENT);
5877 #if (DBVER >= 33)
5878 ADD_INT(d, DB_FAST_STAT);
5879 #endif
5880 ADD_INT(d, DB_FIRST);
5881 ADD_INT(d, DB_FLUSH);
5882 ADD_INT(d, DB_GET_BOTH);
5883 ADD_INT(d, DB_GET_RECNO);
5884 ADD_INT(d, DB_JOIN_ITEM);
5885 ADD_INT(d, DB_KEYFIRST);
5886 ADD_INT(d, DB_KEYLAST);
5887 ADD_INT(d, DB_LAST);
5888 ADD_INT(d, DB_NEXT);
5889 ADD_INT(d, DB_NEXT_DUP);
5890 ADD_INT(d, DB_NEXT_NODUP);
5891 ADD_INT(d, DB_NODUPDATA);
5892 ADD_INT(d, DB_NOOVERWRITE);
5893 ADD_INT(d, DB_NOSYNC);
5894 ADD_INT(d, DB_POSITION);
5895 ADD_INT(d, DB_PREV);
5896 ADD_INT(d, DB_PREV_NODUP);
5897 #if (DBVER < 45)
5898 ADD_INT(d, DB_RECORDCOUNT);
5899 #endif
5900 ADD_INT(d, DB_SET);
5901 ADD_INT(d, DB_SET_RANGE);
5902 ADD_INT(d, DB_SET_RECNO);
5903 ADD_INT(d, DB_WRITECURSOR);
5905 ADD_INT(d, DB_OPFLAGS_MASK);
5906 ADD_INT(d, DB_RMW);
5907 #if (DBVER >= 33)
5908 ADD_INT(d, DB_DIRTY_READ);
5909 ADD_INT(d, DB_MULTIPLE);
5910 ADD_INT(d, DB_MULTIPLE_KEY);
5911 #endif
5913 #if (DBVER >= 44)
5914 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5915 ADD_INT(d, DB_READ_COMMITTED);
5916 #endif
5918 #if (DBVER >= 33)
5919 ADD_INT(d, DB_DONOTINDEX);
5920 #endif
5922 #if (DBVER >= 41)
5923 _addIntToDict(d, "DB_INCOMPLETE", 0);
5924 #else
5925 ADD_INT(d, DB_INCOMPLETE);
5926 #endif
5927 ADD_INT(d, DB_KEYEMPTY);
5928 ADD_INT(d, DB_KEYEXIST);
5929 ADD_INT(d, DB_LOCK_DEADLOCK);
5930 ADD_INT(d, DB_LOCK_NOTGRANTED);
5931 ADD_INT(d, DB_NOSERVER);
5932 ADD_INT(d, DB_NOSERVER_HOME);
5933 ADD_INT(d, DB_NOSERVER_ID);
5934 ADD_INT(d, DB_NOTFOUND);
5935 ADD_INT(d, DB_OLD_VERSION);
5936 ADD_INT(d, DB_RUNRECOVERY);
5937 ADD_INT(d, DB_VERIFY_BAD);
5938 #if (DBVER >= 33)
5939 ADD_INT(d, DB_PAGE_NOTFOUND);
5940 ADD_INT(d, DB_SECONDARY_BAD);
5941 #endif
5942 #if (DBVER >= 40)
5943 ADD_INT(d, DB_STAT_CLEAR);
5944 ADD_INT(d, DB_REGION_INIT);
5945 ADD_INT(d, DB_NOLOCKING);
5946 ADD_INT(d, DB_YIELDCPU);
5947 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5948 ADD_INT(d, DB_NOPANIC);
5949 #endif
5951 #if (DBVER >= 42)
5952 ADD_INT(d, DB_TIME_NOTGRANTED);
5953 ADD_INT(d, DB_TXN_NOT_DURABLE);
5954 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5955 ADD_INT(d, DB_LOG_AUTOREMOVE);
5956 ADD_INT(d, DB_DIRECT_LOG);
5957 ADD_INT(d, DB_DIRECT_DB);
5958 ADD_INT(d, DB_INIT_REP);
5959 ADD_INT(d, DB_ENCRYPT);
5960 ADD_INT(d, DB_CHKSUM);
5961 #endif
5963 #if (DBVER >= 43)
5964 ADD_INT(d, DB_LOG_INMEMORY);
5965 ADD_INT(d, DB_BUFFER_SMALL);
5966 ADD_INT(d, DB_SEQ_DEC);
5967 ADD_INT(d, DB_SEQ_INC);
5968 ADD_INT(d, DB_SEQ_WRAP);
5969 #endif
5971 #if (DBVER >= 41)
5972 ADD_INT(d, DB_ENCRYPT_AES);
5973 ADD_INT(d, DB_AUTO_COMMIT);
5974 #else
5975 /* allow berkeleydb 4.1 aware apps to run on older versions */
5976 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5977 #endif
5979 ADD_INT(d, EINVAL);
5980 ADD_INT(d, EACCES);
5981 ADD_INT(d, ENOSPC);
5982 ADD_INT(d, ENOMEM);
5983 ADD_INT(d, EAGAIN);
5984 ADD_INT(d, EBUSY);
5985 ADD_INT(d, EEXIST);
5986 ADD_INT(d, ENOENT);
5987 ADD_INT(d, EPERM);
5989 #if (DBVER >= 40)
5990 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5991 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5992 #endif
5994 /* The exception name must be correct for pickled exception *
5995 * objects to unpickle properly. */
5996 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5997 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5998 #else
5999 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
6000 #endif
6002 /* All the rest of the exceptions derive only from DBError */
6003 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
6004 PyDict_SetItemString(d, #name, name)
6006 /* The base exception class is DBError */
6007 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
6008 MAKE_EX(DBError);
6010 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
6011 * from both DBError and KeyError, since the API only supports
6012 * using one base class. */
6013 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
6014 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
6015 "class DBKeyEmptyError(DBError, KeyError): pass",
6016 Py_file_input, d, d);
6017 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
6018 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
6019 PyDict_DelItemString(d, "KeyError");
6022 #if !INCOMPLETE_IS_WARNING
6023 MAKE_EX(DBIncompleteError);
6024 #endif
6025 MAKE_EX(DBCursorClosedError);
6026 MAKE_EX(DBKeyEmptyError);
6027 MAKE_EX(DBKeyExistError);
6028 MAKE_EX(DBLockDeadlockError);
6029 MAKE_EX(DBLockNotGrantedError);
6030 MAKE_EX(DBOldVersionError);
6031 MAKE_EX(DBRunRecoveryError);
6032 MAKE_EX(DBVerifyBadError);
6033 MAKE_EX(DBNoServerError);
6034 MAKE_EX(DBNoServerHomeError);
6035 MAKE_EX(DBNoServerIDError);
6036 #if (DBVER >= 33)
6037 MAKE_EX(DBPageNotFoundError);
6038 MAKE_EX(DBSecondaryBadError);
6039 #endif
6041 MAKE_EX(DBInvalidArgError);
6042 MAKE_EX(DBAccessError);
6043 MAKE_EX(DBNoSpaceError);
6044 MAKE_EX(DBNoMemoryError);
6045 MAKE_EX(DBAgainError);
6046 MAKE_EX(DBBusyError);
6047 MAKE_EX(DBFileExistsError);
6048 MAKE_EX(DBNoSuchFileError);
6049 MAKE_EX(DBPermissionsError);
6051 #undef MAKE_EX
6053 /* Check for errors */
6054 if (PyErr_Occurred()) {
6055 PyErr_Print();
6056 Py_FatalError("can't initialize module _bsddb");
6060 /* allow this module to be named _pybsddb so that it can be installed
6061 * and imported on top of python >= 2.3 that includes its own older
6062 * copy of the library named _bsddb without importing the old version. */
6063 DL_EXPORT(void) init_pybsddb(void)
6065 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6066 init_bsddb();