Bump version
[pytest.git] / Modules / _bsddb.c
bloba88f01fffab290c03a0c87942fe6df5973d73401
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.4.4"
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;
532 switch (err) {
533 case 0: /* successful, no error */ break;
535 #if (DBVER < 41)
536 case DB_INCOMPLETE:
537 #if INCOMPLETE_IS_WARNING
538 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
539 if (_db_errmsg[0]) {
540 strcat(errTxt, " -- ");
541 strcat(errTxt, _db_errmsg);
542 _db_errmsg[0] = 0;
544 #ifdef HAVE_WARNINGS
545 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
546 #else
547 fprintf(stderr, errTxt);
548 fprintf(stderr, "\n");
549 #endif
551 #else /* do an exception instead */
552 errObj = DBIncompleteError;
553 #endif
554 break;
555 #endif /* DBVER < 41 */
557 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
558 case DB_KEYEXIST: errObj = DBKeyExistError; break;
559 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
560 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
561 case DB_NOTFOUND: errObj = DBNotFoundError; break;
562 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
563 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
564 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
565 case DB_NOSERVER: errObj = DBNoServerError; break;
566 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
567 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
568 #if (DBVER >= 33)
569 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
570 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
571 #endif
572 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
574 #if (DBVER >= 43)
575 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
576 case ENOMEM: errObj = PyExc_MemoryError; break;
577 #endif
578 case EINVAL: errObj = DBInvalidArgError; break;
579 case EACCES: errObj = DBAccessError; break;
580 case ENOSPC: errObj = DBNoSpaceError; break;
581 case EAGAIN: errObj = DBAgainError; break;
582 case EBUSY : errObj = DBBusyError; break;
583 case EEXIST: errObj = DBFileExistsError; break;
584 case ENOENT: errObj = DBNoSuchFileError; break;
585 case EPERM : errObj = DBPermissionsError; break;
587 default: errObj = DBError; break;
590 if (errObj != NULL) {
591 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
592 if (_db_errmsg[0]) {
593 strcat(errTxt, " -- ");
594 strcat(errTxt, _db_errmsg);
595 _db_errmsg[0] = 0;
598 errTuple = Py_BuildValue("(is)", err, errTxt);
599 PyErr_SetObject(errObj, errTuple);
600 Py_DECREF(errTuple);
603 return ((errObj != NULL) || exceptionRaised);
608 /* set a type exception */
609 static void makeTypeError(char* expected, PyObject* found)
611 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
612 expected, found->ob_type->tp_name);
616 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
617 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
619 if (txnobj == Py_None || txnobj == NULL) {
620 *txn = NULL;
621 return 1;
623 if (DBTxnObject_Check(txnobj)) {
624 *txn = ((DBTxnObject*)txnobj)->txn;
625 return 1;
627 else
628 makeTypeError("DBTxn", txnobj);
629 return 0;
633 /* Delete a key from a database
634 Returns 0 on success, -1 on an error. */
635 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
637 int err;
639 MYDB_BEGIN_ALLOW_THREADS;
640 err = self->db->del(self->db, txn, key, 0);
641 MYDB_END_ALLOW_THREADS;
642 if (makeDBError(err)) {
643 return -1;
645 self->haveStat = 0;
646 return 0;
650 /* Store a key into a database
651 Returns 0 on success, -1 on an error. */
652 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
654 int err;
656 MYDB_BEGIN_ALLOW_THREADS;
657 err = self->db->put(self->db, txn, key, data, flags);
658 MYDB_END_ALLOW_THREADS;
659 if (makeDBError(err)) {
660 return -1;
662 self->haveStat = 0;
663 return 0;
666 /* Get a key/data pair from a cursor */
667 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
668 PyObject *args, PyObject *kwargs, char *format)
670 int err;
671 PyObject* retval = NULL;
672 DBT key, data;
673 int dlen = -1;
674 int doff = -1;
675 int flags = 0;
676 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
679 &flags, &dlen, &doff))
680 return NULL;
682 CHECK_CURSOR_NOT_CLOSED(self);
684 flags |= extra_flags;
685 CLEAR_DBT(key);
686 CLEAR_DBT(data);
687 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
688 /* Tell BerkeleyDB to malloc the return value (thread safe) */
689 data.flags = DB_DBT_MALLOC;
690 key.flags = DB_DBT_MALLOC;
692 if (!add_partial_dbt(&data, dlen, doff))
693 return NULL;
695 MYDB_BEGIN_ALLOW_THREADS;
696 err = self->dbc->c_get(self->dbc, &key, &data, flags);
697 MYDB_END_ALLOW_THREADS;
699 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
700 && self->mydb->moduleFlags.getReturnsNone) {
701 Py_INCREF(Py_None);
702 retval = Py_None;
704 else if (makeDBError(err)) {
705 retval = NULL;
707 else { /* otherwise, success! */
709 /* if Recno or Queue, return the key as an Int */
710 switch (_DB_get_type(self->mydb)) {
711 case -1:
712 retval = NULL;
713 break;
715 case DB_RECNO:
716 case DB_QUEUE:
717 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
718 data.data, data.size);
719 break;
720 case DB_HASH:
721 case DB_BTREE:
722 default:
723 retval = Py_BuildValue("s#s#", key.data, key.size,
724 data.data, data.size);
725 break;
728 if (!err) {
729 FREE_DBT(key);
730 FREE_DBT(data);
732 return retval;
736 /* add an integer to a dictionary using the given name as a key */
737 static void _addIntToDict(PyObject* dict, char *name, int value)
739 PyObject* v = PyInt_FromLong((long) value);
740 if (!v || PyDict_SetItemString(dict, name, v))
741 PyErr_Clear();
743 Py_XDECREF(v);
745 #if (DBVER >= 43)
746 /* add an db_seq_t to a dictionary using the given name as a key */
747 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
749 PyObject* v = PyLong_FromLongLong(value);
750 if (!v || PyDict_SetItemString(dict, name, v))
751 PyErr_Clear();
753 Py_XDECREF(v);
755 #endif
759 /* --------------------------------------------------------------------- */
760 /* Allocators and deallocators */
762 static DBObject*
763 newDBObject(DBEnvObject* arg, int flags)
765 DBObject* self;
766 DB_ENV* db_env = NULL;
767 int err;
769 self = PyObject_New(DBObject, &DB_Type);
770 if (self == NULL)
771 return NULL;
773 self->haveStat = 0;
774 self->flags = 0;
775 self->setflags = 0;
776 self->myenvobj = NULL;
777 #if (DBVER >= 33)
778 self->associateCallback = NULL;
779 self->btCompareCallback = NULL;
780 self->primaryDBType = 0;
781 #endif
782 #ifdef HAVE_WEAKREF
783 self->in_weakreflist = NULL;
784 #endif
786 /* keep a reference to our python DBEnv object */
787 if (arg) {
788 Py_INCREF(arg);
789 self->myenvobj = arg;
790 db_env = arg->db_env;
793 if (self->myenvobj)
794 self->moduleFlags = self->myenvobj->moduleFlags;
795 else
796 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
797 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
799 MYDB_BEGIN_ALLOW_THREADS;
800 err = db_create(&self->db, db_env, flags);
801 self->db->set_errcall(self->db, _db_errorCallback);
802 #if (DBVER >= 33)
803 self->db->app_private = (void*)self;
804 #endif
805 MYDB_END_ALLOW_THREADS;
806 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
807 * list so that a DBEnv can refuse to close without aborting any open
808 * DBTxns and closing any open DBs first. */
809 if (makeDBError(err)) {
810 if (self->myenvobj) {
811 Py_DECREF(self->myenvobj);
812 self->myenvobj = NULL;
814 PyObject_Del(self);
815 self = NULL;
817 return self;
821 static void
822 DB_dealloc(DBObject* self)
824 if (self->db != NULL) {
825 /* avoid closing a DB when its DBEnv has been closed out from under
826 * it */
827 if (!self->myenvobj ||
828 (self->myenvobj && self->myenvobj->db_env))
830 MYDB_BEGIN_ALLOW_THREADS;
831 self->db->close(self->db, 0);
832 MYDB_END_ALLOW_THREADS;
833 #ifdef HAVE_WARNINGS
834 } else {
835 PyErr_Warn(PyExc_RuntimeWarning,
836 "DB could not be closed in destructor: DBEnv already closed");
837 #endif
839 self->db = NULL;
841 #ifdef HAVE_WEAKREF
842 if (self->in_weakreflist != NULL) {
843 PyObject_ClearWeakRefs((PyObject *) self);
845 #endif
846 if (self->myenvobj) {
847 Py_DECREF(self->myenvobj);
848 self->myenvobj = NULL;
850 #if (DBVER >= 33)
851 if (self->associateCallback != NULL) {
852 Py_DECREF(self->associateCallback);
853 self->associateCallback = NULL;
855 if (self->btCompareCallback != NULL) {
856 Py_DECREF(self->btCompareCallback);
857 self->btCompareCallback = NULL;
859 #endif
860 PyObject_Del(self);
864 static DBCursorObject*
865 newDBCursorObject(DBC* dbc, DBObject* db)
867 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
868 if (self == NULL)
869 return NULL;
871 self->dbc = dbc;
872 self->mydb = db;
873 #ifdef HAVE_WEAKREF
874 self->in_weakreflist = NULL;
875 #endif
876 Py_INCREF(self->mydb);
877 return self;
881 static void
882 DBCursor_dealloc(DBCursorObject* self)
884 int err;
886 #ifdef HAVE_WEAKREF
887 if (self->in_weakreflist != NULL) {
888 PyObject_ClearWeakRefs((PyObject *) self);
890 #endif
892 if (self->dbc != NULL) {
893 MYDB_BEGIN_ALLOW_THREADS;
894 /* If the underlying database has been closed, we don't
895 need to do anything. If the environment has been closed
896 we need to leak, as BerkeleyDB will crash trying to access
897 the environment. There was an exception when the
898 user closed the environment even though there still was
899 a database open. */
900 if (self->mydb->db && self->mydb->myenvobj &&
901 !self->mydb->myenvobj->closed)
902 err = self->dbc->c_close(self->dbc);
903 self->dbc = NULL;
904 MYDB_END_ALLOW_THREADS;
906 Py_XDECREF( self->mydb );
907 PyObject_Del(self);
911 static DBEnvObject*
912 newDBEnvObject(int flags)
914 int err;
915 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
916 if (self == NULL)
917 return NULL;
919 self->closed = 1;
920 self->flags = flags;
921 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
922 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
923 #ifdef HAVE_WEAKREF
924 self->in_weakreflist = NULL;
925 #endif
927 MYDB_BEGIN_ALLOW_THREADS;
928 err = db_env_create(&self->db_env, flags);
929 MYDB_END_ALLOW_THREADS;
930 if (makeDBError(err)) {
931 PyObject_Del(self);
932 self = NULL;
934 else {
935 self->db_env->set_errcall(self->db_env, _db_errorCallback);
937 return self;
941 static void
942 DBEnv_dealloc(DBEnvObject* self)
944 #ifdef HAVE_WEAKREF
945 if (self->in_weakreflist != NULL) {
946 PyObject_ClearWeakRefs((PyObject *) self);
948 #endif
950 if (self->db_env && !self->closed) {
951 MYDB_BEGIN_ALLOW_THREADS;
952 self->db_env->close(self->db_env, 0);
953 MYDB_END_ALLOW_THREADS;
955 PyObject_Del(self);
959 static DBTxnObject*
960 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
962 int err;
963 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
964 if (self == NULL)
965 return NULL;
966 Py_INCREF(myenv);
967 self->env = (PyObject*)myenv;
968 #ifdef HAVE_WEAKREF
969 self->in_weakreflist = NULL;
970 #endif
972 MYDB_BEGIN_ALLOW_THREADS;
973 #if (DBVER >= 40)
974 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
975 #else
976 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
977 #endif
978 MYDB_END_ALLOW_THREADS;
979 if (makeDBError(err)) {
980 Py_DECREF(self->env);
981 PyObject_Del(self);
982 self = NULL;
984 return self;
988 static void
989 DBTxn_dealloc(DBTxnObject* self)
991 #ifdef HAVE_WEAKREF
992 if (self->in_weakreflist != NULL) {
993 PyObject_ClearWeakRefs((PyObject *) self);
995 #endif
997 #ifdef HAVE_WARNINGS
998 if (self->txn) {
999 /* it hasn't been finalized, abort it! */
1000 MYDB_BEGIN_ALLOW_THREADS;
1001 #if (DBVER >= 40)
1002 self->txn->abort(self->txn);
1003 #else
1004 txn_abort(self->txn);
1005 #endif
1006 MYDB_END_ALLOW_THREADS;
1007 PyErr_Warn(PyExc_RuntimeWarning,
1008 "DBTxn aborted in destructor. No prior commit() or abort().");
1010 #endif
1012 Py_DECREF(self->env);
1013 PyObject_Del(self);
1017 static DBLockObject*
1018 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1019 db_lockmode_t lock_mode, int flags)
1021 int err;
1022 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1023 if (self == NULL)
1024 return NULL;
1025 #ifdef HAVE_WEAKREF
1026 self->in_weakreflist = NULL;
1027 #endif
1029 MYDB_BEGIN_ALLOW_THREADS;
1030 #if (DBVER >= 40)
1031 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1032 &self->lock);
1033 #else
1034 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1035 #endif
1036 MYDB_END_ALLOW_THREADS;
1037 if (makeDBError(err)) {
1038 PyObject_Del(self);
1039 self = NULL;
1042 return self;
1046 static void
1047 DBLock_dealloc(DBLockObject* self)
1049 #ifdef HAVE_WEAKREF
1050 if (self->in_weakreflist != NULL) {
1051 PyObject_ClearWeakRefs((PyObject *) self);
1053 #endif
1054 /* TODO: is this lock held? should we release it? */
1056 PyObject_Del(self);
1060 #if (DBVER >= 43)
1061 static DBSequenceObject*
1062 newDBSequenceObject(DBObject* mydb, int flags)
1064 int err;
1065 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1066 if (self == NULL)
1067 return NULL;
1068 Py_INCREF(mydb);
1069 self->mydb = mydb;
1070 #ifdef HAVE_WEAKREF
1071 self->in_weakreflist = NULL;
1072 #endif
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1077 MYDB_END_ALLOW_THREADS;
1078 if (makeDBError(err)) {
1079 Py_DECREF(self->mydb);
1080 PyObject_Del(self);
1081 self = NULL;
1084 return self;
1088 static void
1089 DBSequence_dealloc(DBSequenceObject* self)
1091 #ifdef HAVE_WEAKREF
1092 if (self->in_weakreflist != NULL) {
1093 PyObject_ClearWeakRefs((PyObject *) self);
1095 #endif
1097 Py_DECREF(self->mydb);
1098 PyObject_Del(self);
1100 #endif
1102 /* --------------------------------------------------------------------- */
1103 /* DB methods */
1105 static PyObject*
1106 DB_append(DBObject* self, PyObject* args)
1108 PyObject* txnobj = NULL;
1109 PyObject* dataobj;
1110 db_recno_t recno;
1111 DBT key, data;
1112 DB_TXN *txn = NULL;
1114 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1115 return NULL;
1117 CHECK_DB_NOT_CLOSED(self);
1119 /* make a dummy key out of a recno */
1120 recno = 0;
1121 CLEAR_DBT(key);
1122 key.data = &recno;
1123 key.size = sizeof(recno);
1124 key.ulen = key.size;
1125 key.flags = DB_DBT_USERMEM;
1127 if (!make_dbt(dataobj, &data)) return NULL;
1128 if (!checkTxnObj(txnobj, &txn)) return NULL;
1130 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1131 return NULL;
1133 return PyInt_FromLong(recno);
1137 #if (DBVER >= 33)
1139 static int
1140 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1141 DBT* secKey)
1143 int retval = DB_DONOTINDEX;
1144 DBObject* secondaryDB = (DBObject*)db->app_private;
1145 PyObject* callback = secondaryDB->associateCallback;
1146 int type = secondaryDB->primaryDBType;
1147 PyObject* args;
1148 PyObject* result = NULL;
1151 if (callback != NULL) {
1152 MYDB_BEGIN_BLOCK_THREADS;
1154 if (type == DB_RECNO || type == DB_QUEUE)
1155 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1156 priData->data, priData->size);
1157 else
1158 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1159 priData->data, priData->size);
1160 if (args != NULL) {
1161 result = PyEval_CallObject(callback, args);
1163 if (args == NULL || result == NULL) {
1164 PyErr_Print();
1166 else if (result == Py_None) {
1167 retval = DB_DONOTINDEX;
1169 else if (PyInt_Check(result)) {
1170 retval = PyInt_AsLong(result);
1172 else if (PyString_Check(result)) {
1173 char* data;
1174 Py_ssize_t size;
1176 CLEAR_DBT(*secKey);
1177 #if PYTHON_API_VERSION <= 1007
1178 /* 1.5 compatibility */
1179 size = PyString_Size(result);
1180 data = PyString_AsString(result);
1181 #else
1182 PyString_AsStringAndSize(result, &data, &size);
1183 #endif
1184 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1185 secKey->data = malloc(size); /* TODO, check this */
1186 if (secKey->data) {
1187 memcpy(secKey->data, data, size);
1188 secKey->size = size;
1189 retval = 0;
1191 else {
1192 PyErr_SetString(PyExc_MemoryError,
1193 "malloc failed in _db_associateCallback");
1194 PyErr_Print();
1197 else {
1198 PyErr_SetString(
1199 PyExc_TypeError,
1200 "DB associate callback should return DB_DONOTINDEX or string.");
1201 PyErr_Print();
1204 Py_XDECREF(args);
1205 Py_XDECREF(result);
1207 MYDB_END_BLOCK_THREADS;
1209 return retval;
1213 static PyObject*
1214 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1216 int err, flags=0;
1217 DBObject* secondaryDB;
1218 PyObject* callback;
1219 #if (DBVER >= 41)
1220 PyObject *txnobj = NULL;
1221 DB_TXN *txn = NULL;
1222 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1223 NULL};
1224 #else
1225 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1226 #endif
1228 #if (DBVER >= 41)
1229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1230 &secondaryDB, &callback, &flags,
1231 &txnobj)) {
1232 #else
1233 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1234 &secondaryDB, &callback, &flags)) {
1235 #endif
1236 return NULL;
1239 #if (DBVER >= 41)
1240 if (!checkTxnObj(txnobj, &txn)) return NULL;
1241 #endif
1243 CHECK_DB_NOT_CLOSED(self);
1244 if (!DBObject_Check(secondaryDB)) {
1245 makeTypeError("DB", (PyObject*)secondaryDB);
1246 return NULL;
1248 CHECK_DB_NOT_CLOSED(secondaryDB);
1249 if (callback == Py_None) {
1250 callback = NULL;
1252 else if (!PyCallable_Check(callback)) {
1253 makeTypeError("Callable", callback);
1254 return NULL;
1257 /* Save a reference to the callback in the secondary DB. */
1258 Py_XDECREF(secondaryDB->associateCallback);
1259 Py_XINCREF(callback);
1260 secondaryDB->associateCallback = callback;
1261 secondaryDB->primaryDBType = _DB_get_type(self);
1263 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1264 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1265 * The global interepreter lock is not initialized until the first
1266 * thread is created using thread.start_new_thread() or fork() is
1267 * called. that would cause the ALLOW_THREADS here to segfault due
1268 * to a null pointer reference if no threads or child processes
1269 * have been created. This works around that and is a no-op if
1270 * threads have already been initialized.
1271 * (see pybsddb-users mailing list post on 2002-08-07)
1273 #ifdef WITH_THREAD
1274 PyEval_InitThreads();
1275 #endif
1276 MYDB_BEGIN_ALLOW_THREADS;
1277 #if (DBVER >= 41)
1278 err = self->db->associate(self->db,
1279 txn,
1280 secondaryDB->db,
1281 _db_associateCallback,
1282 flags);
1283 #else
1284 err = self->db->associate(self->db,
1285 secondaryDB->db,
1286 _db_associateCallback,
1287 flags);
1288 #endif
1289 MYDB_END_ALLOW_THREADS;
1291 if (err) {
1292 Py_XDECREF(secondaryDB->associateCallback);
1293 secondaryDB->associateCallback = NULL;
1294 secondaryDB->primaryDBType = 0;
1297 RETURN_IF_ERR();
1298 RETURN_NONE();
1302 #endif
1305 static PyObject*
1306 DB_close(DBObject* self, PyObject* args)
1308 int err, flags=0;
1309 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1310 return NULL;
1311 if (self->db != NULL) {
1312 if (self->myenvobj)
1313 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1314 err = self->db->close(self->db, flags);
1315 self->db = NULL;
1316 RETURN_IF_ERR();
1318 RETURN_NONE();
1322 #if (DBVER >= 32)
1323 static PyObject*
1324 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1326 int err, flags=0, type;
1327 PyObject* txnobj = NULL;
1328 PyObject* retval = NULL;
1329 DBT key, data;
1330 DB_TXN *txn = NULL;
1331 static char* kwnames[] = { "txn", "flags", NULL };
1333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1334 &txnobj, &flags))
1335 return NULL;
1337 CHECK_DB_NOT_CLOSED(self);
1338 type = _DB_get_type(self);
1339 if (type == -1)
1340 return NULL;
1341 if (type != DB_QUEUE) {
1342 PyErr_SetString(PyExc_TypeError,
1343 "Consume methods only allowed for Queue DB's");
1344 return NULL;
1346 if (!checkTxnObj(txnobj, &txn))
1347 return NULL;
1349 CLEAR_DBT(key);
1350 CLEAR_DBT(data);
1351 if (CHECK_DBFLAG(self, DB_THREAD)) {
1352 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1353 data.flags = DB_DBT_MALLOC;
1354 key.flags = DB_DBT_MALLOC;
1357 MYDB_BEGIN_ALLOW_THREADS;
1358 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1359 MYDB_END_ALLOW_THREADS;
1361 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1362 && self->moduleFlags.getReturnsNone) {
1363 err = 0;
1364 Py_INCREF(Py_None);
1365 retval = Py_None;
1367 else if (!err) {
1368 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1369 data.size);
1370 FREE_DBT(key);
1371 FREE_DBT(data);
1374 RETURN_IF_ERR();
1375 return retval;
1378 static PyObject*
1379 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1381 return _DB_consume(self, args, kwargs, DB_CONSUME);
1384 static PyObject*
1385 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1386 int consume_flag)
1388 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1390 #endif
1394 static PyObject*
1395 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1397 int err, flags=0;
1398 DBC* dbc;
1399 PyObject* txnobj = NULL;
1400 DB_TXN *txn = NULL;
1401 static char* kwnames[] = { "txn", "flags", NULL };
1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1404 &txnobj, &flags))
1405 return NULL;
1406 CHECK_DB_NOT_CLOSED(self);
1407 if (!checkTxnObj(txnobj, &txn))
1408 return NULL;
1410 MYDB_BEGIN_ALLOW_THREADS;
1411 err = self->db->cursor(self->db, txn, &dbc, flags);
1412 MYDB_END_ALLOW_THREADS;
1413 RETURN_IF_ERR();
1414 return (PyObject*) newDBCursorObject(dbc, self);
1418 static PyObject*
1419 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1421 PyObject* txnobj = NULL;
1422 int flags = 0;
1423 PyObject* keyobj;
1424 DBT key;
1425 DB_TXN *txn = NULL;
1426 static char* kwnames[] = { "key", "txn", "flags", NULL };
1428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1429 &keyobj, &txnobj, &flags))
1430 return NULL;
1431 CHECK_DB_NOT_CLOSED(self);
1432 if (!make_key_dbt(self, keyobj, &key, NULL))
1433 return NULL;
1434 if (!checkTxnObj(txnobj, &txn)) {
1435 FREE_DBT(key);
1436 return NULL;
1439 if (-1 == _DB_delete(self, txn, &key, 0)) {
1440 FREE_DBT(key);
1441 return NULL;
1444 FREE_DBT(key);
1445 RETURN_NONE();
1449 static PyObject*
1450 DB_fd(DBObject* self, PyObject* args)
1452 int err, the_fd;
1454 if (!PyArg_ParseTuple(args,":fd"))
1455 return NULL;
1456 CHECK_DB_NOT_CLOSED(self);
1458 MYDB_BEGIN_ALLOW_THREADS;
1459 err = self->db->fd(self->db, &the_fd);
1460 MYDB_END_ALLOW_THREADS;
1461 RETURN_IF_ERR();
1462 return PyInt_FromLong(the_fd);
1466 static PyObject*
1467 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1469 int err, flags=0;
1470 PyObject* txnobj = NULL;
1471 PyObject* keyobj;
1472 PyObject* dfltobj = NULL;
1473 PyObject* retval = NULL;
1474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, data;
1477 DB_TXN *txn = NULL;
1478 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1479 "doff", NULL};
1481 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1482 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1483 &doff))
1484 return NULL;
1486 CHECK_DB_NOT_CLOSED(self);
1487 if (!make_key_dbt(self, keyobj, &key, &flags))
1488 return NULL;
1489 if (!checkTxnObj(txnobj, &txn)) {
1490 FREE_DBT(key);
1491 return NULL;
1494 CLEAR_DBT(data);
1495 if (CHECK_DBFLAG(self, DB_THREAD)) {
1496 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1497 data.flags = DB_DBT_MALLOC;
1499 if (!add_partial_dbt(&data, dlen, doff)) {
1500 FREE_DBT(key);
1501 return NULL;
1504 MYDB_BEGIN_ALLOW_THREADS;
1505 err = self->db->get(self->db, txn, &key, &data, flags);
1506 MYDB_END_ALLOW_THREADS;
1508 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1509 err = 0;
1510 Py_INCREF(dfltobj);
1511 retval = dfltobj;
1513 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1514 && self->moduleFlags.getReturnsNone) {
1515 err = 0;
1516 Py_INCREF(Py_None);
1517 retval = Py_None;
1519 else if (!err) {
1520 if (flags & DB_SET_RECNO) /* return both key and data */
1521 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1522 data.size);
1523 else /* return just the data */
1524 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1525 FREE_DBT(data);
1527 FREE_DBT(key);
1529 RETURN_IF_ERR();
1530 return retval;
1533 #if (DBVER >= 33)
1534 static PyObject*
1535 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1537 int err, flags=0;
1538 PyObject* txnobj = NULL;
1539 PyObject* keyobj;
1540 PyObject* dfltobj = NULL;
1541 PyObject* retval = NULL;
1542 int dlen = -1;
1543 int doff = -1;
1544 DBT key, pkey, data;
1545 DB_TXN *txn = NULL;
1546 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1547 "doff", NULL};
1549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1550 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1551 &doff))
1552 return NULL;
1554 CHECK_DB_NOT_CLOSED(self);
1555 if (!make_key_dbt(self, keyobj, &key, &flags))
1556 return NULL;
1557 if (!checkTxnObj(txnobj, &txn)) {
1558 FREE_DBT(key);
1559 return NULL;
1562 CLEAR_DBT(data);
1563 if (CHECK_DBFLAG(self, DB_THREAD)) {
1564 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1565 data.flags = DB_DBT_MALLOC;
1567 if (!add_partial_dbt(&data, dlen, doff)) {
1568 FREE_DBT(key);
1569 return NULL;
1572 CLEAR_DBT(pkey);
1573 pkey.flags = DB_DBT_MALLOC;
1575 MYDB_BEGIN_ALLOW_THREADS;
1576 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1577 MYDB_END_ALLOW_THREADS;
1579 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1580 err = 0;
1581 Py_INCREF(dfltobj);
1582 retval = dfltobj;
1584 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1585 && self->moduleFlags.getReturnsNone) {
1586 err = 0;
1587 Py_INCREF(Py_None);
1588 retval = Py_None;
1590 else if (!err) {
1591 PyObject *pkeyObj;
1592 PyObject *dataObj;
1593 dataObj = PyString_FromStringAndSize(data.data, data.size);
1595 if (self->primaryDBType == DB_RECNO ||
1596 self->primaryDBType == DB_QUEUE)
1597 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1598 else
1599 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1601 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1603 PyObject *keyObj;
1604 int type = _DB_get_type(self);
1605 if (type == DB_RECNO || type == DB_QUEUE)
1606 keyObj = PyInt_FromLong(*(int *)key.data);
1607 else
1608 keyObj = PyString_FromStringAndSize(key.data, key.size);
1609 #if (PY_VERSION_HEX >= 0x02040000)
1610 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1611 #else
1612 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1613 #endif
1614 Py_DECREF(keyObj);
1616 else /* return just the pkey and data */
1618 #if (PY_VERSION_HEX >= 0x02040000)
1619 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1620 #else
1621 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1622 #endif
1624 Py_DECREF(dataObj);
1625 Py_DECREF(pkeyObj);
1626 FREE_DBT(pkey);
1627 FREE_DBT(data);
1629 FREE_DBT(key);
1631 RETURN_IF_ERR();
1632 return retval;
1634 #endif
1637 /* Return size of entry */
1638 static PyObject*
1639 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1641 int err, flags=0;
1642 PyObject* txnobj = NULL;
1643 PyObject* keyobj;
1644 PyObject* retval = NULL;
1645 DBT key, data;
1646 DB_TXN *txn = NULL;
1647 static char* kwnames[] = { "key", "txn", NULL };
1649 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1650 &keyobj, &txnobj))
1651 return NULL;
1652 CHECK_DB_NOT_CLOSED(self);
1653 if (!make_key_dbt(self, keyobj, &key, &flags))
1654 return NULL;
1655 if (!checkTxnObj(txnobj, &txn)) {
1656 FREE_DBT(key);
1657 return NULL;
1659 CLEAR_DBT(data);
1661 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1662 thus getting the record size. */
1663 data.flags = DB_DBT_USERMEM;
1664 data.ulen = 0;
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->get(self->db, txn, &key, &data, flags);
1667 MYDB_END_ALLOW_THREADS;
1668 if (err == DB_BUFFER_SMALL) {
1669 retval = PyInt_FromLong((long)data.size);
1670 err = 0;
1673 FREE_DBT(key);
1674 FREE_DBT(data);
1675 RETURN_IF_ERR();
1676 return retval;
1680 static PyObject*
1681 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1683 int err, flags=0;
1684 PyObject* txnobj = NULL;
1685 PyObject* keyobj;
1686 PyObject* dataobj;
1687 PyObject* retval = NULL;
1688 DBT key, data;
1689 DB_TXN *txn = NULL;
1690 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1693 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1694 &keyobj, &dataobj, &txnobj, &flags))
1695 return NULL;
1697 CHECK_DB_NOT_CLOSED(self);
1698 if (!make_key_dbt(self, keyobj, &key, NULL))
1699 return NULL;
1700 if ( !make_dbt(dataobj, &data) ||
1701 !checkTxnObj(txnobj, &txn) )
1703 FREE_DBT(key);
1704 return NULL;
1707 flags |= DB_GET_BOTH;
1709 if (CHECK_DBFLAG(self, DB_THREAD)) {
1710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1711 data.flags = DB_DBT_MALLOC;
1712 /* TODO: Is this flag needed? We're passing a data object that should
1713 match what's in the DB, so there should be no need to malloc.
1714 We run the risk of freeing something twice! Check this. */
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->get(self->db, txn, &key, &data, flags);
1719 MYDB_END_ALLOW_THREADS;
1721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1722 && self->moduleFlags.getReturnsNone) {
1723 err = 0;
1724 Py_INCREF(Py_None);
1725 retval = Py_None;
1727 else if (!err) {
1728 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1729 FREE_DBT(data); /* Only if retrieval was successful */
1732 FREE_DBT(key);
1733 RETURN_IF_ERR();
1734 return retval;
1738 static PyObject*
1739 DB_get_byteswapped(DBObject* self, PyObject* args)
1741 #if (DBVER >= 33)
1742 int err = 0;
1743 #endif
1744 int retval = -1;
1746 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1747 return NULL;
1748 CHECK_DB_NOT_CLOSED(self);
1750 #if (DBVER >= 33)
1751 MYDB_BEGIN_ALLOW_THREADS;
1752 err = self->db->get_byteswapped(self->db, &retval);
1753 MYDB_END_ALLOW_THREADS;
1754 RETURN_IF_ERR();
1755 #else
1756 MYDB_BEGIN_ALLOW_THREADS;
1757 retval = self->db->get_byteswapped(self->db);
1758 MYDB_END_ALLOW_THREADS;
1759 #endif
1760 return PyInt_FromLong(retval);
1764 static PyObject*
1765 DB_get_type(DBObject* self, PyObject* args)
1767 int type;
1769 if (!PyArg_ParseTuple(args,":get_type"))
1770 return NULL;
1771 CHECK_DB_NOT_CLOSED(self);
1773 MYDB_BEGIN_ALLOW_THREADS;
1774 type = _DB_get_type(self);
1775 MYDB_END_ALLOW_THREADS;
1776 if (type == -1)
1777 return NULL;
1778 return PyInt_FromLong(type);
1782 static PyObject*
1783 DB_join(DBObject* self, PyObject* args)
1785 int err, flags=0;
1786 int length, x;
1787 PyObject* cursorsObj;
1788 DBC** cursors;
1789 DBC* dbc;
1792 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1793 return NULL;
1795 CHECK_DB_NOT_CLOSED(self);
1797 if (!PySequence_Check(cursorsObj)) {
1798 PyErr_SetString(PyExc_TypeError,
1799 "Sequence of DBCursor objects expected");
1800 return NULL;
1803 length = PyObject_Length(cursorsObj);
1804 cursors = malloc((length+1) * sizeof(DBC*));
1805 cursors[length] = NULL;
1806 for (x=0; x<length; x++) {
1807 PyObject* item = PySequence_GetItem(cursorsObj, x);
1808 if (item == NULL) {
1809 free(cursors);
1810 return NULL;
1812 if (!DBCursorObject_Check(item)) {
1813 PyErr_SetString(PyExc_TypeError,
1814 "Sequence of DBCursor objects expected");
1815 free(cursors);
1816 return NULL;
1818 cursors[x] = ((DBCursorObject*)item)->dbc;
1819 Py_DECREF(item);
1822 MYDB_BEGIN_ALLOW_THREADS;
1823 err = self->db->join(self->db, cursors, &dbc, flags);
1824 MYDB_END_ALLOW_THREADS;
1825 free(cursors);
1826 RETURN_IF_ERR();
1828 /* FIXME: this is a buggy interface. The returned cursor
1829 contains internal references to the passed in cursors
1830 but does not hold python references to them or prevent
1831 them from being closed prematurely. This can cause
1832 python to crash when things are done in the wrong order. */
1833 return (PyObject*) newDBCursorObject(dbc, self);
1837 static PyObject*
1838 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1840 int err, flags=0;
1841 PyObject* txnobj = NULL;
1842 PyObject* keyobj;
1843 DBT key;
1844 DB_TXN *txn = NULL;
1845 DB_KEY_RANGE range;
1846 static char* kwnames[] = { "key", "txn", "flags", NULL };
1848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1849 &keyobj, &txnobj, &flags))
1850 return NULL;
1851 CHECK_DB_NOT_CLOSED(self);
1852 if (!make_dbt(keyobj, &key))
1853 /* BTree only, don't need to allow for an int key */
1854 return NULL;
1855 if (!checkTxnObj(txnobj, &txn))
1856 return NULL;
1858 MYDB_BEGIN_ALLOW_THREADS;
1859 err = self->db->key_range(self->db, txn, &key, &range, flags);
1860 MYDB_END_ALLOW_THREADS;
1862 RETURN_IF_ERR();
1863 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1867 static PyObject*
1868 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1870 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1871 char* filename = NULL;
1872 char* dbname = NULL;
1873 #if (DBVER >= 41)
1874 PyObject *txnobj = NULL;
1875 DB_TXN *txn = NULL;
1876 /* with dbname */
1877 static char* kwnames[] = {
1878 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1879 /* without dbname */
1880 static char* kwnames_basic[] = {
1881 "filename", "dbtype", "flags", "mode", "txn", NULL};
1882 #else
1883 /* with dbname */
1884 static char* kwnames[] = {
1885 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1886 /* without dbname */
1887 static char* kwnames_basic[] = {
1888 "filename", "dbtype", "flags", "mode", NULL};
1889 #endif
1891 #if (DBVER >= 41)
1892 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1893 &filename, &dbname, &type, &flags, &mode,
1894 &txnobj))
1895 #else
1896 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1897 &filename, &dbname, &type, &flags,
1898 &mode))
1899 #endif
1901 PyErr_Clear();
1902 type = DB_UNKNOWN; flags = 0; mode = 0660;
1903 filename = NULL; dbname = NULL;
1904 #if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1906 kwnames_basic,
1907 &filename, &type, &flags, &mode,
1908 &txnobj))
1909 return NULL;
1910 #else
1911 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1912 kwnames_basic,
1913 &filename, &type, &flags, &mode))
1914 return NULL;
1915 #endif
1918 #if (DBVER >= 41)
1919 if (!checkTxnObj(txnobj, &txn)) return NULL;
1920 #endif
1922 if (NULL == self->db) {
1923 PyObject *t = Py_BuildValue("(is)", 0,
1924 "Cannot call open() twice for DB object");
1925 PyErr_SetObject(DBError, t);
1926 Py_DECREF(t);
1927 return NULL;
1930 #if 0 && (DBVER >= 41)
1931 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1932 && (self->myenvobj->flags & DB_INIT_TXN))
1934 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1935 * explicitly passed) but we are in a transaction ready environment:
1936 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1937 * to work on BerkeleyDB 4.1 without needing to modify their
1938 * DBEnv or DB open calls.
1939 * TODO make this behaviour of the library configurable.
1941 flags |= DB_AUTO_COMMIT;
1943 #endif
1945 MYDB_BEGIN_ALLOW_THREADS;
1946 #if (DBVER >= 41)
1947 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1948 #else
1949 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1950 #endif
1951 MYDB_END_ALLOW_THREADS;
1952 if (makeDBError(err)) {
1953 self->db->close(self->db, 0);
1954 self->db = NULL;
1955 return NULL;
1958 self->flags = flags;
1959 RETURN_NONE();
1963 static PyObject*
1964 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1966 int flags=0;
1967 PyObject* txnobj = NULL;
1968 int dlen = -1;
1969 int doff = -1;
1970 PyObject* keyobj, *dataobj, *retval;
1971 DBT key, data;
1972 DB_TXN *txn = NULL;
1973 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1974 "doff", NULL };
1976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1977 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1978 return NULL;
1980 CHECK_DB_NOT_CLOSED(self);
1981 if (!make_key_dbt(self, keyobj, &key, NULL))
1982 return NULL;
1983 if ( !make_dbt(dataobj, &data) ||
1984 !add_partial_dbt(&data, dlen, doff) ||
1985 !checkTxnObj(txnobj, &txn) )
1987 FREE_DBT(key);
1988 return NULL;
1991 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1992 FREE_DBT(key);
1993 return NULL;
1996 if (flags & DB_APPEND)
1997 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1998 else {
1999 retval = Py_None;
2000 Py_INCREF(retval);
2002 FREE_DBT(key);
2003 return retval;
2008 static PyObject*
2009 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2011 char* filename;
2012 char* database = NULL;
2013 int err, flags=0;
2014 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2017 &filename, &database, &flags))
2018 return NULL;
2019 CHECK_DB_NOT_CLOSED(self);
2021 err = self->db->remove(self->db, filename, database, flags);
2022 self->db = NULL;
2023 RETURN_IF_ERR();
2024 RETURN_NONE();
2029 static PyObject*
2030 DB_rename(DBObject* self, PyObject* args)
2032 char* filename;
2033 char* database;
2034 char* newname;
2035 int err, flags=0;
2037 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2038 &flags))
2039 return NULL;
2040 CHECK_DB_NOT_CLOSED(self);
2042 MYDB_BEGIN_ALLOW_THREADS;
2043 err = self->db->rename(self->db, filename, database, newname, flags);
2044 MYDB_END_ALLOW_THREADS;
2045 RETURN_IF_ERR();
2046 RETURN_NONE();
2050 static PyObject*
2051 DB_set_bt_minkey(DBObject* self, PyObject* args)
2053 int err, minkey;
2055 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2056 return NULL;
2057 CHECK_DB_NOT_CLOSED(self);
2059 MYDB_BEGIN_ALLOW_THREADS;
2060 err = self->db->set_bt_minkey(self->db, minkey);
2061 MYDB_END_ALLOW_THREADS;
2062 RETURN_IF_ERR();
2063 RETURN_NONE();
2066 #if (DBVER >= 33)
2067 static int
2068 _default_cmp(const DBT *leftKey,
2069 const DBT *rightKey)
2071 int res;
2072 int lsize = leftKey->size, rsize = rightKey->size;
2074 res = memcmp(leftKey->data, rightKey->data,
2075 lsize < rsize ? lsize : rsize);
2077 if (res == 0) {
2078 if (lsize < rsize) {
2079 res = -1;
2081 else if (lsize > rsize) {
2082 res = 1;
2085 return res;
2088 static int
2089 _db_compareCallback(DB* db,
2090 const DBT *leftKey,
2091 const DBT *rightKey)
2093 int res = 0;
2094 PyObject *args;
2095 PyObject *result = NULL;
2096 DBObject *self = (DBObject *)db->app_private;
2098 if (self == NULL || self->btCompareCallback == NULL) {
2099 MYDB_BEGIN_BLOCK_THREADS;
2100 PyErr_SetString(PyExc_TypeError,
2101 (self == 0
2102 ? "DB_bt_compare db is NULL."
2103 : "DB_bt_compare callback is NULL."));
2104 /* we're in a callback within the DB code, we can't raise */
2105 PyErr_Print();
2106 res = _default_cmp(leftKey, rightKey);
2107 MYDB_END_BLOCK_THREADS;
2108 } else {
2109 MYDB_BEGIN_BLOCK_THREADS;
2111 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2112 rightKey->data, rightKey->size);
2113 if (args != NULL) {
2114 /* XXX(twouters) I highly doubt this INCREF is correct */
2115 Py_INCREF(self);
2116 result = PyEval_CallObject(self->btCompareCallback, args);
2118 if (args == NULL || result == NULL) {
2119 /* we're in a callback within the DB code, we can't raise */
2120 PyErr_Print();
2121 res = _default_cmp(leftKey, rightKey);
2122 } else if (PyInt_Check(result)) {
2123 res = PyInt_AsLong(result);
2124 } else {
2125 PyErr_SetString(PyExc_TypeError,
2126 "DB_bt_compare callback MUST return an int.");
2127 /* we're in a callback within the DB code, we can't raise */
2128 PyErr_Print();
2129 res = _default_cmp(leftKey, rightKey);
2132 Py_XDECREF(args);
2133 Py_XDECREF(result);
2135 MYDB_END_BLOCK_THREADS;
2137 return res;
2140 static PyObject*
2141 DB_set_bt_compare(DBObject* self, PyObject* args)
2143 int err;
2144 PyObject *comparator;
2145 PyObject *tuple, *result;
2147 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2148 return NULL;
2150 CHECK_DB_NOT_CLOSED(self);
2152 if (!PyCallable_Check(comparator)) {
2153 makeTypeError("Callable", comparator);
2154 return NULL;
2158 * Perform a test call of the comparator function with two empty
2159 * string objects here. verify that it returns an int (0).
2160 * err if not.
2162 tuple = Py_BuildValue("(ss)", "", "");
2163 result = PyEval_CallObject(comparator, tuple);
2164 Py_DECREF(tuple);
2165 if (result == NULL)
2166 return NULL;
2167 if (!PyInt_Check(result)) {
2168 PyErr_SetString(PyExc_TypeError,
2169 "callback MUST return an int");
2170 return NULL;
2171 } else if (PyInt_AsLong(result) != 0) {
2172 PyErr_SetString(PyExc_TypeError,
2173 "callback failed to return 0 on two empty strings");
2174 return NULL;
2176 Py_DECREF(result);
2178 /* We don't accept multiple set_bt_compare operations, in order to
2179 * simplify the code. This would have no real use, as one cannot
2180 * change the function once the db is opened anyway */
2181 if (self->btCompareCallback != NULL) {
2182 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2183 return NULL;
2186 Py_INCREF(comparator);
2187 self->btCompareCallback = comparator;
2189 /* This is to workaround a problem with un-initialized threads (see
2190 comment in DB_associate) */
2191 #ifdef WITH_THREAD
2192 PyEval_InitThreads();
2193 #endif
2195 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2197 if (err) {
2198 /* restore the old state in case of error */
2199 Py_DECREF(comparator);
2200 self->btCompareCallback = NULL;
2203 RETURN_IF_ERR();
2204 RETURN_NONE();
2206 #endif /* DBVER >= 33 */
2209 static PyObject*
2210 DB_set_cachesize(DBObject* self, PyObject* args)
2212 int err;
2213 int gbytes = 0, bytes = 0, ncache = 0;
2215 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2216 &gbytes,&bytes,&ncache))
2217 return NULL;
2218 CHECK_DB_NOT_CLOSED(self);
2220 MYDB_BEGIN_ALLOW_THREADS;
2221 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2222 MYDB_END_ALLOW_THREADS;
2223 RETURN_IF_ERR();
2224 RETURN_NONE();
2228 static PyObject*
2229 DB_set_flags(DBObject* self, PyObject* args)
2231 int err, flags;
2233 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2234 return NULL;
2235 CHECK_DB_NOT_CLOSED(self);
2237 MYDB_BEGIN_ALLOW_THREADS;
2238 err = self->db->set_flags(self->db, flags);
2239 MYDB_END_ALLOW_THREADS;
2240 RETURN_IF_ERR();
2242 self->setflags |= flags;
2243 RETURN_NONE();
2247 static PyObject*
2248 DB_set_h_ffactor(DBObject* self, PyObject* args)
2250 int err, ffactor;
2252 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2253 return NULL;
2254 CHECK_DB_NOT_CLOSED(self);
2256 MYDB_BEGIN_ALLOW_THREADS;
2257 err = self->db->set_h_ffactor(self->db, ffactor);
2258 MYDB_END_ALLOW_THREADS;
2259 RETURN_IF_ERR();
2260 RETURN_NONE();
2264 static PyObject*
2265 DB_set_h_nelem(DBObject* self, PyObject* args)
2267 int err, nelem;
2269 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2270 return NULL;
2271 CHECK_DB_NOT_CLOSED(self);
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_h_nelem(self->db, nelem);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2281 static PyObject*
2282 DB_set_lorder(DBObject* self, PyObject* args)
2284 int err, lorder;
2286 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2287 return NULL;
2288 CHECK_DB_NOT_CLOSED(self);
2290 MYDB_BEGIN_ALLOW_THREADS;
2291 err = self->db->set_lorder(self->db, lorder);
2292 MYDB_END_ALLOW_THREADS;
2293 RETURN_IF_ERR();
2294 RETURN_NONE();
2298 static PyObject*
2299 DB_set_pagesize(DBObject* self, PyObject* args)
2301 int err, pagesize;
2303 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2304 return NULL;
2305 CHECK_DB_NOT_CLOSED(self);
2307 MYDB_BEGIN_ALLOW_THREADS;
2308 err = self->db->set_pagesize(self->db, pagesize);
2309 MYDB_END_ALLOW_THREADS;
2310 RETURN_IF_ERR();
2311 RETURN_NONE();
2315 static PyObject*
2316 DB_set_re_delim(DBObject* self, PyObject* args)
2318 int err;
2319 char delim;
2321 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2322 PyErr_Clear();
2323 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2324 return NULL;
2327 CHECK_DB_NOT_CLOSED(self);
2329 MYDB_BEGIN_ALLOW_THREADS;
2330 err = self->db->set_re_delim(self->db, delim);
2331 MYDB_END_ALLOW_THREADS;
2332 RETURN_IF_ERR();
2333 RETURN_NONE();
2336 static PyObject*
2337 DB_set_re_len(DBObject* self, PyObject* args)
2339 int err, len;
2341 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2342 return NULL;
2343 CHECK_DB_NOT_CLOSED(self);
2345 MYDB_BEGIN_ALLOW_THREADS;
2346 err = self->db->set_re_len(self->db, len);
2347 MYDB_END_ALLOW_THREADS;
2348 RETURN_IF_ERR();
2349 RETURN_NONE();
2353 static PyObject*
2354 DB_set_re_pad(DBObject* self, PyObject* args)
2356 int err;
2357 char pad;
2359 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2360 PyErr_Clear();
2361 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2362 return NULL;
2364 CHECK_DB_NOT_CLOSED(self);
2366 MYDB_BEGIN_ALLOW_THREADS;
2367 err = self->db->set_re_pad(self->db, pad);
2368 MYDB_END_ALLOW_THREADS;
2369 RETURN_IF_ERR();
2370 RETURN_NONE();
2374 static PyObject*
2375 DB_set_re_source(DBObject* self, PyObject* args)
2377 int err;
2378 char *re_source;
2380 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2381 return NULL;
2382 CHECK_DB_NOT_CLOSED(self);
2384 MYDB_BEGIN_ALLOW_THREADS;
2385 err = self->db->set_re_source(self->db, re_source);
2386 MYDB_END_ALLOW_THREADS;
2387 RETURN_IF_ERR();
2388 RETURN_NONE();
2392 #if (DBVER >= 32)
2393 static PyObject*
2394 DB_set_q_extentsize(DBObject* self, PyObject* args)
2396 int err;
2397 int extentsize;
2399 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2400 return NULL;
2401 CHECK_DB_NOT_CLOSED(self);
2403 MYDB_BEGIN_ALLOW_THREADS;
2404 err = self->db->set_q_extentsize(self->db, extentsize);
2405 MYDB_END_ALLOW_THREADS;
2406 RETURN_IF_ERR();
2407 RETURN_NONE();
2409 #endif
2411 static PyObject*
2412 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2414 int err, flags = 0, type;
2415 void* sp;
2416 PyObject* d;
2417 #if (DBVER >= 43)
2418 PyObject* txnobj = NULL;
2419 DB_TXN *txn = NULL;
2420 static char* kwnames[] = { "txn", "flags", NULL };
2421 #else
2422 static char* kwnames[] = { "flags", NULL };
2423 #endif
2425 #if (DBVER >= 43)
2426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2427 &flags, &txnobj))
2428 return NULL;
2429 if (!checkTxnObj(txnobj, &txn))
2430 return NULL;
2431 #else
2432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2433 return NULL;
2434 #endif
2435 CHECK_DB_NOT_CLOSED(self);
2437 MYDB_BEGIN_ALLOW_THREADS;
2438 #if (DBVER >= 43)
2439 err = self->db->stat(self->db, txn, &sp, flags);
2440 #elif (DBVER >= 33)
2441 err = self->db->stat(self->db, &sp, flags);
2442 #else
2443 err = self->db->stat(self->db, &sp, NULL, flags);
2444 #endif
2445 MYDB_END_ALLOW_THREADS;
2446 RETURN_IF_ERR();
2448 self->haveStat = 1;
2450 /* Turn the stat structure into a dictionary */
2451 type = _DB_get_type(self);
2452 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2453 free(sp);
2454 return NULL;
2457 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2458 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2459 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2461 switch (type) {
2462 case DB_HASH:
2463 MAKE_HASH_ENTRY(magic);
2464 MAKE_HASH_ENTRY(version);
2465 MAKE_HASH_ENTRY(nkeys);
2466 MAKE_HASH_ENTRY(ndata);
2467 MAKE_HASH_ENTRY(pagesize);
2468 #if (DBVER < 41)
2469 MAKE_HASH_ENTRY(nelem);
2470 #endif
2471 MAKE_HASH_ENTRY(ffactor);
2472 MAKE_HASH_ENTRY(buckets);
2473 MAKE_HASH_ENTRY(free);
2474 MAKE_HASH_ENTRY(bfree);
2475 MAKE_HASH_ENTRY(bigpages);
2476 MAKE_HASH_ENTRY(big_bfree);
2477 MAKE_HASH_ENTRY(overflows);
2478 MAKE_HASH_ENTRY(ovfl_free);
2479 MAKE_HASH_ENTRY(dup);
2480 MAKE_HASH_ENTRY(dup_free);
2481 break;
2483 case DB_BTREE:
2484 case DB_RECNO:
2485 MAKE_BT_ENTRY(magic);
2486 MAKE_BT_ENTRY(version);
2487 MAKE_BT_ENTRY(nkeys);
2488 MAKE_BT_ENTRY(ndata);
2489 MAKE_BT_ENTRY(pagesize);
2490 MAKE_BT_ENTRY(minkey);
2491 MAKE_BT_ENTRY(re_len);
2492 MAKE_BT_ENTRY(re_pad);
2493 MAKE_BT_ENTRY(levels);
2494 MAKE_BT_ENTRY(int_pg);
2495 MAKE_BT_ENTRY(leaf_pg);
2496 MAKE_BT_ENTRY(dup_pg);
2497 MAKE_BT_ENTRY(over_pg);
2498 MAKE_BT_ENTRY(free);
2499 MAKE_BT_ENTRY(int_pgfree);
2500 MAKE_BT_ENTRY(leaf_pgfree);
2501 MAKE_BT_ENTRY(dup_pgfree);
2502 MAKE_BT_ENTRY(over_pgfree);
2503 break;
2505 case DB_QUEUE:
2506 MAKE_QUEUE_ENTRY(magic);
2507 MAKE_QUEUE_ENTRY(version);
2508 MAKE_QUEUE_ENTRY(nkeys);
2509 MAKE_QUEUE_ENTRY(ndata);
2510 MAKE_QUEUE_ENTRY(pagesize);
2511 MAKE_QUEUE_ENTRY(pages);
2512 MAKE_QUEUE_ENTRY(re_len);
2513 MAKE_QUEUE_ENTRY(re_pad);
2514 MAKE_QUEUE_ENTRY(pgfree);
2515 #if (DBVER == 31)
2516 MAKE_QUEUE_ENTRY(start);
2517 #endif
2518 MAKE_QUEUE_ENTRY(first_recno);
2519 MAKE_QUEUE_ENTRY(cur_recno);
2520 break;
2522 default:
2523 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2524 Py_DECREF(d);
2525 d = NULL;
2528 #undef MAKE_HASH_ENTRY
2529 #undef MAKE_BT_ENTRY
2530 #undef MAKE_QUEUE_ENTRY
2532 free(sp);
2533 return d;
2536 static PyObject*
2537 DB_sync(DBObject* self, PyObject* args)
2539 int err;
2540 int flags = 0;
2542 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2543 return NULL;
2544 CHECK_DB_NOT_CLOSED(self);
2546 MYDB_BEGIN_ALLOW_THREADS;
2547 err = self->db->sync(self->db, flags);
2548 MYDB_END_ALLOW_THREADS;
2549 RETURN_IF_ERR();
2550 RETURN_NONE();
2554 #if (DBVER >= 33)
2555 static PyObject*
2556 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2558 int err, flags=0;
2559 u_int32_t count=0;
2560 PyObject* txnobj = NULL;
2561 DB_TXN *txn = NULL;
2562 static char* kwnames[] = { "txn", "flags", NULL };
2564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2565 &txnobj, &flags))
2566 return NULL;
2567 CHECK_DB_NOT_CLOSED(self);
2568 if (!checkTxnObj(txnobj, &txn))
2569 return NULL;
2571 MYDB_BEGIN_ALLOW_THREADS;
2572 err = self->db->truncate(self->db, txn, &count, flags);
2573 MYDB_END_ALLOW_THREADS;
2574 RETURN_IF_ERR();
2575 return PyInt_FromLong(count);
2577 #endif
2580 static PyObject*
2581 DB_upgrade(DBObject* self, PyObject* args)
2583 int err, flags=0;
2584 char *filename;
2586 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2587 return NULL;
2588 CHECK_DB_NOT_CLOSED(self);
2590 MYDB_BEGIN_ALLOW_THREADS;
2591 err = self->db->upgrade(self->db, filename, flags);
2592 MYDB_END_ALLOW_THREADS;
2593 RETURN_IF_ERR();
2594 RETURN_NONE();
2598 static PyObject*
2599 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2601 int err, flags=0;
2602 char* fileName;
2603 char* dbName=NULL;
2604 char* outFileName=NULL;
2605 FILE* outFile=NULL;
2606 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2607 NULL };
2609 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2610 &fileName, &dbName, &outFileName, &flags))
2611 return NULL;
2613 CHECK_DB_NOT_CLOSED(self);
2614 if (outFileName)
2615 outFile = fopen(outFileName, "w");
2617 MYDB_BEGIN_ALLOW_THREADS;
2618 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2619 MYDB_END_ALLOW_THREADS;
2620 if (outFileName)
2621 fclose(outFile);
2623 /* DB.verify acts as a DB handle destructor (like close); this was
2624 * documented in BerkeleyDB 4.2 but had the undocumented effect
2625 * of not being safe in prior versions while still requiring an explicit
2626 * DB.close call afterwards. Lets call close for the user to emulate
2627 * the safe 4.2 behaviour. */
2628 #if (DBVER <= 41)
2629 self->db->close(self->db, 0);
2630 #endif
2631 self->db = NULL;
2633 RETURN_IF_ERR();
2634 RETURN_NONE();
2638 static PyObject*
2639 DB_set_get_returns_none(DBObject* self, PyObject* args)
2641 int flags=0;
2642 int oldValue=0;
2644 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2645 return NULL;
2646 CHECK_DB_NOT_CLOSED(self);
2648 if (self->moduleFlags.getReturnsNone)
2649 ++oldValue;
2650 if (self->moduleFlags.cursorSetReturnsNone)
2651 ++oldValue;
2652 self->moduleFlags.getReturnsNone = (flags >= 1);
2653 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2654 return PyInt_FromLong(oldValue);
2657 #if (DBVER >= 41)
2658 static PyObject*
2659 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2661 int err;
2662 u_int32_t flags=0;
2663 char *passwd = NULL;
2664 static char* kwnames[] = { "passwd", "flags", NULL };
2666 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2667 &passwd, &flags)) {
2668 return NULL;
2671 MYDB_BEGIN_ALLOW_THREADS;
2672 err = self->db->set_encrypt(self->db, passwd, flags);
2673 MYDB_END_ALLOW_THREADS;
2675 RETURN_IF_ERR();
2676 RETURN_NONE();
2678 #endif /* DBVER >= 41 */
2681 /*-------------------------------------------------------------- */
2682 /* Mapping and Dictionary-like access routines */
2684 Py_ssize_t DB_length(PyObject* _self)
2686 int err;
2687 Py_ssize_t size = 0;
2688 int flags = 0;
2689 void* sp;
2690 DBObject* self = (DBObject*)_self;
2692 if (self->db == NULL) {
2693 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2694 PyErr_SetObject(DBError, t);
2695 Py_DECREF(t);
2696 return -1;
2699 if (self->haveStat) { /* Has the stat function been called recently? If
2700 so, we can use the cached value. */
2701 flags = DB_FAST_STAT;
2704 MYDB_BEGIN_ALLOW_THREADS;
2705 redo_stat_for_length:
2706 #if (DBVER >= 43)
2707 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2708 #elif (DBVER >= 33)
2709 err = self->db->stat(self->db, &sp, flags);
2710 #else
2711 err = self->db->stat(self->db, &sp, NULL, flags);
2712 #endif
2714 /* All the stat structures have matching fields upto the ndata field,
2715 so we can use any of them for the type cast */
2716 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2718 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2719 * redo a full stat to make sure.
2720 * Fixes SF python bug 1493322, pybsddb bug 1184012
2722 if (size == 0 && (flags & DB_FAST_STAT)) {
2723 flags = 0;
2724 if (!err)
2725 free(sp);
2726 goto redo_stat_for_length;
2729 MYDB_END_ALLOW_THREADS;
2731 if (err)
2732 return -1;
2734 self->haveStat = 1;
2736 free(sp);
2737 return size;
2741 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2743 int err;
2744 PyObject* retval;
2745 DBT key;
2746 DBT data;
2748 CHECK_DB_NOT_CLOSED(self);
2749 if (!make_key_dbt(self, keyobj, &key, NULL))
2750 return NULL;
2752 CLEAR_DBT(data);
2753 if (CHECK_DBFLAG(self, DB_THREAD)) {
2754 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2755 data.flags = DB_DBT_MALLOC;
2757 MYDB_BEGIN_ALLOW_THREADS;
2758 err = self->db->get(self->db, NULL, &key, &data, 0);
2759 MYDB_END_ALLOW_THREADS;
2760 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2761 PyErr_SetObject(PyExc_KeyError, keyobj);
2762 retval = NULL;
2764 else if (makeDBError(err)) {
2765 retval = NULL;
2767 else {
2768 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2769 FREE_DBT(data);
2772 FREE_DBT(key);
2773 return retval;
2777 static int
2778 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2780 DBT key, data;
2781 int retval;
2782 int flags = 0;
2784 if (self->db == NULL) {
2785 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2786 PyErr_SetObject(DBError, t);
2787 Py_DECREF(t);
2788 return -1;
2791 if (!make_key_dbt(self, keyobj, &key, NULL))
2792 return -1;
2794 if (dataobj != NULL) {
2795 if (!make_dbt(dataobj, &data))
2796 retval = -1;
2797 else {
2798 if (self->setflags & (DB_DUP|DB_DUPSORT))
2799 /* dictionaries shouldn't have duplicate keys */
2800 flags = DB_NOOVERWRITE;
2801 retval = _DB_put(self, NULL, &key, &data, flags);
2803 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2804 /* try deleting any old record that matches and then PUT it
2805 * again... */
2806 _DB_delete(self, NULL, &key, 0);
2807 PyErr_Clear();
2808 retval = _DB_put(self, NULL, &key, &data, flags);
2812 else {
2813 /* dataobj == NULL, so delete the key */
2814 retval = _DB_delete(self, NULL, &key, 0);
2816 FREE_DBT(key);
2817 return retval;
2821 static PyObject*
2822 DB_has_key(DBObject* self, PyObject* args)
2824 int err;
2825 PyObject* keyobj;
2826 DBT key, data;
2827 PyObject* txnobj = NULL;
2828 DB_TXN *txn = NULL;
2830 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2831 return NULL;
2832 CHECK_DB_NOT_CLOSED(self);
2833 if (!make_key_dbt(self, keyobj, &key, NULL))
2834 return NULL;
2835 if (!checkTxnObj(txnobj, &txn)) {
2836 FREE_DBT(key);
2837 return NULL;
2840 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2841 it has a record but can't allocate a buffer for the data. This saves
2842 having to deal with data we won't be using.
2844 CLEAR_DBT(data);
2845 data.flags = DB_DBT_USERMEM;
2847 MYDB_BEGIN_ALLOW_THREADS;
2848 err = self->db->get(self->db, txn, &key, &data, 0);
2849 MYDB_END_ALLOW_THREADS;
2850 FREE_DBT(key);
2852 if (err == DB_BUFFER_SMALL || err == 0) {
2853 return PyInt_FromLong(1);
2854 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2855 return PyInt_FromLong(0);
2858 makeDBError(err);
2859 return NULL;
2863 #define _KEYS_LIST 1
2864 #define _VALUES_LIST 2
2865 #define _ITEMS_LIST 3
2867 static PyObject*
2868 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2870 int err, dbtype;
2871 DBT key;
2872 DBT data;
2873 DBC *cursor;
2874 PyObject* list;
2875 PyObject* item = NULL;
2877 CHECK_DB_NOT_CLOSED(self);
2878 CLEAR_DBT(key);
2879 CLEAR_DBT(data);
2881 dbtype = _DB_get_type(self);
2882 if (dbtype == -1)
2883 return NULL;
2885 list = PyList_New(0);
2886 if (list == NULL)
2887 return NULL;
2889 /* get a cursor */
2890 MYDB_BEGIN_ALLOW_THREADS;
2891 err = self->db->cursor(self->db, txn, &cursor, 0);
2892 MYDB_END_ALLOW_THREADS;
2893 if (makeDBError(err)) {
2894 Py_DECREF(list);
2895 return NULL;
2898 if (CHECK_DBFLAG(self, DB_THREAD)) {
2899 key.flags = DB_DBT_REALLOC;
2900 data.flags = DB_DBT_REALLOC;
2903 while (1) { /* use the cursor to traverse the DB, collecting items */
2904 MYDB_BEGIN_ALLOW_THREADS;
2905 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2906 MYDB_END_ALLOW_THREADS;
2908 if (err) {
2909 /* for any error, break out of the loop */
2910 break;
2913 switch (type) {
2914 case _KEYS_LIST:
2915 switch(dbtype) {
2916 case DB_BTREE:
2917 case DB_HASH:
2918 default:
2919 item = PyString_FromStringAndSize((char*)key.data, key.size);
2920 break;
2921 case DB_RECNO:
2922 case DB_QUEUE:
2923 item = PyInt_FromLong(*((db_recno_t*)key.data));
2924 break;
2926 break;
2928 case _VALUES_LIST:
2929 item = PyString_FromStringAndSize((char*)data.data, data.size);
2930 break;
2932 case _ITEMS_LIST:
2933 switch(dbtype) {
2934 case DB_BTREE:
2935 case DB_HASH:
2936 default:
2937 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2938 data.size);
2939 break;
2940 case DB_RECNO:
2941 case DB_QUEUE:
2942 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2943 data.data, data.size);
2944 break;
2946 break;
2947 default:
2948 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2949 item = NULL;
2950 break;
2952 if (item == NULL) {
2953 Py_DECREF(list);
2954 list = NULL;
2955 goto done;
2957 PyList_Append(list, item);
2958 Py_DECREF(item);
2961 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2962 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2963 Py_DECREF(list);
2964 list = NULL;
2967 done:
2968 FREE_DBT(key);
2969 FREE_DBT(data);
2970 MYDB_BEGIN_ALLOW_THREADS;
2971 cursor->c_close(cursor);
2972 MYDB_END_ALLOW_THREADS;
2973 return list;
2977 static PyObject*
2978 DB_keys(DBObject* self, PyObject* args)
2980 PyObject* txnobj = NULL;
2981 DB_TXN *txn = NULL;
2983 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2984 return NULL;
2985 if (!checkTxnObj(txnobj, &txn))
2986 return NULL;
2987 return _DB_make_list(self, txn, _KEYS_LIST);
2991 static PyObject*
2992 DB_items(DBObject* self, PyObject* args)
2994 PyObject* txnobj = NULL;
2995 DB_TXN *txn = NULL;
2997 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
2998 return NULL;
2999 if (!checkTxnObj(txnobj, &txn))
3000 return NULL;
3001 return _DB_make_list(self, txn, _ITEMS_LIST);
3005 static PyObject*
3006 DB_values(DBObject* self, PyObject* args)
3008 PyObject* txnobj = NULL;
3009 DB_TXN *txn = NULL;
3011 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3012 return NULL;
3013 if (!checkTxnObj(txnobj, &txn))
3014 return NULL;
3015 return _DB_make_list(self, txn, _VALUES_LIST);
3018 /* --------------------------------------------------------------------- */
3019 /* DBCursor methods */
3022 static PyObject*
3023 DBC_close(DBCursorObject* self, PyObject* args)
3025 int err = 0;
3027 if (!PyArg_ParseTuple(args, ":close"))
3028 return NULL;
3030 if (self->dbc != NULL) {
3031 MYDB_BEGIN_ALLOW_THREADS;
3032 err = self->dbc->c_close(self->dbc);
3033 self->dbc = NULL;
3034 MYDB_END_ALLOW_THREADS;
3036 RETURN_IF_ERR();
3037 RETURN_NONE();
3041 static PyObject*
3042 DBC_count(DBCursorObject* self, PyObject* args)
3044 int err = 0;
3045 db_recno_t count;
3046 int flags = 0;
3048 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3049 return NULL;
3051 CHECK_CURSOR_NOT_CLOSED(self);
3053 MYDB_BEGIN_ALLOW_THREADS;
3054 err = self->dbc->c_count(self->dbc, &count, flags);
3055 MYDB_END_ALLOW_THREADS;
3056 RETURN_IF_ERR();
3058 return PyInt_FromLong(count);
3062 static PyObject*
3063 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3065 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3069 static PyObject*
3070 DBC_delete(DBCursorObject* self, PyObject* args)
3072 int err, flags=0;
3074 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3075 return NULL;
3077 CHECK_CURSOR_NOT_CLOSED(self);
3079 MYDB_BEGIN_ALLOW_THREADS;
3080 err = self->dbc->c_del(self->dbc, flags);
3081 MYDB_END_ALLOW_THREADS;
3082 RETURN_IF_ERR();
3084 self->mydb->haveStat = 0;
3085 RETURN_NONE();
3089 static PyObject*
3090 DBC_dup(DBCursorObject* self, PyObject* args)
3092 int err, flags =0;
3093 DBC* dbc = NULL;
3095 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3096 return NULL;
3098 CHECK_CURSOR_NOT_CLOSED(self);
3100 MYDB_BEGIN_ALLOW_THREADS;
3101 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3102 MYDB_END_ALLOW_THREADS;
3103 RETURN_IF_ERR();
3105 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3108 static PyObject*
3109 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3111 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3115 static PyObject*
3116 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3118 int err, flags=0;
3119 PyObject* keyobj = NULL;
3120 PyObject* dataobj = NULL;
3121 PyObject* retval = NULL;
3122 int dlen = -1;
3123 int doff = -1;
3124 DBT key, data;
3125 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3126 NULL };
3128 CLEAR_DBT(key);
3129 CLEAR_DBT(data);
3130 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3131 &flags, &dlen, &doff))
3133 PyErr_Clear();
3134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3135 &kwnames[1],
3136 &keyobj, &flags, &dlen, &doff))
3138 PyErr_Clear();
3139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3140 kwnames, &keyobj, &dataobj,
3141 &flags, &dlen, &doff))
3143 return NULL;
3148 CHECK_CURSOR_NOT_CLOSED(self);
3150 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3151 return NULL;
3152 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3153 (!add_partial_dbt(&data, dlen, doff)) )
3155 FREE_DBT(key);
3156 return NULL;
3159 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3160 data.flags = DB_DBT_MALLOC;
3161 if (!(key.flags & DB_DBT_REALLOC)) {
3162 key.flags |= DB_DBT_MALLOC;
3166 MYDB_BEGIN_ALLOW_THREADS;
3167 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3168 MYDB_END_ALLOW_THREADS;
3170 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3171 && self->mydb->moduleFlags.getReturnsNone) {
3172 Py_INCREF(Py_None);
3173 retval = Py_None;
3175 else if (makeDBError(err)) {
3176 retval = NULL;
3178 else {
3179 switch (_DB_get_type(self->mydb)) {
3180 case -1:
3181 retval = NULL;
3182 break;
3183 case DB_BTREE:
3184 case DB_HASH:
3185 default:
3186 retval = Py_BuildValue("s#s#", key.data, key.size,
3187 data.data, data.size);
3188 break;
3189 case DB_RECNO:
3190 case DB_QUEUE:
3191 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3192 data.data, data.size);
3193 break;
3195 FREE_DBT(data);
3197 FREE_DBT(key);
3198 return retval;
3201 #if (DBVER >= 33)
3202 static PyObject*
3203 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3205 int err, flags=0;
3206 PyObject* keyobj = NULL;
3207 PyObject* dataobj = NULL;
3208 PyObject* retval = NULL;
3209 int dlen = -1;
3210 int doff = -1;
3211 DBT key, pkey, data;
3212 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3213 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3215 CLEAR_DBT(key);
3216 CLEAR_DBT(data);
3217 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3218 &flags, &dlen, &doff))
3220 PyErr_Clear();
3221 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3222 kwnames_keyOnly,
3223 &keyobj, &flags, &dlen, &doff))
3225 PyErr_Clear();
3226 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3227 kwnames, &keyobj, &dataobj,
3228 &flags, &dlen, &doff))
3230 return NULL;
3235 CHECK_CURSOR_NOT_CLOSED(self);
3237 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3238 return NULL;
3239 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3240 (!add_partial_dbt(&data, dlen, doff)) ) {
3241 FREE_DBT(key);
3242 return NULL;
3245 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3246 data.flags = DB_DBT_MALLOC;
3247 if (!(key.flags & DB_DBT_REALLOC)) {
3248 key.flags |= DB_DBT_MALLOC;
3252 CLEAR_DBT(pkey);
3253 pkey.flags = DB_DBT_MALLOC;
3255 MYDB_BEGIN_ALLOW_THREADS;
3256 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3257 MYDB_END_ALLOW_THREADS;
3259 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3260 && self->mydb->moduleFlags.getReturnsNone) {
3261 Py_INCREF(Py_None);
3262 retval = Py_None;
3264 else if (makeDBError(err)) {
3265 retval = NULL;
3267 else {
3268 PyObject *pkeyObj;
3269 PyObject *dataObj;
3270 dataObj = PyString_FromStringAndSize(data.data, data.size);
3272 if (self->mydb->primaryDBType == DB_RECNO ||
3273 self->mydb->primaryDBType == DB_QUEUE)
3274 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3275 else
3276 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3278 if (key.data && key.size) /* return key, pkey and data */
3280 PyObject *keyObj;
3281 int type = _DB_get_type(self->mydb);
3282 if (type == DB_RECNO || type == DB_QUEUE)
3283 keyObj = PyInt_FromLong(*(int *)key.data);
3284 else
3285 keyObj = PyString_FromStringAndSize(key.data, key.size);
3286 #if (PY_VERSION_HEX >= 0x02040000)
3287 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3288 #else
3289 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3290 #endif
3291 Py_DECREF(keyObj);
3292 FREE_DBT(key);
3294 else /* return just the pkey and data */
3296 #if (PY_VERSION_HEX >= 0x02040000)
3297 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3298 #else
3299 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3300 #endif
3302 Py_DECREF(dataObj);
3303 Py_DECREF(pkeyObj);
3304 FREE_DBT(pkey);
3305 FREE_DBT(data);
3307 /* the only time REALLOC should be set is if we used an integer
3308 * key that make_key_dbt malloc'd for us. always free these. */
3309 if (key.flags & DB_DBT_REALLOC) {
3310 FREE_DBT(key);
3312 return retval;
3314 #endif
3317 static PyObject*
3318 DBC_get_recno(DBCursorObject* self, PyObject* args)
3320 int err;
3321 db_recno_t recno;
3322 DBT key;
3323 DBT data;
3325 if (!PyArg_ParseTuple(args, ":get_recno"))
3326 return NULL;
3328 CHECK_CURSOR_NOT_CLOSED(self);
3330 CLEAR_DBT(key);
3331 CLEAR_DBT(data);
3332 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3333 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3334 data.flags = DB_DBT_MALLOC;
3335 key.flags = DB_DBT_MALLOC;
3338 MYDB_BEGIN_ALLOW_THREADS;
3339 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3340 MYDB_END_ALLOW_THREADS;
3341 RETURN_IF_ERR();
3343 recno = *((db_recno_t*)data.data);
3344 FREE_DBT(key);
3345 FREE_DBT(data);
3346 return PyInt_FromLong(recno);
3350 static PyObject*
3351 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3353 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3357 static PyObject*
3358 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3360 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3364 static PyObject*
3365 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3367 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3371 static PyObject*
3372 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3374 int err, flags = 0;
3375 PyObject* keyobj, *dataobj;
3376 DBT key, data;
3377 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3378 NULL };
3379 int dlen = -1;
3380 int doff = -1;
3382 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3383 &keyobj, &dataobj, &flags, &dlen, &doff))
3384 return NULL;
3386 CHECK_CURSOR_NOT_CLOSED(self);
3388 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3389 return NULL;
3390 if (!make_dbt(dataobj, &data) ||
3391 !add_partial_dbt(&data, dlen, doff) )
3393 FREE_DBT(key);
3394 return NULL;
3397 MYDB_BEGIN_ALLOW_THREADS;
3398 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3399 MYDB_END_ALLOW_THREADS;
3400 FREE_DBT(key);
3401 RETURN_IF_ERR();
3402 self->mydb->haveStat = 0;
3403 RETURN_NONE();
3407 static PyObject*
3408 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3410 int err, flags = 0;
3411 DBT key, data;
3412 PyObject* retval, *keyobj;
3413 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3414 int dlen = -1;
3415 int doff = -1;
3417 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3418 &keyobj, &flags, &dlen, &doff))
3419 return NULL;
3421 CHECK_CURSOR_NOT_CLOSED(self);
3423 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3424 return NULL;
3426 CLEAR_DBT(data);
3427 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3428 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3429 data.flags = DB_DBT_MALLOC;
3431 if (!add_partial_dbt(&data, dlen, doff)) {
3432 FREE_DBT(key);
3433 return NULL;
3436 MYDB_BEGIN_ALLOW_THREADS;
3437 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3438 MYDB_END_ALLOW_THREADS;
3439 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3440 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3441 Py_INCREF(Py_None);
3442 retval = Py_None;
3444 else if (makeDBError(err)) {
3445 retval = NULL;
3447 else {
3448 switch (_DB_get_type(self->mydb)) {
3449 case -1:
3450 retval = NULL;
3451 break;
3452 case DB_BTREE:
3453 case DB_HASH:
3454 default:
3455 retval = Py_BuildValue("s#s#", key.data, key.size,
3456 data.data, data.size);
3457 break;
3458 case DB_RECNO:
3459 case DB_QUEUE:
3460 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3461 data.data, data.size);
3462 break;
3464 FREE_DBT(data);
3465 FREE_DBT(key);
3467 /* the only time REALLOC should be set is if we used an integer
3468 * key that make_key_dbt malloc'd for us. always free these. */
3469 if (key.flags & DB_DBT_REALLOC) {
3470 FREE_DBT(key);
3473 return retval;
3477 static PyObject*
3478 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3480 int err, flags = 0;
3481 DBT key, data;
3482 PyObject* retval, *keyobj;
3483 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3484 int dlen = -1;
3485 int doff = -1;
3487 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3488 &keyobj, &flags, &dlen, &doff))
3489 return NULL;
3491 CHECK_CURSOR_NOT_CLOSED(self);
3493 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3494 return NULL;
3496 CLEAR_DBT(data);
3497 if (!add_partial_dbt(&data, dlen, doff)) {
3498 FREE_DBT(key);
3499 return NULL;
3501 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3502 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3503 data.flags |= DB_DBT_MALLOC;
3504 /* only BTREE databases will return anything in the key */
3505 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3506 key.flags |= DB_DBT_MALLOC;
3509 MYDB_BEGIN_ALLOW_THREADS;
3510 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3511 MYDB_END_ALLOW_THREADS;
3512 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3513 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3514 Py_INCREF(Py_None);
3515 retval = Py_None;
3517 else if (makeDBError(err)) {
3518 retval = NULL;
3520 else {
3521 switch (_DB_get_type(self->mydb)) {
3522 case -1:
3523 retval = NULL;
3524 break;
3525 case DB_BTREE:
3526 case DB_HASH:
3527 default:
3528 retval = Py_BuildValue("s#s#", key.data, key.size,
3529 data.data, data.size);
3530 break;
3531 case DB_RECNO:
3532 case DB_QUEUE:
3533 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3534 data.data, data.size);
3535 break;
3537 FREE_DBT(key);
3538 FREE_DBT(data);
3540 /* the only time REALLOC should be set is if we used an integer
3541 * key that make_key_dbt malloc'd for us. always free these. */
3542 if (key.flags & DB_DBT_REALLOC) {
3543 FREE_DBT(key);
3546 return retval;
3549 static PyObject*
3550 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3551 int flags, unsigned int returnsNone)
3553 int err;
3554 DBT key, data;
3555 PyObject* retval;
3557 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3558 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3559 return NULL;
3560 if (!make_dbt(dataobj, &data)) {
3561 FREE_DBT(key);
3562 return NULL;
3565 MYDB_BEGIN_ALLOW_THREADS;
3566 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3567 MYDB_END_ALLOW_THREADS;
3568 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3569 Py_INCREF(Py_None);
3570 retval = Py_None;
3572 else if (makeDBError(err)) {
3573 retval = NULL;
3575 else {
3576 switch (_DB_get_type(self->mydb)) {
3577 case -1:
3578 retval = NULL;
3579 break;
3580 case DB_BTREE:
3581 case DB_HASH:
3582 default:
3583 retval = Py_BuildValue("s#s#", key.data, key.size,
3584 data.data, data.size);
3585 break;
3586 case DB_RECNO:
3587 case DB_QUEUE:
3588 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3589 data.data, data.size);
3590 break;
3594 FREE_DBT(key);
3595 return retval;
3598 static PyObject*
3599 DBC_get_both(DBCursorObject* self, PyObject* args)
3601 int flags=0;
3602 PyObject *keyobj, *dataobj;
3604 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3605 return NULL;
3607 /* if the cursor is closed, self->mydb may be invalid */
3608 CHECK_CURSOR_NOT_CLOSED(self);
3610 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3611 self->mydb->moduleFlags.getReturnsNone);
3614 /* Return size of entry */
3615 static PyObject*
3616 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3618 int err, flags=DB_CURRENT;
3619 PyObject* retval = NULL;
3620 DBT key, data;
3622 if (!PyArg_ParseTuple(args, ":get_current_size"))
3623 return NULL;
3624 CHECK_CURSOR_NOT_CLOSED(self);
3625 CLEAR_DBT(key);
3626 CLEAR_DBT(data);
3628 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3629 getting the record size. */
3630 data.flags = DB_DBT_USERMEM;
3631 data.ulen = 0;
3632 MYDB_BEGIN_ALLOW_THREADS;
3633 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3634 MYDB_END_ALLOW_THREADS;
3635 if (err == DB_BUFFER_SMALL || !err) {
3636 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3637 retval = PyInt_FromLong((long)data.size);
3638 err = 0;
3641 FREE_DBT(key);
3642 FREE_DBT(data);
3643 RETURN_IF_ERR();
3644 return retval;
3647 static PyObject*
3648 DBC_set_both(DBCursorObject* self, PyObject* args)
3650 int flags=0;
3651 PyObject *keyobj, *dataobj;
3653 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3654 return NULL;
3656 /* if the cursor is closed, self->mydb may be invalid */
3657 CHECK_CURSOR_NOT_CLOSED(self);
3659 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3660 self->mydb->moduleFlags.cursorSetReturnsNone);
3664 static PyObject*
3665 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3667 int err, irecno, flags=0;
3668 db_recno_t recno;
3669 DBT key, data;
3670 PyObject* retval;
3671 int dlen = -1;
3672 int doff = -1;
3673 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3675 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3676 &irecno, &flags, &dlen, &doff))
3677 return NULL;
3679 CHECK_CURSOR_NOT_CLOSED(self);
3681 CLEAR_DBT(key);
3682 recno = (db_recno_t) irecno;
3683 /* use allocated space so DB will be able to realloc room for the real
3684 * key */
3685 key.data = malloc(sizeof(db_recno_t));
3686 if (key.data == NULL) {
3687 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3688 return NULL;
3690 key.size = sizeof(db_recno_t);
3691 key.ulen = key.size;
3692 memcpy(key.data, &recno, sizeof(db_recno_t));
3693 key.flags = DB_DBT_REALLOC;
3695 CLEAR_DBT(data);
3696 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3697 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3698 data.flags = DB_DBT_MALLOC;
3700 if (!add_partial_dbt(&data, dlen, doff)) {
3701 FREE_DBT(key);
3702 return NULL;
3705 MYDB_BEGIN_ALLOW_THREADS;
3706 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3707 MYDB_END_ALLOW_THREADS;
3708 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3709 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3710 Py_INCREF(Py_None);
3711 retval = Py_None;
3713 else if (makeDBError(err)) {
3714 retval = NULL;
3716 else { /* Can only be used for BTrees, so no need to return int key */
3717 retval = Py_BuildValue("s#s#", key.data, key.size,
3718 data.data, data.size);
3719 FREE_DBT(data);
3721 FREE_DBT(key);
3723 return retval;
3727 static PyObject*
3728 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3730 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3734 static PyObject*
3735 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3737 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3741 static PyObject*
3742 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3744 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3748 static PyObject*
3749 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3751 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3755 static PyObject*
3756 DBC_join_item(DBCursorObject* self, PyObject* args)
3758 int err, flags=0;
3759 DBT key, data;
3760 PyObject* retval;
3762 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3763 return NULL;
3765 CHECK_CURSOR_NOT_CLOSED(self);
3767 CLEAR_DBT(key);
3768 CLEAR_DBT(data);
3769 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3770 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3771 key.flags = DB_DBT_MALLOC;
3774 MYDB_BEGIN_ALLOW_THREADS;
3775 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3776 MYDB_END_ALLOW_THREADS;
3777 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3778 && self->mydb->moduleFlags.getReturnsNone) {
3779 Py_INCREF(Py_None);
3780 retval = Py_None;
3782 else if (makeDBError(err)) {
3783 retval = NULL;
3785 else {
3786 retval = Py_BuildValue("s#", key.data, key.size);
3787 FREE_DBT(key);
3790 return retval;
3795 /* --------------------------------------------------------------------- */
3796 /* DBEnv methods */
3799 static PyObject*
3800 DBEnv_close(DBEnvObject* self, PyObject* args)
3802 int err, flags = 0;
3804 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3805 return NULL;
3806 if (!self->closed) { /* Don't close more than once */
3807 MYDB_BEGIN_ALLOW_THREADS;
3808 err = self->db_env->close(self->db_env, flags);
3809 MYDB_END_ALLOW_THREADS;
3810 /* after calling DBEnv->close, regardless of error, this DBEnv
3811 * may not be accessed again (BerkeleyDB docs). */
3812 self->closed = 1;
3813 self->db_env = NULL;
3814 RETURN_IF_ERR();
3816 RETURN_NONE();
3820 static PyObject*
3821 DBEnv_open(DBEnvObject* self, PyObject* args)
3823 int err, flags=0, mode=0660;
3824 char *db_home;
3826 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3827 return NULL;
3829 CHECK_ENV_NOT_CLOSED(self);
3831 MYDB_BEGIN_ALLOW_THREADS;
3832 err = self->db_env->open(self->db_env, db_home, flags, mode);
3833 MYDB_END_ALLOW_THREADS;
3834 RETURN_IF_ERR();
3835 self->closed = 0;
3836 self->flags = flags;
3837 RETURN_NONE();
3841 static PyObject*
3842 DBEnv_remove(DBEnvObject* self, PyObject* args)
3844 int err, flags=0;
3845 char *db_home;
3847 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3848 return NULL;
3849 CHECK_ENV_NOT_CLOSED(self);
3850 MYDB_BEGIN_ALLOW_THREADS;
3851 err = self->db_env->remove(self->db_env, db_home, flags);
3852 MYDB_END_ALLOW_THREADS;
3853 RETURN_IF_ERR();
3854 RETURN_NONE();
3857 #if (DBVER >= 41)
3858 static PyObject*
3859 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3861 int err;
3862 u_int32_t flags=0;
3863 char *file = NULL;
3864 char *database = NULL;
3865 PyObject *txnobj = NULL;
3866 DB_TXN *txn = NULL;
3867 static char* kwnames[] = { "file", "database", "txn", "flags",
3868 NULL };
3870 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3871 &file, &database, &txnobj, &flags)) {
3872 return NULL;
3874 if (!checkTxnObj(txnobj, &txn)) {
3875 return NULL;
3877 CHECK_ENV_NOT_CLOSED(self);
3878 MYDB_BEGIN_ALLOW_THREADS;
3879 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3880 MYDB_END_ALLOW_THREADS;
3881 RETURN_IF_ERR();
3882 RETURN_NONE();
3885 static PyObject*
3886 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3888 int err;
3889 u_int32_t flags=0;
3890 char *file = NULL;
3891 char *database = NULL;
3892 char *newname = NULL;
3893 PyObject *txnobj = NULL;
3894 DB_TXN *txn = NULL;
3895 static char* kwnames[] = { "file", "database", "newname", "txn",
3896 "flags", NULL };
3898 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3899 &file, &database, &newname, &txnobj, &flags)) {
3900 return NULL;
3902 if (!checkTxnObj(txnobj, &txn)) {
3903 return NULL;
3905 CHECK_ENV_NOT_CLOSED(self);
3906 MYDB_BEGIN_ALLOW_THREADS;
3907 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3908 flags);
3909 MYDB_END_ALLOW_THREADS;
3910 RETURN_IF_ERR();
3911 RETURN_NONE();
3914 static PyObject*
3915 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3917 int err;
3918 u_int32_t flags=0;
3919 char *passwd = NULL;
3920 static char* kwnames[] = { "passwd", "flags", NULL };
3922 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3923 &passwd, &flags)) {
3924 return NULL;
3927 MYDB_BEGIN_ALLOW_THREADS;
3928 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3929 MYDB_END_ALLOW_THREADS;
3931 RETURN_IF_ERR();
3932 RETURN_NONE();
3934 #endif /* DBVER >= 41 */
3936 #if (DBVER >= 40)
3937 static PyObject*
3938 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3940 int err;
3941 u_int32_t flags=0;
3942 u_int32_t timeout = 0;
3943 static char* kwnames[] = { "timeout", "flags", NULL };
3945 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3946 &timeout, &flags)) {
3947 return NULL;
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3952 MYDB_END_ALLOW_THREADS;
3954 RETURN_IF_ERR();
3955 RETURN_NONE();
3957 #endif /* DBVER >= 40 */
3959 static PyObject*
3960 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3962 int err;
3963 long shm_key = 0;
3965 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3966 return NULL;
3967 CHECK_ENV_NOT_CLOSED(self);
3969 err = self->db_env->set_shm_key(self->db_env, shm_key);
3970 RETURN_IF_ERR();
3971 RETURN_NONE();
3974 static PyObject*
3975 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3977 int err, gbytes=0, bytes=0, ncache=0;
3979 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3980 &gbytes, &bytes, &ncache))
3981 return NULL;
3982 CHECK_ENV_NOT_CLOSED(self);
3984 MYDB_BEGIN_ALLOW_THREADS;
3985 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3986 MYDB_END_ALLOW_THREADS;
3987 RETURN_IF_ERR();
3988 RETURN_NONE();
3992 #if (DBVER >= 32)
3993 static PyObject*
3994 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3996 int err, flags=0, onoff=0;
3998 if (!PyArg_ParseTuple(args, "ii:set_flags",
3999 &flags, &onoff))
4000 return NULL;
4001 CHECK_ENV_NOT_CLOSED(self);
4003 MYDB_BEGIN_ALLOW_THREADS;
4004 err = self->db_env->set_flags(self->db_env, flags, onoff);
4005 MYDB_END_ALLOW_THREADS;
4006 RETURN_IF_ERR();
4007 RETURN_NONE();
4009 #endif
4012 static PyObject*
4013 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4015 int err;
4016 char *dir;
4018 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4019 return NULL;
4020 CHECK_ENV_NOT_CLOSED(self);
4022 MYDB_BEGIN_ALLOW_THREADS;
4023 err = self->db_env->set_data_dir(self->db_env, dir);
4024 MYDB_END_ALLOW_THREADS;
4025 RETURN_IF_ERR();
4026 RETURN_NONE();
4030 static PyObject*
4031 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4033 int err, lg_bsize;
4035 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4036 return NULL;
4037 CHECK_ENV_NOT_CLOSED(self);
4039 MYDB_BEGIN_ALLOW_THREADS;
4040 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4041 MYDB_END_ALLOW_THREADS;
4042 RETURN_IF_ERR();
4043 RETURN_NONE();
4047 static PyObject*
4048 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4050 int err;
4051 char *dir;
4053 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4054 return NULL;
4055 CHECK_ENV_NOT_CLOSED(self);
4057 MYDB_BEGIN_ALLOW_THREADS;
4058 err = self->db_env->set_lg_dir(self->db_env, dir);
4059 MYDB_END_ALLOW_THREADS;
4060 RETURN_IF_ERR();
4061 RETURN_NONE();
4064 static PyObject*
4065 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4067 int err, lg_max;
4069 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4070 return NULL;
4071 CHECK_ENV_NOT_CLOSED(self);
4073 MYDB_BEGIN_ALLOW_THREADS;
4074 err = self->db_env->set_lg_max(self->db_env, lg_max);
4075 MYDB_END_ALLOW_THREADS;
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4081 #if (DBVER >= 33)
4082 static PyObject*
4083 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4085 int err, lg_max;
4087 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4091 MYDB_BEGIN_ALLOW_THREADS;
4092 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4093 MYDB_END_ALLOW_THREADS;
4094 RETURN_IF_ERR();
4095 RETURN_NONE();
4097 #endif
4100 static PyObject*
4101 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4103 int err, lk_detect;
4105 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4106 return NULL;
4107 CHECK_ENV_NOT_CLOSED(self);
4109 MYDB_BEGIN_ALLOW_THREADS;
4110 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4111 MYDB_END_ALLOW_THREADS;
4112 RETURN_IF_ERR();
4113 RETURN_NONE();
4117 static PyObject*
4118 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4120 int err, max;
4122 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4123 return NULL;
4124 CHECK_ENV_NOT_CLOSED(self);
4126 MYDB_BEGIN_ALLOW_THREADS;
4127 err = self->db_env->set_lk_max(self->db_env, max);
4128 MYDB_END_ALLOW_THREADS;
4129 RETURN_IF_ERR();
4130 RETURN_NONE();
4134 #if (DBVER >= 32)
4136 static PyObject*
4137 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4139 int err, max;
4141 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4142 return NULL;
4143 CHECK_ENV_NOT_CLOSED(self);
4145 MYDB_BEGIN_ALLOW_THREADS;
4146 err = self->db_env->set_lk_max_locks(self->db_env, max);
4147 MYDB_END_ALLOW_THREADS;
4148 RETURN_IF_ERR();
4149 RETURN_NONE();
4153 static PyObject*
4154 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4156 int err, max;
4158 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4159 return NULL;
4160 CHECK_ENV_NOT_CLOSED(self);
4162 MYDB_BEGIN_ALLOW_THREADS;
4163 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4164 MYDB_END_ALLOW_THREADS;
4165 RETURN_IF_ERR();
4166 RETURN_NONE();
4170 static PyObject*
4171 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4173 int err, max;
4175 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4176 return NULL;
4177 CHECK_ENV_NOT_CLOSED(self);
4179 MYDB_BEGIN_ALLOW_THREADS;
4180 err = self->db_env->set_lk_max_objects(self->db_env, max);
4181 MYDB_END_ALLOW_THREADS;
4182 RETURN_IF_ERR();
4183 RETURN_NONE();
4186 #endif
4189 static PyObject*
4190 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4192 int err, mp_mmapsize;
4194 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4195 return NULL;
4196 CHECK_ENV_NOT_CLOSED(self);
4198 MYDB_BEGIN_ALLOW_THREADS;
4199 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4200 MYDB_END_ALLOW_THREADS;
4201 RETURN_IF_ERR();
4202 RETURN_NONE();
4206 static PyObject*
4207 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4209 int err;
4210 char *dir;
4212 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4213 return NULL;
4214 CHECK_ENV_NOT_CLOSED(self);
4216 MYDB_BEGIN_ALLOW_THREADS;
4217 err = self->db_env->set_tmp_dir(self->db_env, dir);
4218 MYDB_END_ALLOW_THREADS;
4219 RETURN_IF_ERR();
4220 RETURN_NONE();
4224 static PyObject*
4225 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4227 int flags = 0;
4228 PyObject* txnobj = NULL;
4229 DB_TXN *txn = NULL;
4230 static char* kwnames[] = { "parent", "flags", NULL };
4232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4233 &txnobj, &flags))
4234 return NULL;
4236 if (!checkTxnObj(txnobj, &txn))
4237 return NULL;
4238 CHECK_ENV_NOT_CLOSED(self);
4240 return (PyObject*)newDBTxnObject(self, txn, flags);
4244 static PyObject*
4245 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4247 int err, kbyte=0, min=0, flags=0;
4249 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4250 return NULL;
4251 CHECK_ENV_NOT_CLOSED(self);
4253 MYDB_BEGIN_ALLOW_THREADS;
4254 #if (DBVER >= 40)
4255 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4256 #else
4257 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4258 #endif
4259 MYDB_END_ALLOW_THREADS;
4260 RETURN_IF_ERR();
4261 RETURN_NONE();
4265 static PyObject*
4266 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4268 int err, max;
4270 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4271 return NULL;
4272 CHECK_ENV_NOT_CLOSED(self);
4274 err = self->db_env->set_tx_max(self->db_env, max);
4275 RETURN_IF_ERR();
4276 RETURN_NONE();
4280 static PyObject*
4281 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4283 int err;
4284 long stamp;
4285 time_t timestamp;
4287 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4288 return NULL;
4289 CHECK_ENV_NOT_CLOSED(self);
4290 timestamp = (time_t)stamp;
4291 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4292 RETURN_IF_ERR();
4293 RETURN_NONE();
4297 static PyObject*
4298 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4300 int err, atype, flags=0;
4301 int aborted = 0;
4303 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4304 return NULL;
4305 CHECK_ENV_NOT_CLOSED(self);
4307 MYDB_BEGIN_ALLOW_THREADS;
4308 #if (DBVER >= 40)
4309 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4310 #else
4311 err = lock_detect(self->db_env, flags, atype, &aborted);
4312 #endif
4313 MYDB_END_ALLOW_THREADS;
4314 RETURN_IF_ERR();
4315 return PyInt_FromLong(aborted);
4319 static PyObject*
4320 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4322 int flags=0;
4323 int locker, lock_mode;
4324 DBT obj;
4325 PyObject* objobj;
4327 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4328 return NULL;
4331 if (!make_dbt(objobj, &obj))
4332 return NULL;
4334 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4338 static PyObject*
4339 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4341 int err;
4342 u_int32_t theID;
4344 if (!PyArg_ParseTuple(args, ":lock_id"))
4345 return NULL;
4347 CHECK_ENV_NOT_CLOSED(self);
4348 MYDB_BEGIN_ALLOW_THREADS;
4349 #if (DBVER >= 40)
4350 err = self->db_env->lock_id(self->db_env, &theID);
4351 #else
4352 err = lock_id(self->db_env, &theID);
4353 #endif
4354 MYDB_END_ALLOW_THREADS;
4355 RETURN_IF_ERR();
4357 return PyInt_FromLong((long)theID);
4361 static PyObject*
4362 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4364 int err;
4365 DBLockObject* dblockobj;
4367 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4368 return NULL;
4370 CHECK_ENV_NOT_CLOSED(self);
4371 MYDB_BEGIN_ALLOW_THREADS;
4372 #if (DBVER >= 40)
4373 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4374 #else
4375 err = lock_put(self->db_env, &dblockobj->lock);
4376 #endif
4377 MYDB_END_ALLOW_THREADS;
4378 RETURN_IF_ERR();
4379 RETURN_NONE();
4382 #if (DBVER >= 44)
4383 static PyObject*
4384 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4386 int err;
4387 char *file;
4388 u_int32_t flags = 0;
4389 static char* kwnames[] = { "file", "flags", NULL};
4391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4392 &file, &flags))
4393 return NULL;
4394 CHECK_ENV_NOT_CLOSED(self);
4396 MYDB_BEGIN_ALLOW_THREADS;
4397 err = self->db_env->lsn_reset(self->db_env, file, flags);
4398 MYDB_END_ALLOW_THREADS;
4399 RETURN_IF_ERR();
4400 RETURN_NONE();
4402 #endif /* DBVER >= 4.4 */
4404 #if (DBVER >= 40)
4405 static PyObject*
4406 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4408 int err;
4409 DB_LOG_STAT* statp = NULL;
4410 PyObject* d = NULL;
4411 u_int32_t flags = 0;
4413 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4414 return NULL;
4415 CHECK_ENV_NOT_CLOSED(self);
4417 MYDB_BEGIN_ALLOW_THREADS;
4418 err = self->db_env->log_stat(self->db_env, &statp, flags);
4419 MYDB_END_ALLOW_THREADS;
4420 RETURN_IF_ERR();
4422 /* Turn the stat structure into a dictionary */
4423 d = PyDict_New();
4424 if (d == NULL) {
4425 if (statp)
4426 free(statp);
4427 return NULL;
4430 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4432 MAKE_ENTRY(magic);
4433 MAKE_ENTRY(version);
4434 MAKE_ENTRY(mode);
4435 MAKE_ENTRY(lg_bsize);
4436 #if (DBVER >= 44)
4437 MAKE_ENTRY(lg_size);
4438 MAKE_ENTRY(record);
4439 #endif
4440 #if (DBVER <= 40)
4441 MAKE_ENTRY(lg_max);
4442 #endif
4443 MAKE_ENTRY(w_mbytes);
4444 MAKE_ENTRY(w_bytes);
4445 MAKE_ENTRY(wc_mbytes);
4446 MAKE_ENTRY(wc_bytes);
4447 MAKE_ENTRY(wcount);
4448 MAKE_ENTRY(wcount_fill);
4449 #if (DBVER >= 44)
4450 MAKE_ENTRY(rcount);
4451 #endif
4452 MAKE_ENTRY(scount);
4453 MAKE_ENTRY(cur_file);
4454 MAKE_ENTRY(cur_offset);
4455 MAKE_ENTRY(disk_file);
4456 MAKE_ENTRY(disk_offset);
4457 MAKE_ENTRY(maxcommitperflush);
4458 MAKE_ENTRY(mincommitperflush);
4459 MAKE_ENTRY(regsize);
4460 MAKE_ENTRY(region_wait);
4461 MAKE_ENTRY(region_nowait);
4463 #undef MAKE_ENTRY
4464 free(statp);
4465 return d;
4466 } /* DBEnv_log_stat */
4467 #endif /* DBVER >= 4.0 for log_stat method */
4470 static PyObject*
4471 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4473 int err;
4474 DB_LOCK_STAT* sp;
4475 PyObject* d = NULL;
4476 u_int32_t flags = 0;
4478 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4479 return NULL;
4480 CHECK_ENV_NOT_CLOSED(self);
4482 MYDB_BEGIN_ALLOW_THREADS;
4483 #if (DBVER >= 40)
4484 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4485 #else
4486 #if (DBVER >= 33)
4487 err = lock_stat(self->db_env, &sp);
4488 #else
4489 err = lock_stat(self->db_env, &sp, NULL);
4490 #endif
4491 #endif
4492 MYDB_END_ALLOW_THREADS;
4493 RETURN_IF_ERR();
4495 /* Turn the stat structure into a dictionary */
4496 d = PyDict_New();
4497 if (d == NULL) {
4498 free(sp);
4499 return NULL;
4502 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4504 #if (DBVER < 41)
4505 MAKE_ENTRY(lastid);
4506 #endif
4507 MAKE_ENTRY(nmodes);
4508 #if (DBVER >= 32)
4509 MAKE_ENTRY(maxlocks);
4510 MAKE_ENTRY(maxlockers);
4511 MAKE_ENTRY(maxobjects);
4512 MAKE_ENTRY(nlocks);
4513 MAKE_ENTRY(maxnlocks);
4514 #endif
4515 MAKE_ENTRY(nlockers);
4516 MAKE_ENTRY(maxnlockers);
4517 #if (DBVER >= 32)
4518 MAKE_ENTRY(nobjects);
4519 MAKE_ENTRY(maxnobjects);
4520 #endif
4521 MAKE_ENTRY(nrequests);
4522 MAKE_ENTRY(nreleases);
4523 #if (DBVER < 44)
4524 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4525 MAKE_ENTRY(nconflicts);
4526 #else
4527 MAKE_ENTRY(lock_nowait);
4528 MAKE_ENTRY(lock_wait);
4529 #endif
4530 MAKE_ENTRY(ndeadlocks);
4531 MAKE_ENTRY(regsize);
4532 MAKE_ENTRY(region_wait);
4533 MAKE_ENTRY(region_nowait);
4535 #undef MAKE_ENTRY
4536 free(sp);
4537 return d;
4541 static PyObject*
4542 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4544 int flags=0;
4545 int err;
4546 char **log_list = NULL;
4547 PyObject* list;
4548 PyObject* item = NULL;
4550 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4551 return NULL;
4553 CHECK_ENV_NOT_CLOSED(self);
4554 MYDB_BEGIN_ALLOW_THREADS;
4555 #if (DBVER >= 40)
4556 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4557 #elif (DBVER == 33)
4558 err = log_archive(self->db_env, &log_list, flags);
4559 #else
4560 err = log_archive(self->db_env, &log_list, flags, NULL);
4561 #endif
4562 MYDB_END_ALLOW_THREADS;
4563 RETURN_IF_ERR();
4565 list = PyList_New(0);
4566 if (list == NULL) {
4567 if (log_list)
4568 free(log_list);
4569 return NULL;
4572 if (log_list) {
4573 char **log_list_start;
4574 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4575 item = PyString_FromString (*log_list);
4576 if (item == NULL) {
4577 Py_DECREF(list);
4578 list = NULL;
4579 break;
4581 PyList_Append(list, item);
4582 Py_DECREF(item);
4584 free(log_list_start);
4586 return list;
4590 static PyObject*
4591 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4593 int err;
4594 DB_TXN_STAT* sp;
4595 PyObject* d = NULL;
4596 u_int32_t flags=0;
4598 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4599 return NULL;
4600 CHECK_ENV_NOT_CLOSED(self);
4602 MYDB_BEGIN_ALLOW_THREADS;
4603 #if (DBVER >= 40)
4604 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4605 #elif (DBVER == 33)
4606 err = txn_stat(self->db_env, &sp);
4607 #else
4608 err = txn_stat(self->db_env, &sp, NULL);
4609 #endif
4610 MYDB_END_ALLOW_THREADS;
4611 RETURN_IF_ERR();
4613 /* Turn the stat structure into a dictionary */
4614 d = PyDict_New();
4615 if (d == NULL) {
4616 free(sp);
4617 return NULL;
4620 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4622 MAKE_ENTRY(time_ckp);
4623 MAKE_ENTRY(last_txnid);
4624 MAKE_ENTRY(maxtxns);
4625 MAKE_ENTRY(nactive);
4626 MAKE_ENTRY(maxnactive);
4627 MAKE_ENTRY(nbegins);
4628 MAKE_ENTRY(naborts);
4629 MAKE_ENTRY(ncommits);
4630 MAKE_ENTRY(regsize);
4631 MAKE_ENTRY(region_wait);
4632 MAKE_ENTRY(region_nowait);
4634 #undef MAKE_ENTRY
4635 free(sp);
4636 return d;
4640 static PyObject*
4641 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4643 int flags=0;
4644 int oldValue=0;
4646 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4647 return NULL;
4648 CHECK_ENV_NOT_CLOSED(self);
4650 if (self->moduleFlags.getReturnsNone)
4651 ++oldValue;
4652 if (self->moduleFlags.cursorSetReturnsNone)
4653 ++oldValue;
4654 self->moduleFlags.getReturnsNone = (flags >= 1);
4655 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4656 return PyInt_FromLong(oldValue);
4660 /* --------------------------------------------------------------------- */
4661 /* DBTxn methods */
4664 static PyObject*
4665 DBTxn_commit(DBTxnObject* self, PyObject* args)
4667 int flags=0, err;
4668 DB_TXN *txn;
4670 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4671 return NULL;
4673 if (!self->txn) {
4674 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4675 "after txn_commit or txn_abort");
4676 PyErr_SetObject(DBError, t);
4677 Py_DECREF(t);
4678 return NULL;
4680 txn = self->txn;
4681 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4682 MYDB_BEGIN_ALLOW_THREADS;
4683 #if (DBVER >= 40)
4684 err = txn->commit(txn, flags);
4685 #else
4686 err = txn_commit(txn, flags);
4687 #endif
4688 MYDB_END_ALLOW_THREADS;
4689 RETURN_IF_ERR();
4690 RETURN_NONE();
4693 static PyObject*
4694 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4696 #if (DBVER >= 33)
4697 int err;
4698 char* gid=NULL;
4699 int gid_size=0;
4701 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4702 return NULL;
4704 if (gid_size != DB_XIDDATASIZE) {
4705 PyErr_SetString(PyExc_TypeError,
4706 "gid must be DB_XIDDATASIZE bytes long");
4707 return NULL;
4710 if (!self->txn) {
4711 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4712 "after txn_commit or txn_abort");
4713 PyErr_SetObject(DBError, t);
4714 Py_DECREF(t);
4715 return NULL;
4717 MYDB_BEGIN_ALLOW_THREADS;
4718 #if (DBVER >= 40)
4719 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4720 #else
4721 err = txn_prepare(self->txn, (u_int8_t*)gid);
4722 #endif
4723 MYDB_END_ALLOW_THREADS;
4724 RETURN_IF_ERR();
4725 RETURN_NONE();
4726 #else
4727 int err;
4729 if (!PyArg_ParseTuple(args, ":prepare"))
4730 return NULL;
4732 if (!self->txn) {
4733 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4734 "after txn_commit or txn_abort");
4735 PyErr_SetObject(DBError, t);
4736 Py_DECREF(t);
4737 return NULL;
4739 MYDB_BEGIN_ALLOW_THREADS;
4740 err = txn_prepare(self->txn);
4741 MYDB_END_ALLOW_THREADS;
4742 RETURN_IF_ERR();
4743 RETURN_NONE();
4744 #endif
4748 static PyObject*
4749 DBTxn_abort(DBTxnObject* self, PyObject* args)
4751 int err;
4752 DB_TXN *txn;
4754 if (!PyArg_ParseTuple(args, ":abort"))
4755 return NULL;
4757 if (!self->txn) {
4758 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4759 "after txn_commit or txn_abort");
4760 PyErr_SetObject(DBError, t);
4761 Py_DECREF(t);
4762 return NULL;
4764 txn = self->txn;
4765 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4766 MYDB_BEGIN_ALLOW_THREADS;
4767 #if (DBVER >= 40)
4768 err = txn->abort(txn);
4769 #else
4770 err = txn_abort(txn);
4771 #endif
4772 MYDB_END_ALLOW_THREADS;
4773 RETURN_IF_ERR();
4774 RETURN_NONE();
4778 static PyObject*
4779 DBTxn_id(DBTxnObject* self, PyObject* args)
4781 int id;
4783 if (!PyArg_ParseTuple(args, ":id"))
4784 return NULL;
4786 if (!self->txn) {
4787 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4788 "after txn_commit or txn_abort");
4789 PyErr_SetObject(DBError, t);
4790 Py_DECREF(t);
4791 return NULL;
4793 MYDB_BEGIN_ALLOW_THREADS;
4794 #if (DBVER >= 40)
4795 id = self->txn->id(self->txn);
4796 #else
4797 id = txn_id(self->txn);
4798 #endif
4799 MYDB_END_ALLOW_THREADS;
4800 return PyInt_FromLong(id);
4803 #if (DBVER >= 43)
4804 /* --------------------------------------------------------------------- */
4805 /* DBSequence methods */
4808 static PyObject*
4809 DBSequence_close(DBSequenceObject* self, PyObject* args)
4811 int err, flags=0;
4812 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4813 return NULL;
4814 CHECK_SEQUENCE_NOT_CLOSED(self)
4816 MYDB_BEGIN_ALLOW_THREADS
4817 err = self->sequence->close(self->sequence, flags);
4818 self->sequence = NULL;
4819 MYDB_END_ALLOW_THREADS
4821 RETURN_IF_ERR();
4823 RETURN_NONE();
4826 static PyObject*
4827 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4829 int err, flags = 0;
4830 int delta = 1;
4831 db_seq_t value;
4832 PyObject *txnobj = NULL;
4833 DB_TXN *txn = NULL;
4834 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4835 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4836 return NULL;
4837 CHECK_SEQUENCE_NOT_CLOSED(self)
4839 if (!checkTxnObj(txnobj, &txn))
4840 return NULL;
4842 MYDB_BEGIN_ALLOW_THREADS
4843 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4844 MYDB_END_ALLOW_THREADS
4846 RETURN_IF_ERR();
4847 return PyLong_FromLongLong(value);
4851 static PyObject*
4852 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4854 if (!PyArg_ParseTuple(args,":get_dbp"))
4855 return NULL;
4856 CHECK_SEQUENCE_NOT_CLOSED(self)
4857 Py_INCREF(self->mydb);
4858 return (PyObject* )self->mydb;
4861 static PyObject*
4862 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4864 int err;
4865 DBT key;
4866 CHECK_SEQUENCE_NOT_CLOSED(self)
4867 MYDB_BEGIN_ALLOW_THREADS
4868 err = self->sequence->get_key(self->sequence, &key);
4869 MYDB_END_ALLOW_THREADS
4871 RETURN_IF_ERR();
4873 return PyString_FromStringAndSize(key.data, key.size);
4876 static PyObject*
4877 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4879 int err;
4880 db_seq_t value;
4881 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4882 return NULL;
4883 CHECK_SEQUENCE_NOT_CLOSED(self)
4885 MYDB_BEGIN_ALLOW_THREADS
4886 err = self->sequence->initial_value(self->sequence, value);
4887 MYDB_END_ALLOW_THREADS
4889 RETURN_IF_ERR();
4891 RETURN_NONE();
4894 static PyObject*
4895 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4897 int err, flags = 0;
4898 PyObject* keyobj;
4899 PyObject *txnobj = NULL;
4900 DB_TXN *txn = NULL;
4901 DBT key;
4903 static char* kwnames[] = {"key", "txn", "flags", NULL };
4904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4905 return NULL;
4907 if (!checkTxnObj(txnobj, &txn))
4908 return NULL;
4910 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4911 return NULL;
4913 MYDB_BEGIN_ALLOW_THREADS
4914 err = self->sequence->open(self->sequence, txn, &key, flags);
4915 MYDB_END_ALLOW_THREADS
4917 CLEAR_DBT(key);
4918 RETURN_IF_ERR();
4920 RETURN_NONE();
4923 static PyObject*
4924 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4926 int err, flags = 0;
4927 PyObject *txnobj = NULL;
4928 DB_TXN *txn = NULL;
4930 static char* kwnames[] = {"txn", "flags", NULL };
4931 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4932 return NULL;
4934 if (!checkTxnObj(txnobj, &txn))
4935 return NULL;
4937 CHECK_SEQUENCE_NOT_CLOSED(self)
4939 MYDB_BEGIN_ALLOW_THREADS
4940 err = self->sequence->remove(self->sequence, txn, flags);
4941 MYDB_END_ALLOW_THREADS
4943 RETURN_IF_ERR();
4944 RETURN_NONE();
4947 static PyObject*
4948 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4950 int err, size;
4951 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4952 return NULL;
4953 CHECK_SEQUENCE_NOT_CLOSED(self)
4955 MYDB_BEGIN_ALLOW_THREADS
4956 err = self->sequence->set_cachesize(self->sequence, size);
4957 MYDB_END_ALLOW_THREADS
4959 RETURN_IF_ERR();
4960 RETURN_NONE();
4963 static PyObject*
4964 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4966 int err, size;
4967 if (!PyArg_ParseTuple(args,":get_cachesize"))
4968 return NULL;
4969 CHECK_SEQUENCE_NOT_CLOSED(self)
4971 MYDB_BEGIN_ALLOW_THREADS
4972 err = self->sequence->get_cachesize(self->sequence, &size);
4973 MYDB_END_ALLOW_THREADS
4975 RETURN_IF_ERR();
4976 return PyInt_FromLong(size);
4979 static PyObject*
4980 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4982 int err, flags = 0;
4983 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4984 return NULL;
4985 CHECK_SEQUENCE_NOT_CLOSED(self)
4987 MYDB_BEGIN_ALLOW_THREADS
4988 err = self->sequence->set_flags(self->sequence, flags);
4989 MYDB_END_ALLOW_THREADS
4991 RETURN_IF_ERR();
4992 RETURN_NONE();
4996 static PyObject*
4997 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4999 unsigned int flags;
5000 int err;
5001 if (!PyArg_ParseTuple(args,":get_flags"))
5002 return NULL;
5003 CHECK_SEQUENCE_NOT_CLOSED(self)
5005 MYDB_BEGIN_ALLOW_THREADS
5006 err = self->sequence->get_flags(self->sequence, &flags);
5007 MYDB_END_ALLOW_THREADS
5009 RETURN_IF_ERR();
5010 return PyInt_FromLong((int)flags);
5013 static PyObject*
5014 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5016 int err;
5017 db_seq_t min, max;
5018 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5019 return NULL;
5020 CHECK_SEQUENCE_NOT_CLOSED(self)
5022 MYDB_BEGIN_ALLOW_THREADS
5023 err = self->sequence->set_range(self->sequence, min, max);
5024 MYDB_END_ALLOW_THREADS
5026 RETURN_IF_ERR();
5027 RETURN_NONE();
5030 static PyObject*
5031 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5033 int err;
5034 db_seq_t min, max;
5035 if (!PyArg_ParseTuple(args,":get_range"))
5036 return NULL;
5037 CHECK_SEQUENCE_NOT_CLOSED(self)
5039 MYDB_BEGIN_ALLOW_THREADS
5040 err = self->sequence->get_range(self->sequence, &min, &max);
5041 MYDB_END_ALLOW_THREADS
5043 RETURN_IF_ERR();
5044 return Py_BuildValue("(LL)", min, max);
5047 static PyObject*
5048 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5050 int err, flags = 0;
5051 DB_SEQUENCE_STAT* sp = NULL;
5052 PyObject* dict_stat;
5053 static char* kwnames[] = {"flags", NULL };
5054 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5055 return NULL;
5056 CHECK_SEQUENCE_NOT_CLOSED(self);
5058 MYDB_BEGIN_ALLOW_THREADS;
5059 err = self->sequence->stat(self->sequence, &sp, flags);
5060 MYDB_END_ALLOW_THREADS;
5061 RETURN_IF_ERR();
5063 if ((dict_stat = PyDict_New()) == NULL) {
5064 free(sp);
5065 return NULL;
5069 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5070 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5072 MAKE_INT_ENTRY(wait);
5073 MAKE_INT_ENTRY(nowait);
5074 MAKE_LONG_LONG_ENTRY(current);
5075 MAKE_LONG_LONG_ENTRY(value);
5076 MAKE_LONG_LONG_ENTRY(last_value);
5077 MAKE_LONG_LONG_ENTRY(min);
5078 MAKE_LONG_LONG_ENTRY(max);
5079 MAKE_INT_ENTRY(cache_size);
5080 MAKE_INT_ENTRY(flags);
5082 #undef MAKE_INT_ENTRY
5083 #undef MAKE_LONG_LONG_ENTRY
5085 free(sp);
5086 return dict_stat;
5088 #endif
5091 /* --------------------------------------------------------------------- */
5092 /* Method definition tables and type objects */
5094 static PyMethodDef DB_methods[] = {
5095 {"append", (PyCFunction)DB_append, METH_VARARGS},
5096 #if (DBVER >= 33)
5097 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5098 #endif
5099 {"close", (PyCFunction)DB_close, METH_VARARGS},
5100 #if (DBVER >= 32)
5101 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5102 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5103 #endif
5104 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5105 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5106 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5107 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5108 #if (DBVER >= 33)
5109 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5110 #endif
5111 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5112 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5113 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5114 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5115 {"join", (PyCFunction)DB_join, METH_VARARGS},
5116 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5117 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5118 {"items", (PyCFunction)DB_items, METH_VARARGS},
5119 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5120 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5121 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5122 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5123 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5124 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5125 #if (DBVER >= 33)
5126 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5127 #endif
5128 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5129 #if (DBVER >= 41)
5130 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5131 #endif
5132 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5133 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5134 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5135 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5136 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5137 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5138 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5139 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5140 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5141 #if (DBVER >= 32)
5142 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5143 #endif
5144 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5145 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5146 #if (DBVER >= 33)
5147 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5148 #endif
5149 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5150 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5151 {"values", (PyCFunction)DB_values, METH_VARARGS},
5152 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5153 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5154 {NULL, NULL} /* sentinel */
5158 static PyMappingMethods DB_mapping = {
5159 DB_length, /*mp_length*/
5160 (binaryfunc)DB_subscript, /*mp_subscript*/
5161 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5165 static PyMethodDef DBCursor_methods[] = {
5166 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5167 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5168 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5169 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5170 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5171 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5172 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5173 #if (DBVER >= 33)
5174 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5175 #endif
5176 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5177 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5178 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5179 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5180 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5181 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5182 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5183 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5184 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5185 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5186 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5187 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5188 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5189 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5190 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5191 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5192 {NULL, NULL} /* sentinel */
5196 static PyMethodDef DBEnv_methods[] = {
5197 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5198 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5199 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5200 #if (DBVER >= 41)
5201 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5202 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5203 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5204 #endif
5205 #if (DBVER >= 40)
5206 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5207 #endif
5208 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5209 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5210 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5211 #if (DBVER >= 32)
5212 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5213 #endif
5214 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5215 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5216 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5217 #if (DBVER >= 33)
5218 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5219 #endif
5220 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5221 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5222 #if (DBVER >= 32)
5223 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5224 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5225 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5226 #endif
5227 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5228 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5229 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5230 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5231 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5232 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5233 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5234 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5235 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5236 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5237 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5238 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5239 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5240 #if (DBVER >= 40)
5241 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5242 #endif
5243 #if (DBVER >= 44)
5244 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5245 #endif
5246 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5247 {NULL, NULL} /* sentinel */
5251 static PyMethodDef DBTxn_methods[] = {
5252 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5253 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5254 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5255 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5256 {NULL, NULL} /* sentinel */
5260 #if (DBVER >= 43)
5261 static PyMethodDef DBSequence_methods[] = {
5262 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5263 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5264 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5265 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5266 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5267 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5268 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5269 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5270 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5271 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5272 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5273 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5274 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5275 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5276 {NULL, NULL} /* sentinel */
5278 #endif
5281 static PyObject*
5282 DB_getattr(DBObject* self, char *name)
5284 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5288 static PyObject*
5289 DBEnv_getattr(DBEnvObject* self, char *name)
5291 if (!strcmp(name, "db_home")) {
5292 CHECK_ENV_NOT_CLOSED(self);
5293 if (self->db_env->db_home == NULL) {
5294 RETURN_NONE();
5296 return PyString_FromString(self->db_env->db_home);
5299 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5303 static PyObject*
5304 DBCursor_getattr(DBCursorObject* self, char *name)
5306 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5309 static PyObject*
5310 DBTxn_getattr(DBTxnObject* self, char *name)
5312 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5315 static PyObject*
5316 DBLock_getattr(DBLockObject* self, char *name)
5318 return NULL;
5321 #if (DBVER >= 43)
5322 static PyObject*
5323 DBSequence_getattr(DBSequenceObject* self, char *name)
5325 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5327 #endif
5329 statichere PyTypeObject DB_Type = {
5330 PyObject_HEAD_INIT(NULL)
5331 0, /*ob_size*/
5332 "DB", /*tp_name*/
5333 sizeof(DBObject), /*tp_basicsize*/
5334 0, /*tp_itemsize*/
5335 /* methods */
5336 (destructor)DB_dealloc, /*tp_dealloc*/
5337 0, /*tp_print*/
5338 (getattrfunc)DB_getattr, /*tp_getattr*/
5339 0, /*tp_setattr*/
5340 0, /*tp_compare*/
5341 0, /*tp_repr*/
5342 0, /*tp_as_number*/
5343 0, /*tp_as_sequence*/
5344 &DB_mapping,/*tp_as_mapping*/
5345 0, /*tp_hash*/
5346 #ifdef HAVE_WEAKREF
5347 0, /* tp_call */
5348 0, /* tp_str */
5349 0, /* tp_getattro */
5350 0, /* tp_setattro */
5351 0, /* tp_as_buffer */
5352 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5353 0, /* tp_doc */
5354 0, /* tp_traverse */
5355 0, /* tp_clear */
5356 0, /* tp_richcompare */
5357 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5358 #endif
5362 statichere PyTypeObject DBCursor_Type = {
5363 PyObject_HEAD_INIT(NULL)
5364 0, /*ob_size*/
5365 "DBCursor", /*tp_name*/
5366 sizeof(DBCursorObject), /*tp_basicsize*/
5367 0, /*tp_itemsize*/
5368 /* methods */
5369 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5370 0, /*tp_print*/
5371 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5372 0, /*tp_setattr*/
5373 0, /*tp_compare*/
5374 0, /*tp_repr*/
5375 0, /*tp_as_number*/
5376 0, /*tp_as_sequence*/
5377 0, /*tp_as_mapping*/
5378 0, /*tp_hash*/
5379 #ifdef HAVE_WEAKREF
5380 0, /* tp_call */
5381 0, /* tp_str */
5382 0, /* tp_getattro */
5383 0, /* tp_setattro */
5384 0, /* tp_as_buffer */
5385 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5386 0, /* tp_doc */
5387 0, /* tp_traverse */
5388 0, /* tp_clear */
5389 0, /* tp_richcompare */
5390 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5391 #endif
5395 statichere PyTypeObject DBEnv_Type = {
5396 PyObject_HEAD_INIT(NULL)
5397 0, /*ob_size*/
5398 "DBEnv", /*tp_name*/
5399 sizeof(DBEnvObject), /*tp_basicsize*/
5400 0, /*tp_itemsize*/
5401 /* methods */
5402 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5403 0, /*tp_print*/
5404 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5405 0, /*tp_setattr*/
5406 0, /*tp_compare*/
5407 0, /*tp_repr*/
5408 0, /*tp_as_number*/
5409 0, /*tp_as_sequence*/
5410 0, /*tp_as_mapping*/
5411 0, /*tp_hash*/
5412 #ifdef HAVE_WEAKREF
5413 0, /* tp_call */
5414 0, /* tp_str */
5415 0, /* tp_getattro */
5416 0, /* tp_setattro */
5417 0, /* tp_as_buffer */
5418 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5419 0, /* tp_doc */
5420 0, /* tp_traverse */
5421 0, /* tp_clear */
5422 0, /* tp_richcompare */
5423 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5424 #endif
5427 statichere PyTypeObject DBTxn_Type = {
5428 PyObject_HEAD_INIT(NULL)
5429 0, /*ob_size*/
5430 "DBTxn", /*tp_name*/
5431 sizeof(DBTxnObject), /*tp_basicsize*/
5432 0, /*tp_itemsize*/
5433 /* methods */
5434 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5435 0, /*tp_print*/
5436 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5437 0, /*tp_setattr*/
5438 0, /*tp_compare*/
5439 0, /*tp_repr*/
5440 0, /*tp_as_number*/
5441 0, /*tp_as_sequence*/
5442 0, /*tp_as_mapping*/
5443 0, /*tp_hash*/
5444 #ifdef HAVE_WEAKREF
5445 0, /* tp_call */
5446 0, /* tp_str */
5447 0, /* tp_getattro */
5448 0, /* tp_setattro */
5449 0, /* tp_as_buffer */
5450 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5451 0, /* tp_doc */
5452 0, /* tp_traverse */
5453 0, /* tp_clear */
5454 0, /* tp_richcompare */
5455 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5456 #endif
5460 statichere PyTypeObject DBLock_Type = {
5461 PyObject_HEAD_INIT(NULL)
5462 0, /*ob_size*/
5463 "DBLock", /*tp_name*/
5464 sizeof(DBLockObject), /*tp_basicsize*/
5465 0, /*tp_itemsize*/
5466 /* methods */
5467 (destructor)DBLock_dealloc, /*tp_dealloc*/
5468 0, /*tp_print*/
5469 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5470 0, /*tp_setattr*/
5471 0, /*tp_compare*/
5472 0, /*tp_repr*/
5473 0, /*tp_as_number*/
5474 0, /*tp_as_sequence*/
5475 0, /*tp_as_mapping*/
5476 0, /*tp_hash*/
5477 #ifdef HAVE_WEAKREF
5478 0, /* tp_call */
5479 0, /* tp_str */
5480 0, /* tp_getattro */
5481 0, /* tp_setattro */
5482 0, /* tp_as_buffer */
5483 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5484 0, /* tp_doc */
5485 0, /* tp_traverse */
5486 0, /* tp_clear */
5487 0, /* tp_richcompare */
5488 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5489 #endif
5492 #if (DBVER >= 43)
5493 statichere PyTypeObject DBSequence_Type = {
5494 PyObject_HEAD_INIT(NULL)
5495 0, /*ob_size*/
5496 "DBSequence", /*tp_name*/
5497 sizeof(DBSequenceObject), /*tp_basicsize*/
5498 0, /*tp_itemsize*/
5499 /* methods */
5500 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5501 0, /*tp_print*/
5502 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5503 0, /*tp_setattr*/
5504 0, /*tp_compare*/
5505 0, /*tp_repr*/
5506 0, /*tp_as_number*/
5507 0, /*tp_as_sequence*/
5508 0, /*tp_as_mapping*/
5509 0, /*tp_hash*/
5510 #ifdef HAVE_WEAKREF
5511 0, /* tp_call */
5512 0, /* tp_str */
5513 0, /* tp_getattro */
5514 0, /* tp_setattro */
5515 0, /* tp_as_buffer */
5516 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5517 0, /* tp_doc */
5518 0, /* tp_traverse */
5519 0, /* tp_clear */
5520 0, /* tp_richcompare */
5521 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5522 #endif
5524 #endif
5526 /* --------------------------------------------------------------------- */
5527 /* Module-level functions */
5529 static PyObject*
5530 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5532 PyObject* dbenvobj = NULL;
5533 int flags = 0;
5534 static char* kwnames[] = { "dbEnv", "flags", NULL};
5536 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5537 &dbenvobj, &flags))
5538 return NULL;
5539 if (dbenvobj == Py_None)
5540 dbenvobj = NULL;
5541 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5542 makeTypeError("DBEnv", dbenvobj);
5543 return NULL;
5546 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5550 static PyObject*
5551 DBEnv_construct(PyObject* self, PyObject* args)
5553 int flags = 0;
5554 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5555 return (PyObject* )newDBEnvObject(flags);
5558 #if (DBVER >= 43)
5559 static PyObject*
5560 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5562 PyObject* dbobj;
5563 int flags = 0;
5564 static char* kwnames[] = { "db", "flags", NULL};
5566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5567 return NULL;
5568 if (!DBObject_Check(dbobj)) {
5569 makeTypeError("DB", dbobj);
5570 return NULL;
5572 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5574 #endif
5576 static char bsddb_version_doc[] =
5577 "Returns a tuple of major, minor, and patch release numbers of the\n\
5578 underlying DB library.";
5580 static PyObject*
5581 bsddb_version(PyObject* self, PyObject* args)
5583 int major, minor, patch;
5585 if (!PyArg_ParseTuple(args, ":version"))
5586 return NULL;
5587 db_version(&major, &minor, &patch);
5588 return Py_BuildValue("(iii)", major, minor, patch);
5592 /* List of functions defined in the module */
5594 static PyMethodDef bsddb_methods[] = {
5595 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5596 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5597 #if (DBVER >= 43)
5598 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5599 #endif
5600 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5601 {NULL, NULL} /* sentinel */
5605 /* --------------------------------------------------------------------- */
5606 /* Module initialization */
5609 /* Convenience routine to export an integer value.
5610 * Errors are silently ignored, for better or for worse...
5612 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5614 #define MODULE_NAME_MAX_LEN 11
5615 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5617 DL_EXPORT(void) init_bsddb(void)
5619 PyObject* m;
5620 PyObject* d;
5621 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5622 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5623 PyObject* cvsid_s = PyString_FromString( rcs_id );
5625 /* Initialize the type of the new type objects here; doing it here
5626 is required for portability to Windows without requiring C++. */
5627 DB_Type.ob_type = &PyType_Type;
5628 DBCursor_Type.ob_type = &PyType_Type;
5629 DBEnv_Type.ob_type = &PyType_Type;
5630 DBTxn_Type.ob_type = &PyType_Type;
5631 DBLock_Type.ob_type = &PyType_Type;
5632 #if (DBVER >= 43)
5633 DBSequence_Type.ob_type = &PyType_Type;
5634 #endif
5637 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5638 /* Save the current interpreter, so callbacks can do the right thing. */
5639 _db_interpreterState = PyThreadState_GET()->interp;
5640 #endif
5642 /* Create the module and add the functions */
5643 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5644 if (m == NULL)
5645 return;
5647 /* Add some symbolic constants to the module */
5648 d = PyModule_GetDict(m);
5649 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5650 PyDict_SetItemString(d, "cvsid", cvsid_s);
5651 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5652 Py_DECREF(pybsddb_version_s);
5653 pybsddb_version_s = NULL;
5654 Py_DECREF(cvsid_s);
5655 cvsid_s = NULL;
5656 Py_DECREF(db_version_s);
5657 db_version_s = NULL;
5659 ADD_INT(d, DB_VERSION_MAJOR);
5660 ADD_INT(d, DB_VERSION_MINOR);
5661 ADD_INT(d, DB_VERSION_PATCH);
5663 ADD_INT(d, DB_MAX_PAGES);
5664 ADD_INT(d, DB_MAX_RECORDS);
5666 #if (DBVER >= 42)
5667 ADD_INT(d, DB_RPCCLIENT);
5668 #else
5669 ADD_INT(d, DB_CLIENT);
5670 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5671 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5672 #endif
5673 ADD_INT(d, DB_XA_CREATE);
5675 ADD_INT(d, DB_CREATE);
5676 ADD_INT(d, DB_NOMMAP);
5677 ADD_INT(d, DB_THREAD);
5679 ADD_INT(d, DB_FORCE);
5680 ADD_INT(d, DB_INIT_CDB);
5681 ADD_INT(d, DB_INIT_LOCK);
5682 ADD_INT(d, DB_INIT_LOG);
5683 ADD_INT(d, DB_INIT_MPOOL);
5684 ADD_INT(d, DB_INIT_TXN);
5685 #if (DBVER >= 32)
5686 ADD_INT(d, DB_JOINENV);
5687 #endif
5689 ADD_INT(d, DB_RECOVER);
5690 ADD_INT(d, DB_RECOVER_FATAL);
5691 ADD_INT(d, DB_TXN_NOSYNC);
5692 ADD_INT(d, DB_USE_ENVIRON);
5693 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5695 ADD_INT(d, DB_LOCKDOWN);
5696 ADD_INT(d, DB_PRIVATE);
5697 ADD_INT(d, DB_SYSTEM_MEM);
5699 ADD_INT(d, DB_TXN_SYNC);
5700 ADD_INT(d, DB_TXN_NOWAIT);
5702 ADD_INT(d, DB_EXCL);
5703 ADD_INT(d, DB_FCNTL_LOCKING);
5704 ADD_INT(d, DB_ODDFILESIZE);
5705 ADD_INT(d, DB_RDWRMASTER);
5706 ADD_INT(d, DB_RDONLY);
5707 ADD_INT(d, DB_TRUNCATE);
5708 #if (DBVER >= 32)
5709 ADD_INT(d, DB_EXTENT);
5710 ADD_INT(d, DB_CDB_ALLDB);
5711 ADD_INT(d, DB_VERIFY);
5712 #endif
5713 ADD_INT(d, DB_UPGRADE);
5715 ADD_INT(d, DB_AGGRESSIVE);
5716 ADD_INT(d, DB_NOORDERCHK);
5717 ADD_INT(d, DB_ORDERCHKONLY);
5718 ADD_INT(d, DB_PR_PAGE);
5719 #if ! (DBVER >= 33)
5720 ADD_INT(d, DB_VRFY_FLAGMASK);
5721 ADD_INT(d, DB_PR_HEADERS);
5722 #endif
5723 ADD_INT(d, DB_PR_RECOVERYTEST);
5724 ADD_INT(d, DB_SALVAGE);
5726 ADD_INT(d, DB_LOCK_NORUN);
5727 ADD_INT(d, DB_LOCK_DEFAULT);
5728 ADD_INT(d, DB_LOCK_OLDEST);
5729 ADD_INT(d, DB_LOCK_RANDOM);
5730 ADD_INT(d, DB_LOCK_YOUNGEST);
5731 #if (DBVER >= 33)
5732 ADD_INT(d, DB_LOCK_MAXLOCKS);
5733 ADD_INT(d, DB_LOCK_MINLOCKS);
5734 ADD_INT(d, DB_LOCK_MINWRITE);
5735 #endif
5738 #if (DBVER >= 33)
5739 /* docs say to use zero instead */
5740 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5741 #else
5742 ADD_INT(d, DB_LOCK_CONFLICT);
5743 #endif
5745 ADD_INT(d, DB_LOCK_DUMP);
5746 ADD_INT(d, DB_LOCK_GET);
5747 ADD_INT(d, DB_LOCK_INHERIT);
5748 ADD_INT(d, DB_LOCK_PUT);
5749 ADD_INT(d, DB_LOCK_PUT_ALL);
5750 ADD_INT(d, DB_LOCK_PUT_OBJ);
5752 ADD_INT(d, DB_LOCK_NG);
5753 ADD_INT(d, DB_LOCK_READ);
5754 ADD_INT(d, DB_LOCK_WRITE);
5755 ADD_INT(d, DB_LOCK_NOWAIT);
5756 #if (DBVER >= 32)
5757 ADD_INT(d, DB_LOCK_WAIT);
5758 #endif
5759 ADD_INT(d, DB_LOCK_IWRITE);
5760 ADD_INT(d, DB_LOCK_IREAD);
5761 ADD_INT(d, DB_LOCK_IWR);
5762 #if (DBVER >= 33)
5763 #if (DBVER < 44)
5764 ADD_INT(d, DB_LOCK_DIRTY);
5765 #else
5766 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5767 #endif
5768 ADD_INT(d, DB_LOCK_WWRITE);
5769 #endif
5771 ADD_INT(d, DB_LOCK_RECORD);
5772 ADD_INT(d, DB_LOCK_UPGRADE);
5773 #if (DBVER >= 32)
5774 ADD_INT(d, DB_LOCK_SWITCH);
5775 #endif
5776 #if (DBVER >= 33)
5777 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5778 #endif
5780 ADD_INT(d, DB_LOCK_NOWAIT);
5781 ADD_INT(d, DB_LOCK_RECORD);
5782 ADD_INT(d, DB_LOCK_UPGRADE);
5784 #if (DBVER >= 33)
5785 ADD_INT(d, DB_LSTAT_ABORTED);
5786 #if (DBVER < 43)
5787 ADD_INT(d, DB_LSTAT_ERR);
5788 #endif
5789 ADD_INT(d, DB_LSTAT_FREE);
5790 ADD_INT(d, DB_LSTAT_HELD);
5791 #if (DBVER == 33)
5792 ADD_INT(d, DB_LSTAT_NOGRANT);
5793 #endif
5794 ADD_INT(d, DB_LSTAT_PENDING);
5795 ADD_INT(d, DB_LSTAT_WAITING);
5796 #endif
5798 ADD_INT(d, DB_ARCH_ABS);
5799 ADD_INT(d, DB_ARCH_DATA);
5800 ADD_INT(d, DB_ARCH_LOG);
5801 #if (DBVER >= 42)
5802 ADD_INT(d, DB_ARCH_REMOVE);
5803 #endif
5805 ADD_INT(d, DB_BTREE);
5806 ADD_INT(d, DB_HASH);
5807 ADD_INT(d, DB_RECNO);
5808 ADD_INT(d, DB_QUEUE);
5809 ADD_INT(d, DB_UNKNOWN);
5811 ADD_INT(d, DB_DUP);
5812 ADD_INT(d, DB_DUPSORT);
5813 ADD_INT(d, DB_RECNUM);
5814 ADD_INT(d, DB_RENUMBER);
5815 ADD_INT(d, DB_REVSPLITOFF);
5816 ADD_INT(d, DB_SNAPSHOT);
5818 ADD_INT(d, DB_JOIN_NOSORT);
5820 ADD_INT(d, DB_AFTER);
5821 ADD_INT(d, DB_APPEND);
5822 ADD_INT(d, DB_BEFORE);
5823 ADD_INT(d, DB_CACHED_COUNTS);
5824 #if (DBVER >= 41)
5825 _addIntToDict(d, "DB_CHECKPOINT", 0);
5826 #else
5827 ADD_INT(d, DB_CHECKPOINT);
5828 ADD_INT(d, DB_CURLSN);
5829 #endif
5830 #if ((DBVER >= 33) && (DBVER <= 41))
5831 ADD_INT(d, DB_COMMIT);
5832 #endif
5833 ADD_INT(d, DB_CONSUME);
5834 #if (DBVER >= 32)
5835 ADD_INT(d, DB_CONSUME_WAIT);
5836 #endif
5837 ADD_INT(d, DB_CURRENT);
5838 #if (DBVER >= 33)
5839 ADD_INT(d, DB_FAST_STAT);
5840 #endif
5841 ADD_INT(d, DB_FIRST);
5842 ADD_INT(d, DB_FLUSH);
5843 ADD_INT(d, DB_GET_BOTH);
5844 ADD_INT(d, DB_GET_RECNO);
5845 ADD_INT(d, DB_JOIN_ITEM);
5846 ADD_INT(d, DB_KEYFIRST);
5847 ADD_INT(d, DB_KEYLAST);
5848 ADD_INT(d, DB_LAST);
5849 ADD_INT(d, DB_NEXT);
5850 ADD_INT(d, DB_NEXT_DUP);
5851 ADD_INT(d, DB_NEXT_NODUP);
5852 ADD_INT(d, DB_NODUPDATA);
5853 ADD_INT(d, DB_NOOVERWRITE);
5854 ADD_INT(d, DB_NOSYNC);
5855 ADD_INT(d, DB_POSITION);
5856 ADD_INT(d, DB_PREV);
5857 ADD_INT(d, DB_PREV_NODUP);
5858 ADD_INT(d, DB_RECORDCOUNT);
5859 ADD_INT(d, DB_SET);
5860 ADD_INT(d, DB_SET_RANGE);
5861 ADD_INT(d, DB_SET_RECNO);
5862 ADD_INT(d, DB_WRITECURSOR);
5864 ADD_INT(d, DB_OPFLAGS_MASK);
5865 ADD_INT(d, DB_RMW);
5866 #if (DBVER >= 33)
5867 ADD_INT(d, DB_DIRTY_READ);
5868 ADD_INT(d, DB_MULTIPLE);
5869 ADD_INT(d, DB_MULTIPLE_KEY);
5870 #endif
5872 #if (DBVER >= 44)
5873 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5874 ADD_INT(d, DB_READ_COMMITTED);
5875 #endif
5877 #if (DBVER >= 33)
5878 ADD_INT(d, DB_DONOTINDEX);
5879 #endif
5881 #if (DBVER >= 41)
5882 _addIntToDict(d, "DB_INCOMPLETE", 0);
5883 #else
5884 ADD_INT(d, DB_INCOMPLETE);
5885 #endif
5886 ADD_INT(d, DB_KEYEMPTY);
5887 ADD_INT(d, DB_KEYEXIST);
5888 ADD_INT(d, DB_LOCK_DEADLOCK);
5889 ADD_INT(d, DB_LOCK_NOTGRANTED);
5890 ADD_INT(d, DB_NOSERVER);
5891 ADD_INT(d, DB_NOSERVER_HOME);
5892 ADD_INT(d, DB_NOSERVER_ID);
5893 ADD_INT(d, DB_NOTFOUND);
5894 ADD_INT(d, DB_OLD_VERSION);
5895 ADD_INT(d, DB_RUNRECOVERY);
5896 ADD_INT(d, DB_VERIFY_BAD);
5897 #if (DBVER >= 33)
5898 ADD_INT(d, DB_PAGE_NOTFOUND);
5899 ADD_INT(d, DB_SECONDARY_BAD);
5900 #endif
5901 #if (DBVER >= 40)
5902 ADD_INT(d, DB_STAT_CLEAR);
5903 ADD_INT(d, DB_REGION_INIT);
5904 ADD_INT(d, DB_NOLOCKING);
5905 ADD_INT(d, DB_YIELDCPU);
5906 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5907 ADD_INT(d, DB_NOPANIC);
5908 #endif
5910 #if (DBVER >= 42)
5911 ADD_INT(d, DB_TIME_NOTGRANTED);
5912 ADD_INT(d, DB_TXN_NOT_DURABLE);
5913 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5914 ADD_INT(d, DB_LOG_AUTOREMOVE);
5915 ADD_INT(d, DB_DIRECT_LOG);
5916 ADD_INT(d, DB_DIRECT_DB);
5917 ADD_INT(d, DB_INIT_REP);
5918 ADD_INT(d, DB_ENCRYPT);
5919 ADD_INT(d, DB_CHKSUM);
5920 #endif
5922 #if (DBVER >= 43)
5923 ADD_INT(d, DB_LOG_INMEMORY);
5924 ADD_INT(d, DB_BUFFER_SMALL);
5925 ADD_INT(d, DB_SEQ_DEC);
5926 ADD_INT(d, DB_SEQ_INC);
5927 ADD_INT(d, DB_SEQ_WRAP);
5928 #endif
5930 #if (DBVER >= 41)
5931 ADD_INT(d, DB_ENCRYPT_AES);
5932 ADD_INT(d, DB_AUTO_COMMIT);
5933 #else
5934 /* allow berkeleydb 4.1 aware apps to run on older versions */
5935 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5936 #endif
5938 ADD_INT(d, EINVAL);
5939 ADD_INT(d, EACCES);
5940 ADD_INT(d, ENOSPC);
5941 ADD_INT(d, ENOMEM);
5942 ADD_INT(d, EAGAIN);
5943 ADD_INT(d, EBUSY);
5944 ADD_INT(d, EEXIST);
5945 ADD_INT(d, ENOENT);
5946 ADD_INT(d, EPERM);
5948 #if (DBVER >= 40)
5949 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5950 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5951 #endif
5953 /* The exception name must be correct for pickled exception *
5954 * objects to unpickle properly. */
5955 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5956 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5957 #else
5958 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5959 #endif
5961 /* All the rest of the exceptions derive only from DBError */
5962 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5963 PyDict_SetItemString(d, #name, name)
5965 /* The base exception class is DBError */
5966 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5967 MAKE_EX(DBError);
5969 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5970 * from both DBError and KeyError, since the API only supports
5971 * using one base class. */
5972 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5973 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5974 "class DBKeyEmptyError(DBError, KeyError): pass",
5975 Py_file_input, d, d);
5976 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5977 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5978 PyDict_DelItemString(d, "KeyError");
5981 #if !INCOMPLETE_IS_WARNING
5982 MAKE_EX(DBIncompleteError);
5983 #endif
5984 MAKE_EX(DBCursorClosedError);
5985 MAKE_EX(DBKeyEmptyError);
5986 MAKE_EX(DBKeyExistError);
5987 MAKE_EX(DBLockDeadlockError);
5988 MAKE_EX(DBLockNotGrantedError);
5989 MAKE_EX(DBOldVersionError);
5990 MAKE_EX(DBRunRecoveryError);
5991 MAKE_EX(DBVerifyBadError);
5992 MAKE_EX(DBNoServerError);
5993 MAKE_EX(DBNoServerHomeError);
5994 MAKE_EX(DBNoServerIDError);
5995 #if (DBVER >= 33)
5996 MAKE_EX(DBPageNotFoundError);
5997 MAKE_EX(DBSecondaryBadError);
5998 #endif
6000 MAKE_EX(DBInvalidArgError);
6001 MAKE_EX(DBAccessError);
6002 MAKE_EX(DBNoSpaceError);
6003 MAKE_EX(DBNoMemoryError);
6004 MAKE_EX(DBAgainError);
6005 MAKE_EX(DBBusyError);
6006 MAKE_EX(DBFileExistsError);
6007 MAKE_EX(DBNoSuchFileError);
6008 MAKE_EX(DBPermissionsError);
6010 #undef MAKE_EX
6012 /* Check for errors */
6013 if (PyErr_Occurred()) {
6014 PyErr_Print();
6015 Py_FatalError("can't initialize module _bsddb");
6019 /* allow this module to be named _pybsddb so that it can be installed
6020 * and imported on top of python >= 2.3 that includes its own older
6021 * copy of the library named _bsddb without importing the old version. */
6022 DL_EXPORT(void) init_pybsddb(void)
6024 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6025 init_bsddb();