Exceptions raised during renaming in rotating file handlers are now passed to handleE...
[python.git] / Modules / _bsddb.c
blob6f4da7ee61615ebd9dc070a8cb1a31f731fb3278
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 5 types:
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
74 /* --------------------------------------------------------------------- */
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
82 * --Robin
85 /* --------------------------------------------------------------------- */
87 #include <stddef.h> /* for offsetof() */
88 #include <Python.h>
89 #include <db.h>
91 /* --------------------------------------------------------------------- */
92 /* Various macro definitions */
94 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
95 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
96 #if DB_VERSION_MINOR > 9
97 #error "eek! DBVER can't handle minor versions > 9"
98 #endif
100 #define PY_BSDDB_VERSION "4.3.3"
101 static char *rcs_id = "$Id$";
104 #ifdef WITH_THREAD
106 /* These are for when calling Python --> C */
107 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
110 /* For 2.3, use the PyGILState_ calls */
111 #if (PY_VERSION_HEX >= 0x02030000)
112 #define MYDB_USE_GILSTATE
113 #endif
115 /* and these are for calling C --> Python */
116 #if defined(MYDB_USE_GILSTATE)
117 #define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119 #define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121 #else /* MYDB_USE_GILSTATE */
122 /* Pre GILState API - do it the long old way */
123 static PyInterpreterState* _db_interpreterState = NULL;
124 #define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
131 #define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
137 #endif /* MYDB_USE_GILSTATE */
139 #else
140 /* Compiled without threads - avoid all this cruft */
141 #define MYDB_BEGIN_ALLOW_THREADS
142 #define MYDB_END_ALLOW_THREADS
143 #define MYDB_BEGIN_BLOCK_THREADS
144 #define MYDB_END_BLOCK_THREADS
146 #endif
148 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
149 #define INCOMPLETE_IS_WARNING 1
151 /* --------------------------------------------------------------------- */
152 /* Exceptions */
154 static PyObject* DBError; /* Base class, all others derive from this */
155 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
156 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
157 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164 static PyObject* DBNoServerError; /* DB_NOSERVER */
165 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167 #if (DBVER >= 33)
168 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170 #endif
172 #if !INCOMPLETE_IS_WARNING
173 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174 #endif
176 static PyObject* DBInvalidArgError; /* EINVAL */
177 static PyObject* DBAccessError; /* EACCES */
178 static PyObject* DBNoSpaceError; /* ENOSPC */
179 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
180 static PyObject* DBAgainError; /* EAGAIN */
181 static PyObject* DBBusyError; /* EBUSY */
182 static PyObject* DBFileExistsError; /* EEXIST */
183 static PyObject* DBNoSuchFileError; /* ENOENT */
184 static PyObject* DBPermissionsError; /* EPERM */
186 #if (DBVER < 43)
187 #define DB_BUFFER_SMALL ENOMEM
188 #endif
191 /* --------------------------------------------------------------------- */
192 /* Structure definitions */
194 #if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
195 #define HAVE_WEAKREF
196 #else
197 #undef HAVE_WEAKREF
198 #endif
200 /* if Python >= 2.1 better support warnings */
201 #if PYTHON_API_VERSION >= 1010
202 #define HAVE_WARNINGS
203 #else
204 #undef HAVE_WARNINGS
205 #endif
207 #if PYTHON_API_VERSION <= 1007
208 /* 1.5 compatibility */
209 #define PyObject_New PyObject_NEW
210 #define PyObject_Del PyMem_DEL
211 #endif
213 struct behaviourFlags {
214 /* What is the default behaviour when DB->get or DBCursor->get returns a
215 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
216 unsigned int getReturnsNone : 1;
217 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
218 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
219 unsigned int cursorSetReturnsNone : 1;
222 #define DEFAULT_GET_RETURNS_NONE 1
223 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
225 typedef struct {
226 PyObject_HEAD
227 DB_ENV* db_env;
228 u_int32_t flags; /* saved flags from open() */
229 int closed;
230 struct behaviourFlags moduleFlags;
231 #ifdef HAVE_WEAKREF
232 PyObject *in_weakreflist; /* List of weak references */
233 #endif
234 } DBEnvObject;
237 typedef struct {
238 PyObject_HEAD
239 DB* db;
240 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
241 u_int32_t flags; /* saved flags from open() */
242 u_int32_t setflags; /* saved flags from set_flags() */
243 int haveStat;
244 struct behaviourFlags moduleFlags;
245 #if (DBVER >= 33)
246 PyObject* associateCallback;
247 PyObject* btCompareCallback;
248 int primaryDBType;
249 #endif
250 #ifdef HAVE_WEAKREF
251 PyObject *in_weakreflist; /* List of weak references */
252 #endif
253 } DBObject;
256 typedef struct {
257 PyObject_HEAD
258 DBC* dbc;
259 DBObject* mydb;
260 #ifdef HAVE_WEAKREF
261 PyObject *in_weakreflist; /* List of weak references */
262 #endif
263 } DBCursorObject;
266 typedef struct {
267 PyObject_HEAD
268 DB_TXN* txn;
269 #ifdef HAVE_WEAKREF
270 PyObject *in_weakreflist; /* List of weak references */
271 #endif
272 } DBTxnObject;
275 typedef struct {
276 PyObject_HEAD
277 DB_LOCK lock;
278 #ifdef HAVE_WEAKREF
279 PyObject *in_weakreflist; /* List of weak references */
280 #endif
281 } DBLockObject;
285 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
287 #define DBObject_Check(v) ((v)->ob_type == &DB_Type)
288 #define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
289 #define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
290 #define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
291 #define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
294 /* --------------------------------------------------------------------- */
295 /* Utility macros and functions */
297 #define RETURN_IF_ERR() \
298 if (makeDBError(err)) { \
299 return NULL; \
302 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
304 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
305 if ((nonNull) == NULL) { \
306 PyObject *errTuple = NULL; \
307 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
308 PyErr_SetObject((pyErrObj), errTuple); \
309 Py_DECREF(errTuple); \
310 return NULL; \
313 #define CHECK_DB_NOT_CLOSED(dbobj) \
314 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
316 #define CHECK_ENV_NOT_CLOSED(env) \
317 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
319 #define CHECK_CURSOR_NOT_CLOSED(curs) \
320 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
323 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
324 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
326 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
328 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
329 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
332 static int makeDBError(int err);
335 /* Return the access method type of the DBObject */
336 static int _DB_get_type(DBObject* self)
338 #if (DBVER >= 33)
339 DBTYPE type;
340 int err;
341 err = self->db->get_type(self->db, &type);
342 if (makeDBError(err)) {
343 return -1;
345 return type;
346 #else
347 return self->db->get_type(self->db);
348 #endif
352 /* Create a DBT structure (containing key and data values) from Python
353 strings. Returns 1 on success, 0 on an error. */
354 static int make_dbt(PyObject* obj, DBT* dbt)
356 CLEAR_DBT(*dbt);
357 if (obj == Py_None) {
358 /* no need to do anything, the structure has already been zeroed */
360 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
361 PyErr_SetString(PyExc_TypeError,
362 "Data values must be of type string or None.");
363 return 0;
365 return 1;
369 /* Recno and Queue DBs can have integer keys. This function figures out
370 what's been given, verifies that it's allowed, and then makes the DBT.
372 Caller MUST call FREE_DBT(key) when done. */
373 static int
374 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
376 db_recno_t recno;
377 int type;
379 CLEAR_DBT(*key);
380 if (keyobj == Py_None) {
381 type = _DB_get_type(self);
382 if (type == -1)
383 return 0;
384 if (type == DB_RECNO || type == DB_QUEUE) {
385 PyErr_SetString(
386 PyExc_TypeError,
387 "None keys not allowed for Recno and Queue DB's");
388 return 0;
390 /* no need to do anything, the structure has already been zeroed */
393 else if (PyString_Check(keyobj)) {
394 /* verify access method type */
395 type = _DB_get_type(self);
396 if (type == -1)
397 return 0;
398 if (type == DB_RECNO || type == DB_QUEUE) {
399 PyErr_SetString(
400 PyExc_TypeError,
401 "String keys not allowed for Recno and Queue DB's");
402 return 0;
405 key->data = PyString_AS_STRING(keyobj);
406 key->size = PyString_GET_SIZE(keyobj);
409 else if (PyInt_Check(keyobj)) {
410 /* verify access method type */
411 type = _DB_get_type(self);
412 if (type == -1)
413 return 0;
414 if (type == DB_BTREE && pflags != NULL) {
415 /* if BTREE then an Integer key is allowed with the
416 * DB_SET_RECNO flag */
417 *pflags |= DB_SET_RECNO;
419 else if (type != DB_RECNO && type != DB_QUEUE) {
420 PyErr_SetString(
421 PyExc_TypeError,
422 "Integer keys only allowed for Recno and Queue DB's");
423 return 0;
426 /* Make a key out of the requested recno, use allocated space so DB
427 * will be able to realloc room for the real key if needed. */
428 recno = PyInt_AS_LONG(keyobj);
429 key->data = malloc(sizeof(db_recno_t));
430 if (key->data == NULL) {
431 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
432 return 0;
434 key->ulen = key->size = sizeof(db_recno_t);
435 memcpy(key->data, &recno, sizeof(db_recno_t));
436 key->flags = DB_DBT_REALLOC;
438 else {
439 PyErr_Format(PyExc_TypeError,
440 "String or Integer object expected for key, %s found",
441 keyobj->ob_type->tp_name);
442 return 0;
445 return 1;
449 /* Add partial record access to an existing DBT data struct.
450 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
451 and the data storage/retrieval will be done using dlen and doff. */
452 static int add_partial_dbt(DBT* d, int dlen, int doff) {
453 /* if neither were set we do nothing (-1 is the default value) */
454 if ((dlen == -1) && (doff == -1)) {
455 return 1;
458 if ((dlen < 0) || (doff < 0)) {
459 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
460 return 0;
463 d->flags = d->flags | DB_DBT_PARTIAL;
464 d->dlen = (unsigned int) dlen;
465 d->doff = (unsigned int) doff;
466 return 1;
469 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
470 /* TODO: make this use the native libc strlcpy() when available (BSD) */
471 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
473 unsigned int srclen, copylen;
475 srclen = strlen(src);
476 if (n <= 0)
477 return srclen;
478 copylen = (srclen > n-1) ? n-1 : srclen;
479 /* populate dest[0] thru dest[copylen-1] */
480 memcpy(dest, src, copylen);
481 /* guarantee null termination */
482 dest[copylen] = 0;
484 return srclen;
487 /* Callback used to save away more information about errors from the DB
488 * library. */
489 static char _db_errmsg[1024];
490 #if (DBVER <= 42)
491 static void _db_errorCallback(const char* prefix, char* msg)
492 #else
493 static void _db_errorCallback(const DB_ENV *db_env,
494 const char* prefix, const char* msg)
495 #endif
497 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
501 /* make a nice exception object to raise for errors. */
502 static int makeDBError(int err)
504 char errTxt[2048]; /* really big, just in case... */
505 PyObject *errObj = NULL;
506 PyObject *errTuple = NULL;
507 int exceptionRaised = 0;
509 switch (err) {
510 case 0: /* successful, no error */ break;
512 #if (DBVER < 41)
513 case DB_INCOMPLETE:
514 #if INCOMPLETE_IS_WARNING
515 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
516 if (_db_errmsg[0]) {
517 strcat(errTxt, " -- ");
518 strcat(errTxt, _db_errmsg);
519 _db_errmsg[0] = 0;
521 #ifdef HAVE_WARNINGS
522 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
523 #else
524 fprintf(stderr, errTxt);
525 fprintf(stderr, "\n");
526 #endif
528 #else /* do an exception instead */
529 errObj = DBIncompleteError;
530 #endif
531 break;
532 #endif /* DBVER < 41 */
534 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
535 case DB_KEYEXIST: errObj = DBKeyExistError; break;
536 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
537 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
538 case DB_NOTFOUND: errObj = DBNotFoundError; break;
539 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
540 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
541 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
542 case DB_NOSERVER: errObj = DBNoServerError; break;
543 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
544 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
545 #if (DBVER >= 33)
546 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
547 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
548 #endif
549 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
551 #if (DBVER >= 43)
552 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
553 case ENOMEM: errObj = PyExc_MemoryError; break;
554 #endif
555 case EINVAL: errObj = DBInvalidArgError; break;
556 case EACCES: errObj = DBAccessError; break;
557 case ENOSPC: errObj = DBNoSpaceError; break;
558 case EAGAIN: errObj = DBAgainError; break;
559 case EBUSY : errObj = DBBusyError; break;
560 case EEXIST: errObj = DBFileExistsError; break;
561 case ENOENT: errObj = DBNoSuchFileError; break;
562 case EPERM : errObj = DBPermissionsError; break;
564 default: errObj = DBError; break;
567 if (errObj != NULL) {
568 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
569 if (_db_errmsg[0]) {
570 strcat(errTxt, " -- ");
571 strcat(errTxt, _db_errmsg);
572 _db_errmsg[0] = 0;
575 errTuple = Py_BuildValue("(is)", err, errTxt);
576 PyErr_SetObject(errObj, errTuple);
577 Py_DECREF(errTuple);
580 return ((errObj != NULL) || exceptionRaised);
585 /* set a type exception */
586 static void makeTypeError(char* expected, PyObject* found)
588 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
589 expected, found->ob_type->tp_name);
593 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
594 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
596 if (txnobj == Py_None || txnobj == NULL) {
597 *txn = NULL;
598 return 1;
600 if (DBTxnObject_Check(txnobj)) {
601 *txn = ((DBTxnObject*)txnobj)->txn;
602 return 1;
604 else
605 makeTypeError("DBTxn", txnobj);
606 return 0;
610 /* Delete a key from a database
611 Returns 0 on success, -1 on an error. */
612 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
614 int err;
616 MYDB_BEGIN_ALLOW_THREADS;
617 err = self->db->del(self->db, txn, key, 0);
618 MYDB_END_ALLOW_THREADS;
619 if (makeDBError(err)) {
620 return -1;
622 self->haveStat = 0;
623 return 0;
627 /* Store a key into a database
628 Returns 0 on success, -1 on an error. */
629 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
631 int err;
633 MYDB_BEGIN_ALLOW_THREADS;
634 err = self->db->put(self->db, txn, key, data, flags);
635 MYDB_END_ALLOW_THREADS;
636 if (makeDBError(err)) {
637 return -1;
639 self->haveStat = 0;
640 return 0;
643 /* Get a key/data pair from a cursor */
644 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
645 PyObject *args, PyObject *kwargs, char *format)
647 int err;
648 PyObject* retval = NULL;
649 DBT key, data;
650 int dlen = -1;
651 int doff = -1;
652 int flags = 0;
653 static const char* kwnames[] = { "flags", "dlen", "doff", NULL };
655 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
656 &flags, &dlen, &doff))
657 return NULL;
659 CHECK_CURSOR_NOT_CLOSED(self);
661 flags |= extra_flags;
662 CLEAR_DBT(key);
663 CLEAR_DBT(data);
664 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
665 /* Tell BerkeleyDB to malloc the return value (thread safe) */
666 data.flags = DB_DBT_MALLOC;
667 key.flags = DB_DBT_MALLOC;
669 if (!add_partial_dbt(&data, dlen, doff))
670 return NULL;
672 MYDB_BEGIN_ALLOW_THREADS;
673 err = self->dbc->c_get(self->dbc, &key, &data, flags);
674 MYDB_END_ALLOW_THREADS;
676 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
677 && self->mydb->moduleFlags.getReturnsNone) {
678 Py_INCREF(Py_None);
679 retval = Py_None;
681 else if (makeDBError(err)) {
682 retval = NULL;
684 else { /* otherwise, success! */
686 /* if Recno or Queue, return the key as an Int */
687 switch (_DB_get_type(self->mydb)) {
688 case -1:
689 retval = NULL;
690 break;
692 case DB_RECNO:
693 case DB_QUEUE:
694 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
695 data.data, data.size);
696 break;
697 case DB_HASH:
698 case DB_BTREE:
699 default:
700 retval = Py_BuildValue("s#s#", key.data, key.size,
701 data.data, data.size);
702 break;
705 if (!err) {
706 FREE_DBT(key);
707 FREE_DBT(data);
709 return retval;
713 /* add an integer to a dictionary using the given name as a key */
714 static void _addIntToDict(PyObject* dict, char *name, int value)
716 PyObject* v = PyInt_FromLong((long) value);
717 if (!v || PyDict_SetItemString(dict, name, v))
718 PyErr_Clear();
720 Py_XDECREF(v);
726 /* --------------------------------------------------------------------- */
727 /* Allocators and deallocators */
729 static DBObject*
730 newDBObject(DBEnvObject* arg, int flags)
732 DBObject* self;
733 DB_ENV* db_env = NULL;
734 int err;
736 self = PyObject_New(DBObject, &DB_Type);
737 if (self == NULL)
738 return NULL;
740 self->haveStat = 0;
741 self->flags = 0;
742 self->setflags = 0;
743 self->myenvobj = NULL;
744 #if (DBVER >= 33)
745 self->associateCallback = NULL;
746 self->btCompareCallback = NULL;
747 self->primaryDBType = 0;
748 #endif
749 #ifdef HAVE_WEAKREF
750 self->in_weakreflist = NULL;
751 #endif
753 /* keep a reference to our python DBEnv object */
754 if (arg) {
755 Py_INCREF(arg);
756 self->myenvobj = arg;
757 db_env = arg->db_env;
760 if (self->myenvobj)
761 self->moduleFlags = self->myenvobj->moduleFlags;
762 else
763 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
764 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
766 MYDB_BEGIN_ALLOW_THREADS;
767 err = db_create(&self->db, db_env, flags);
768 self->db->set_errcall(self->db, _db_errorCallback);
769 #if (DBVER >= 33)
770 self->db->app_private = (void*)self;
771 #endif
772 MYDB_END_ALLOW_THREADS;
773 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
774 * list so that a DBEnv can refuse to close without aborting any open
775 * open DBTxns and closing any open DBs first. */
776 if (makeDBError(err)) {
777 if (self->myenvobj) {
778 Py_DECREF(self->myenvobj);
779 self->myenvobj = NULL;
781 self = NULL;
783 return self;
787 static void
788 DB_dealloc(DBObject* self)
790 if (self->db != NULL) {
791 /* avoid closing a DB when its DBEnv has been closed out from under
792 * it */
793 if (!self->myenvobj ||
794 (self->myenvobj && self->myenvobj->db_env))
796 MYDB_BEGIN_ALLOW_THREADS;
797 self->db->close(self->db, 0);
798 MYDB_END_ALLOW_THREADS;
799 #ifdef HAVE_WARNINGS
800 } else {
801 PyErr_Warn(PyExc_RuntimeWarning,
802 "DB could not be closed in destructor: DBEnv already closed");
803 #endif
805 self->db = NULL;
807 #ifdef HAVE_WEAKREF
808 if (self->in_weakreflist != NULL) {
809 PyObject_ClearWeakRefs((PyObject *) self);
811 #endif
812 if (self->myenvobj) {
813 Py_DECREF(self->myenvobj);
814 self->myenvobj = NULL;
816 #if (DBVER >= 33)
817 if (self->associateCallback != NULL) {
818 Py_DECREF(self->associateCallback);
819 self->associateCallback = NULL;
821 if (self->btCompareCallback != NULL) {
822 Py_DECREF(self->btCompareCallback);
823 self->btCompareCallback = NULL;
825 #endif
826 PyObject_Del(self);
830 static DBCursorObject*
831 newDBCursorObject(DBC* dbc, DBObject* db)
833 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
834 if (self == NULL)
835 return NULL;
837 self->dbc = dbc;
838 self->mydb = db;
839 #ifdef HAVE_WEAKREF
840 self->in_weakreflist = NULL;
841 #endif
842 Py_INCREF(self->mydb);
843 return self;
847 static void
848 DBCursor_dealloc(DBCursorObject* self)
850 int err;
852 #ifdef HAVE_WEAKREF
853 if (self->in_weakreflist != NULL) {
854 PyObject_ClearWeakRefs((PyObject *) self);
856 #endif
858 if (self->dbc != NULL) {
859 MYDB_BEGIN_ALLOW_THREADS;
860 /* If the underlying database has been closed, we don't
861 need to do anything. If the environment has been closed
862 we need to leak, as BerkeleyDB will crash trying to access
863 the environment. There was an exception when the
864 user closed the environment even though there still was
865 a database open. */
866 if (self->mydb->db && self->mydb->myenvobj &&
867 !self->mydb->myenvobj->closed)
868 err = self->dbc->c_close(self->dbc);
869 self->dbc = NULL;
870 MYDB_END_ALLOW_THREADS;
872 Py_XDECREF( self->mydb );
873 PyObject_Del(self);
877 static DBEnvObject*
878 newDBEnvObject(int flags)
880 int err;
881 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
882 if (self == NULL)
883 return NULL;
885 self->closed = 1;
886 self->flags = flags;
887 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
888 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
889 #ifdef HAVE_WEAKREF
890 self->in_weakreflist = NULL;
891 #endif
893 MYDB_BEGIN_ALLOW_THREADS;
894 err = db_env_create(&self->db_env, flags);
895 MYDB_END_ALLOW_THREADS;
896 if (makeDBError(err)) {
897 self = NULL;
899 else {
900 self->db_env->set_errcall(self->db_env, _db_errorCallback);
902 return self;
906 static void
907 DBEnv_dealloc(DBEnvObject* self)
909 #ifdef HAVE_WEAKREF
910 if (self->in_weakreflist != NULL) {
911 PyObject_ClearWeakRefs((PyObject *) self);
913 #endif
915 if (self->db_env) {
916 MYDB_BEGIN_ALLOW_THREADS;
917 self->db_env->close(self->db_env, 0);
918 MYDB_END_ALLOW_THREADS;
920 PyObject_Del(self);
924 static DBTxnObject*
925 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
927 int err;
928 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
929 if (self == NULL)
930 return NULL;
931 #ifdef HAVE_WEAKREF
932 self->in_weakreflist = NULL;
933 #endif
935 MYDB_BEGIN_ALLOW_THREADS;
936 #if (DBVER >= 40)
937 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
938 #else
939 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
940 #endif
941 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
942 * list so that a DBEnv can refuse to close without aborting any open
943 * open DBTxns and closing any open DBs first. */
944 MYDB_END_ALLOW_THREADS;
945 if (makeDBError(err)) {
946 self = NULL;
948 return self;
952 static void
953 DBTxn_dealloc(DBTxnObject* self)
955 #ifdef HAVE_WEAKREF
956 if (self->in_weakreflist != NULL) {
957 PyObject_ClearWeakRefs((PyObject *) self);
959 #endif
961 #ifdef HAVE_WARNINGS
962 if (self->txn) {
963 /* it hasn't been finalized, abort it! */
964 MYDB_BEGIN_ALLOW_THREADS;
965 #if (DBVER >= 40)
966 self->txn->abort(self->txn);
967 #else
968 txn_abort(self->txn);
969 #endif
970 MYDB_END_ALLOW_THREADS;
971 PyErr_Warn(PyExc_RuntimeWarning,
972 "DBTxn aborted in destructor. No prior commit() or abort().");
974 #endif
976 PyObject_Del(self);
980 static DBLockObject*
981 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
982 db_lockmode_t lock_mode, int flags)
984 int err;
985 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
986 if (self == NULL)
987 return NULL;
988 #ifdef HAVE_WEAKREF
989 self->in_weakreflist = NULL;
990 #endif
992 MYDB_BEGIN_ALLOW_THREADS;
993 #if (DBVER >= 40)
994 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
995 &self->lock);
996 #else
997 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
998 #endif
999 MYDB_END_ALLOW_THREADS;
1000 if (makeDBError(err)) {
1001 self = NULL;
1004 return self;
1008 static void
1009 DBLock_dealloc(DBLockObject* self)
1011 #ifdef HAVE_WEAKREF
1012 if (self->in_weakreflist != NULL) {
1013 PyObject_ClearWeakRefs((PyObject *) self);
1015 #endif
1016 /* TODO: is this lock held? should we release it? */
1018 PyObject_Del(self);
1022 /* --------------------------------------------------------------------- */
1023 /* DB methods */
1025 static PyObject*
1026 DB_append(DBObject* self, PyObject* args)
1028 PyObject* txnobj = NULL;
1029 PyObject* dataobj;
1030 db_recno_t recno;
1031 DBT key, data;
1032 DB_TXN *txn = NULL;
1034 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1035 return NULL;
1037 CHECK_DB_NOT_CLOSED(self);
1039 /* make a dummy key out of a recno */
1040 recno = 0;
1041 CLEAR_DBT(key);
1042 key.data = &recno;
1043 key.size = sizeof(recno);
1044 key.ulen = key.size;
1045 key.flags = DB_DBT_USERMEM;
1047 if (!make_dbt(dataobj, &data)) return NULL;
1048 if (!checkTxnObj(txnobj, &txn)) return NULL;
1050 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1051 return NULL;
1053 return PyInt_FromLong(recno);
1057 #if (DBVER >= 33)
1059 static int
1060 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1061 DBT* secKey)
1063 int retval = DB_DONOTINDEX;
1064 DBObject* secondaryDB = (DBObject*)db->app_private;
1065 PyObject* callback = secondaryDB->associateCallback;
1066 int type = secondaryDB->primaryDBType;
1067 PyObject* key;
1068 PyObject* data;
1069 PyObject* args;
1070 PyObject* result;
1073 if (callback != NULL) {
1074 MYDB_BEGIN_BLOCK_THREADS;
1076 if (type == DB_RECNO || type == DB_QUEUE) {
1077 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1079 else {
1080 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1082 data = PyString_FromStringAndSize(priData->data, priData->size);
1083 args = PyTuple_New(2);
1084 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1085 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1087 result = PyEval_CallObject(callback, args);
1089 if (result == NULL) {
1090 PyErr_Print();
1092 else if (result == Py_None) {
1093 retval = DB_DONOTINDEX;
1095 else if (PyInt_Check(result)) {
1096 retval = PyInt_AsLong(result);
1098 else if (PyString_Check(result)) {
1099 char* data;
1100 int size;
1102 CLEAR_DBT(*secKey);
1103 #if PYTHON_API_VERSION <= 1007
1104 /* 1.5 compatibility */
1105 size = PyString_Size(result);
1106 data = PyString_AsString(result);
1107 #else
1108 PyString_AsStringAndSize(result, &data, &size);
1109 #endif
1110 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1111 secKey->data = malloc(size); /* TODO, check this */
1112 if (secKey->data) {
1113 memcpy(secKey->data, data, size);
1114 secKey->size = size;
1115 retval = 0;
1117 else {
1118 PyErr_SetString(PyExc_MemoryError,
1119 "malloc failed in _db_associateCallback");
1120 PyErr_Print();
1123 else {
1124 PyErr_SetString(
1125 PyExc_TypeError,
1126 "DB associate callback should return DB_DONOTINDEX or string.");
1127 PyErr_Print();
1130 Py_DECREF(args);
1131 if (result) {
1132 Py_DECREF(result);
1135 MYDB_END_BLOCK_THREADS;
1137 return retval;
1141 static PyObject*
1142 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1144 int err, flags=0;
1145 DBObject* secondaryDB;
1146 PyObject* callback;
1147 #if (DBVER >= 41)
1148 PyObject *txnobj = NULL;
1149 DB_TXN *txn = NULL;
1150 static const char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1151 NULL};
1152 #else
1153 static const char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1154 #endif
1156 #if (DBVER >= 41)
1157 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1158 &secondaryDB, &callback, &flags,
1159 &txnobj)) {
1160 #else
1161 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1162 &secondaryDB, &callback, &flags)) {
1163 #endif
1164 return NULL;
1167 #if (DBVER >= 41)
1168 if (!checkTxnObj(txnobj, &txn)) return NULL;
1169 #endif
1171 CHECK_DB_NOT_CLOSED(self);
1172 if (!DBObject_Check(secondaryDB)) {
1173 makeTypeError("DB", (PyObject*)secondaryDB);
1174 return NULL;
1176 CHECK_DB_NOT_CLOSED(secondaryDB);
1177 if (callback == Py_None) {
1178 callback = NULL;
1180 else if (!PyCallable_Check(callback)) {
1181 makeTypeError("Callable", callback);
1182 return NULL;
1185 /* Save a reference to the callback in the secondary DB. */
1186 Py_XDECREF(secondaryDB->associateCallback);
1187 Py_INCREF(callback);
1188 secondaryDB->associateCallback = callback;
1189 secondaryDB->primaryDBType = _DB_get_type(self);
1191 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1192 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1193 * The global interepreter lock is not initialized until the first
1194 * thread is created using thread.start_new_thread() or fork() is
1195 * called. that would cause the ALLOW_THREADS here to segfault due
1196 * to a null pointer reference if no threads or child processes
1197 * have been created. This works around that and is a no-op if
1198 * threads have already been initialized.
1199 * (see pybsddb-users mailing list post on 2002-08-07)
1201 #ifdef WITH_THREAD
1202 PyEval_InitThreads();
1203 #endif
1204 MYDB_BEGIN_ALLOW_THREADS;
1205 #if (DBVER >= 41)
1206 err = self->db->associate(self->db,
1207 txn,
1208 secondaryDB->db,
1209 _db_associateCallback,
1210 flags);
1211 #else
1212 err = self->db->associate(self->db,
1213 secondaryDB->db,
1214 _db_associateCallback,
1215 flags);
1216 #endif
1217 MYDB_END_ALLOW_THREADS;
1219 if (err) {
1220 Py_XDECREF(secondaryDB->associateCallback);
1221 secondaryDB->associateCallback = NULL;
1222 secondaryDB->primaryDBType = 0;
1225 RETURN_IF_ERR();
1226 RETURN_NONE();
1230 #endif
1233 static PyObject*
1234 DB_close(DBObject* self, PyObject* args)
1236 int err, flags=0;
1237 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1238 return NULL;
1239 if (self->db != NULL) {
1240 if (self->myenvobj)
1241 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1242 err = self->db->close(self->db, flags);
1243 self->db = NULL;
1244 RETURN_IF_ERR();
1246 RETURN_NONE();
1250 #if (DBVER >= 32)
1251 static PyObject*
1252 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1254 int err, flags=0, type;
1255 PyObject* txnobj = NULL;
1256 PyObject* retval = NULL;
1257 DBT key, data;
1258 DB_TXN *txn = NULL;
1259 static const char* kwnames[] = { "txn", "flags", NULL };
1261 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1262 &txnobj, &flags))
1263 return NULL;
1265 CHECK_DB_NOT_CLOSED(self);
1266 type = _DB_get_type(self);
1267 if (type == -1)
1268 return NULL;
1269 if (type != DB_QUEUE) {
1270 PyErr_SetString(PyExc_TypeError,
1271 "Consume methods only allowed for Queue DB's");
1272 return NULL;
1274 if (!checkTxnObj(txnobj, &txn))
1275 return NULL;
1277 CLEAR_DBT(key);
1278 CLEAR_DBT(data);
1279 if (CHECK_DBFLAG(self, DB_THREAD)) {
1280 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1281 data.flags = DB_DBT_MALLOC;
1282 key.flags = DB_DBT_MALLOC;
1285 MYDB_BEGIN_ALLOW_THREADS;
1286 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1287 MYDB_END_ALLOW_THREADS;
1289 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1290 && self->moduleFlags.getReturnsNone) {
1291 err = 0;
1292 Py_INCREF(Py_None);
1293 retval = Py_None;
1295 else if (!err) {
1296 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1297 data.size);
1298 FREE_DBT(key);
1299 FREE_DBT(data);
1302 RETURN_IF_ERR();
1303 return retval;
1306 static PyObject*
1307 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1309 return _DB_consume(self, args, kwargs, DB_CONSUME);
1312 static PyObject*
1313 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1314 int consume_flag)
1316 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1318 #endif
1322 static PyObject*
1323 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1325 int err, flags=0;
1326 DBC* dbc;
1327 PyObject* txnobj = NULL;
1328 DB_TXN *txn = NULL;
1329 static const char* kwnames[] = { "txn", "flags", NULL };
1331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1332 &txnobj, &flags))
1333 return NULL;
1334 CHECK_DB_NOT_CLOSED(self);
1335 if (!checkTxnObj(txnobj, &txn))
1336 return NULL;
1338 MYDB_BEGIN_ALLOW_THREADS;
1339 err = self->db->cursor(self->db, txn, &dbc, flags);
1340 MYDB_END_ALLOW_THREADS;
1341 RETURN_IF_ERR();
1342 return (PyObject*) newDBCursorObject(dbc, self);
1346 static PyObject*
1347 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1349 PyObject* txnobj = NULL;
1350 int flags = 0;
1351 PyObject* keyobj;
1352 DBT key;
1353 DB_TXN *txn = NULL;
1354 static const char* kwnames[] = { "key", "txn", "flags", NULL };
1356 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1357 &keyobj, &txnobj, &flags))
1358 return NULL;
1359 CHECK_DB_NOT_CLOSED(self);
1360 if (!make_key_dbt(self, keyobj, &key, NULL))
1361 return NULL;
1362 if (!checkTxnObj(txnobj, &txn)) {
1363 FREE_DBT(key);
1364 return NULL;
1367 if (-1 == _DB_delete(self, txn, &key, 0)) {
1368 FREE_DBT(key);
1369 return NULL;
1372 FREE_DBT(key);
1373 RETURN_NONE();
1377 static PyObject*
1378 DB_fd(DBObject* self, PyObject* args)
1380 int err, the_fd;
1382 if (!PyArg_ParseTuple(args,":fd"))
1383 return NULL;
1384 CHECK_DB_NOT_CLOSED(self);
1386 MYDB_BEGIN_ALLOW_THREADS;
1387 err = self->db->fd(self->db, &the_fd);
1388 MYDB_END_ALLOW_THREADS;
1389 RETURN_IF_ERR();
1390 return PyInt_FromLong(the_fd);
1394 static PyObject*
1395 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1397 int err, flags=0;
1398 PyObject* txnobj = NULL;
1399 PyObject* keyobj;
1400 PyObject* dfltobj = NULL;
1401 PyObject* retval = NULL;
1402 int dlen = -1;
1403 int doff = -1;
1404 DBT key, data;
1405 DB_TXN *txn = NULL;
1406 static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1407 "doff", NULL};
1409 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1410 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1411 &doff))
1412 return NULL;
1414 CHECK_DB_NOT_CLOSED(self);
1415 if (!make_key_dbt(self, keyobj, &key, &flags))
1416 return NULL;
1417 if (!checkTxnObj(txnobj, &txn)) {
1418 FREE_DBT(key);
1419 return NULL;
1422 CLEAR_DBT(data);
1423 if (CHECK_DBFLAG(self, DB_THREAD)) {
1424 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1425 data.flags = DB_DBT_MALLOC;
1427 if (!add_partial_dbt(&data, dlen, doff)) {
1428 FREE_DBT(key);
1429 return NULL;
1432 MYDB_BEGIN_ALLOW_THREADS;
1433 err = self->db->get(self->db, txn, &key, &data, flags);
1434 MYDB_END_ALLOW_THREADS;
1436 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1437 err = 0;
1438 Py_INCREF(dfltobj);
1439 retval = dfltobj;
1441 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1442 && self->moduleFlags.getReturnsNone) {
1443 err = 0;
1444 Py_INCREF(Py_None);
1445 retval = Py_None;
1447 else if (!err) {
1448 if (flags & DB_SET_RECNO) /* return both key and data */
1449 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1450 data.size);
1451 else /* return just the data */
1452 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1453 FREE_DBT(data);
1455 FREE_DBT(key);
1457 RETURN_IF_ERR();
1458 return retval;
1461 #if (DBVER >= 33)
1462 static PyObject*
1463 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1465 int err, flags=0;
1466 PyObject* txnobj = NULL;
1467 PyObject* keyobj;
1468 PyObject* dfltobj = NULL;
1469 PyObject* retval = NULL;
1470 int dlen = -1;
1471 int doff = -1;
1472 DBT key, pkey, data;
1473 DB_TXN *txn = NULL;
1474 static const char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1475 "doff", NULL};
1477 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1478 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1479 &doff))
1480 return NULL;
1482 CHECK_DB_NOT_CLOSED(self);
1483 if (!make_key_dbt(self, keyobj, &key, &flags))
1484 return NULL;
1485 if (!checkTxnObj(txnobj, &txn)) {
1486 FREE_DBT(key);
1487 return NULL;
1490 CLEAR_DBT(data);
1491 if (CHECK_DBFLAG(self, DB_THREAD)) {
1492 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1493 data.flags = DB_DBT_MALLOC;
1495 if (!add_partial_dbt(&data, dlen, doff)) {
1496 FREE_DBT(key);
1497 return NULL;
1500 CLEAR_DBT(pkey);
1501 pkey.flags = DB_DBT_MALLOC;
1503 MYDB_BEGIN_ALLOW_THREADS;
1504 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1505 MYDB_END_ALLOW_THREADS;
1507 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1508 err = 0;
1509 Py_INCREF(dfltobj);
1510 retval = dfltobj;
1512 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1513 && self->moduleFlags.getReturnsNone) {
1514 err = 0;
1515 Py_INCREF(Py_None);
1516 retval = Py_None;
1518 else if (!err) {
1519 PyObject *pkeyObj;
1520 PyObject *dataObj;
1521 dataObj = PyString_FromStringAndSize(data.data, data.size);
1523 if (self->primaryDBType == DB_RECNO ||
1524 self->primaryDBType == DB_QUEUE)
1525 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1526 else
1527 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1529 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1531 PyObject *keyObj;
1532 int type = _DB_get_type(self);
1533 if (type == DB_RECNO || type == DB_QUEUE)
1534 keyObj = PyInt_FromLong(*(int *)key.data);
1535 else
1536 keyObj = PyString_FromStringAndSize(key.data, key.size);
1537 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1539 else /* return just the pkey and data */
1541 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1543 FREE_DBT(pkey);
1544 FREE_DBT(data);
1546 FREE_DBT(key);
1548 RETURN_IF_ERR();
1549 return retval;
1551 #endif
1554 /* Return size of entry */
1555 static PyObject*
1556 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1558 int err, flags=0;
1559 PyObject* txnobj = NULL;
1560 PyObject* keyobj;
1561 PyObject* retval = NULL;
1562 DBT key, data;
1563 DB_TXN *txn = NULL;
1564 static const char* kwnames[] = { "key", "txn", NULL };
1566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1567 &keyobj, &txnobj))
1568 return NULL;
1569 CHECK_DB_NOT_CLOSED(self);
1570 if (!make_key_dbt(self, keyobj, &key, &flags))
1571 return NULL;
1572 if (!checkTxnObj(txnobj, &txn)) {
1573 FREE_DBT(key);
1574 return NULL;
1576 CLEAR_DBT(data);
1578 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1579 thus getting the record size. */
1580 data.flags = DB_DBT_USERMEM;
1581 data.ulen = 0;
1582 MYDB_BEGIN_ALLOW_THREADS;
1583 err = self->db->get(self->db, txn, &key, &data, flags);
1584 MYDB_END_ALLOW_THREADS;
1585 if (err == DB_BUFFER_SMALL) {
1586 retval = PyInt_FromLong((long)data.size);
1587 err = 0;
1590 FREE_DBT(key);
1591 FREE_DBT(data);
1592 RETURN_IF_ERR();
1593 return retval;
1597 static PyObject*
1598 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1600 int err, flags=0;
1601 PyObject* txnobj = NULL;
1602 PyObject* keyobj;
1603 PyObject* dataobj;
1604 PyObject* retval = NULL;
1605 DBT key, data;
1606 DB_TXN *txn = NULL;
1607 static const char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1610 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1611 &keyobj, &dataobj, &txnobj, &flags))
1612 return NULL;
1614 CHECK_DB_NOT_CLOSED(self);
1615 if (!make_key_dbt(self, keyobj, &key, NULL))
1616 return NULL;
1617 if ( !make_dbt(dataobj, &data) ||
1618 !checkTxnObj(txnobj, &txn) )
1620 FREE_DBT(key);
1621 return NULL;
1624 flags |= DB_GET_BOTH;
1626 if (CHECK_DBFLAG(self, DB_THREAD)) {
1627 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1628 data.flags = DB_DBT_MALLOC;
1629 /* TODO: Is this flag needed? We're passing a data object that should
1630 match what's in the DB, so there should be no need to malloc.
1631 We run the risk of freeing something twice! Check this. */
1634 MYDB_BEGIN_ALLOW_THREADS;
1635 err = self->db->get(self->db, txn, &key, &data, flags);
1636 MYDB_END_ALLOW_THREADS;
1638 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1639 && self->moduleFlags.getReturnsNone) {
1640 err = 0;
1641 Py_INCREF(Py_None);
1642 retval = Py_None;
1644 else if (!err) {
1645 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1646 FREE_DBT(data); /* Only if retrieval was successful */
1649 FREE_DBT(key);
1650 RETURN_IF_ERR();
1651 return retval;
1655 static PyObject*
1656 DB_get_byteswapped(DBObject* self, PyObject* args)
1658 #if (DBVER >= 33)
1659 int err = 0;
1660 #endif
1661 int retval = -1;
1663 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1664 return NULL;
1665 CHECK_DB_NOT_CLOSED(self);
1667 #if (DBVER >= 33)
1668 MYDB_BEGIN_ALLOW_THREADS;
1669 err = self->db->get_byteswapped(self->db, &retval);
1670 MYDB_END_ALLOW_THREADS;
1671 RETURN_IF_ERR();
1672 #else
1673 MYDB_BEGIN_ALLOW_THREADS;
1674 retval = self->db->get_byteswapped(self->db);
1675 MYDB_END_ALLOW_THREADS;
1676 #endif
1677 return PyInt_FromLong(retval);
1681 static PyObject*
1682 DB_get_type(DBObject* self, PyObject* args)
1684 int type;
1686 if (!PyArg_ParseTuple(args,":get_type"))
1687 return NULL;
1688 CHECK_DB_NOT_CLOSED(self);
1690 MYDB_BEGIN_ALLOW_THREADS;
1691 type = _DB_get_type(self);
1692 MYDB_END_ALLOW_THREADS;
1693 if (type == -1)
1694 return NULL;
1695 return PyInt_FromLong(type);
1699 static PyObject*
1700 DB_join(DBObject* self, PyObject* args)
1702 int err, flags=0;
1703 int length, x;
1704 PyObject* cursorsObj;
1705 DBC** cursors;
1706 DBC* dbc;
1709 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1710 return NULL;
1712 CHECK_DB_NOT_CLOSED(self);
1714 if (!PySequence_Check(cursorsObj)) {
1715 PyErr_SetString(PyExc_TypeError,
1716 "Sequence of DBCursor objects expected");
1717 return NULL;
1720 length = PyObject_Length(cursorsObj);
1721 cursors = malloc((length+1) * sizeof(DBC*));
1722 cursors[length] = NULL;
1723 for (x=0; x<length; x++) {
1724 PyObject* item = PySequence_GetItem(cursorsObj, x);
1725 if (!DBCursorObject_Check(item)) {
1726 PyErr_SetString(PyExc_TypeError,
1727 "Sequence of DBCursor objects expected");
1728 free(cursors);
1729 return NULL;
1731 cursors[x] = ((DBCursorObject*)item)->dbc;
1734 MYDB_BEGIN_ALLOW_THREADS;
1735 err = self->db->join(self->db, cursors, &dbc, flags);
1736 MYDB_END_ALLOW_THREADS;
1737 free(cursors);
1738 RETURN_IF_ERR();
1740 /* FIXME: this is a buggy interface. The returned cursor
1741 contains internal references to the passed in cursors
1742 but does not hold python references to them or prevent
1743 them from being closed prematurely. This can cause
1744 python to crash when things are done in the wrong order. */
1745 return (PyObject*) newDBCursorObject(dbc, self);
1749 static PyObject*
1750 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1752 int err, flags=0;
1753 PyObject* txnobj = NULL;
1754 PyObject* keyobj;
1755 DBT key;
1756 DB_TXN *txn = NULL;
1757 DB_KEY_RANGE range;
1758 static const char* kwnames[] = { "key", "txn", "flags", NULL };
1760 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1761 &keyobj, &txnobj, &flags))
1762 return NULL;
1763 CHECK_DB_NOT_CLOSED(self);
1764 if (!make_dbt(keyobj, &key))
1765 /* BTree only, don't need to allow for an int key */
1766 return NULL;
1767 if (!checkTxnObj(txnobj, &txn))
1768 return NULL;
1770 MYDB_BEGIN_ALLOW_THREADS;
1771 err = self->db->key_range(self->db, txn, &key, &range, flags);
1772 MYDB_END_ALLOW_THREADS;
1774 RETURN_IF_ERR();
1775 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1779 static PyObject*
1780 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1782 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1783 char* filename = NULL;
1784 char* dbname = NULL;
1785 #if (DBVER >= 41)
1786 PyObject *txnobj = NULL;
1787 DB_TXN *txn = NULL;
1788 /* with dbname */
1789 static const char* kwnames[] = {
1790 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1791 /* without dbname */
1792 static const char* kwnames_basic[] = {
1793 "filename", "dbtype", "flags", "mode", "txn", NULL};
1794 #else
1795 /* with dbname */
1796 static const char* kwnames[] = {
1797 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1798 /* without dbname */
1799 static const char* kwnames_basic[] = {
1800 "filename", "dbtype", "flags", "mode", NULL};
1801 #endif
1803 #if (DBVER >= 41)
1804 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1805 &filename, &dbname, &type, &flags, &mode,
1806 &txnobj))
1807 #else
1808 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1809 &filename, &dbname, &type, &flags,
1810 &mode))
1811 #endif
1813 PyErr_Clear();
1814 type = DB_UNKNOWN; flags = 0; mode = 0660;
1815 filename = NULL; dbname = NULL;
1816 #if (DBVER >= 41)
1817 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1818 kwnames_basic,
1819 &filename, &type, &flags, &mode,
1820 &txnobj))
1821 return NULL;
1822 #else
1823 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1824 kwnames_basic,
1825 &filename, &type, &flags, &mode))
1826 return NULL;
1827 #endif
1830 #if (DBVER >= 41)
1831 if (!checkTxnObj(txnobj, &txn)) return NULL;
1832 #endif
1834 if (NULL == self->db) {
1835 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1836 "Cannot call open() twice for DB object"));
1837 return NULL;
1840 #if 0 && (DBVER >= 41)
1841 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1842 && (self->myenvobj->flags & DB_INIT_TXN))
1844 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1845 * explicitly passed) but we are in a transaction ready environment:
1846 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1847 * to work on BerkeleyDB 4.1 without needing to modify their
1848 * DBEnv or DB open calls.
1849 * TODO make this behaviour of the library configurable.
1851 flags |= DB_AUTO_COMMIT;
1853 #endif
1855 MYDB_BEGIN_ALLOW_THREADS;
1856 #if (DBVER >= 41)
1857 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1858 #else
1859 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1860 #endif
1861 MYDB_END_ALLOW_THREADS;
1862 if (makeDBError(err)) {
1863 self->db->close(self->db, 0);
1864 self->db = NULL;
1865 return NULL;
1868 self->flags = flags;
1869 RETURN_NONE();
1873 static PyObject*
1874 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1876 int flags=0;
1877 PyObject* txnobj = NULL;
1878 int dlen = -1;
1879 int doff = -1;
1880 PyObject* keyobj, *dataobj, *retval;
1881 DBT key, data;
1882 DB_TXN *txn = NULL;
1883 static const char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1884 "doff", NULL };
1886 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1887 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1888 return NULL;
1890 CHECK_DB_NOT_CLOSED(self);
1891 if (!make_key_dbt(self, keyobj, &key, NULL))
1892 return NULL;
1893 if ( !make_dbt(dataobj, &data) ||
1894 !add_partial_dbt(&data, dlen, doff) ||
1895 !checkTxnObj(txnobj, &txn) )
1897 FREE_DBT(key);
1898 return NULL;
1901 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1902 FREE_DBT(key);
1903 return NULL;
1906 if (flags & DB_APPEND)
1907 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1908 else {
1909 retval = Py_None;
1910 Py_INCREF(retval);
1912 FREE_DBT(key);
1913 return retval;
1918 static PyObject*
1919 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1921 char* filename;
1922 char* database = NULL;
1923 int err, flags=0;
1924 static const char* kwnames[] = { "filename", "dbname", "flags", NULL};
1926 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1927 &filename, &database, &flags))
1928 return NULL;
1929 CHECK_DB_NOT_CLOSED(self);
1931 err = self->db->remove(self->db, filename, database, flags);
1932 self->db = NULL;
1933 RETURN_IF_ERR();
1934 RETURN_NONE();
1939 static PyObject*
1940 DB_rename(DBObject* self, PyObject* args)
1942 char* filename;
1943 char* database;
1944 char* newname;
1945 int err, flags=0;
1947 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1948 &flags))
1949 return NULL;
1950 CHECK_DB_NOT_CLOSED(self);
1952 MYDB_BEGIN_ALLOW_THREADS;
1953 err = self->db->rename(self->db, filename, database, newname, flags);
1954 MYDB_END_ALLOW_THREADS;
1955 RETURN_IF_ERR();
1956 RETURN_NONE();
1960 static PyObject*
1961 DB_set_bt_minkey(DBObject* self, PyObject* args)
1963 int err, minkey;
1965 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1966 return NULL;
1967 CHECK_DB_NOT_CLOSED(self);
1969 MYDB_BEGIN_ALLOW_THREADS;
1970 err = self->db->set_bt_minkey(self->db, minkey);
1971 MYDB_END_ALLOW_THREADS;
1972 RETURN_IF_ERR();
1973 RETURN_NONE();
1976 #if (DBVER >= 33)
1977 static int
1978 _default_cmp (const DBT *leftKey,
1979 const DBT *rightKey)
1981 int res;
1982 int lsize = leftKey->size, rsize = rightKey->size;
1984 res = memcmp (leftKey->data, rightKey->data,
1985 lsize < rsize ? lsize : rsize);
1987 if (res == 0) {
1988 if (lsize < rsize) {
1989 res = -1;
1991 else if (lsize > rsize) {
1992 res = 1;
1995 return res;
1998 static int
1999 _db_compareCallback (DB* db,
2000 const DBT *leftKey,
2001 const DBT *rightKey)
2003 int res = 0;
2004 PyObject *args;
2005 PyObject *result;
2006 PyObject *leftObject;
2007 PyObject *rightObject;
2008 DBObject *self = (DBObject *) db->app_private;
2010 if (self == NULL || self->btCompareCallback == NULL) {
2011 MYDB_BEGIN_BLOCK_THREADS;
2012 PyErr_SetString (PyExc_TypeError,
2013 (self == 0
2014 ? "DB_bt_compare db is NULL."
2015 : "DB_bt_compare callback is NULL."));
2016 /* we're in a callback within the DB code, we can't raise */
2017 PyErr_Print ();
2018 res = _default_cmp (leftKey, rightKey);
2019 MYDB_END_BLOCK_THREADS;
2021 else {
2022 MYDB_BEGIN_BLOCK_THREADS;
2024 leftObject = PyString_FromStringAndSize (leftKey->data, leftKey->size);
2025 rightObject = PyString_FromStringAndSize (rightKey->data, rightKey->size);
2027 args = PyTuple_New (2);
2028 Py_INCREF (self);
2029 PyTuple_SET_ITEM (args, 0, leftObject); /* steals reference */
2030 PyTuple_SET_ITEM (args, 1, rightObject); /* steals reference */
2032 result = PyEval_CallObject (self->btCompareCallback, args);
2033 if (result == 0) {
2034 /* we're in a callback within the DB code, we can't raise */
2035 PyErr_Print ();
2036 res = _default_cmp (leftKey, rightKey);
2038 else if (PyInt_Check (result)) {
2039 res = PyInt_AsLong (result);
2041 else {
2042 PyErr_SetString (PyExc_TypeError,
2043 "DB_bt_compare callback MUST return an int.");
2044 /* we're in a callback within the DB code, we can't raise */
2045 PyErr_Print ();
2046 res = _default_cmp (leftKey, rightKey);
2049 Py_DECREF (args);
2050 Py_XDECREF (result);
2052 MYDB_END_BLOCK_THREADS;
2054 return res;
2057 static PyObject*
2058 DB_set_bt_compare (DBObject* self, PyObject* args)
2060 int err;
2061 PyObject *comparator;
2062 PyObject *tuple, *emptyStr, *result;
2064 if (!PyArg_ParseTuple(args,"O:set_bt_compare", &comparator ))
2065 return NULL;
2067 CHECK_DB_NOT_CLOSED (self);
2069 if (! PyCallable_Check (comparator)) {
2070 makeTypeError ("Callable", comparator);
2071 return NULL;
2075 * Perform a test call of the comparator function with two empty
2076 * string objects here. verify that it returns an int (0).
2077 * err if not.
2079 tuple = PyTuple_New (2);
2081 emptyStr = PyString_FromStringAndSize (NULL, 0);
2082 Py_INCREF(emptyStr);
2083 PyTuple_SET_ITEM (tuple, 0, emptyStr);
2084 PyTuple_SET_ITEM (tuple, 1, emptyStr); /* steals reference */
2085 result = PyEval_CallObject (comparator, tuple);
2086 Py_DECREF (tuple);
2087 if (result == 0 || !PyInt_Check(result)) {
2088 PyErr_SetString (PyExc_TypeError,
2089 "callback MUST return an int");
2090 return NULL;
2092 else if (PyInt_AsLong(result) != 0) {
2093 PyErr_SetString (PyExc_TypeError,
2094 "callback failed to return 0 on two empty strings");
2095 return NULL;
2098 /* We don't accept multiple set_bt_compare operations, in order to
2099 * simplify the code. This would have no real use, as one cannot
2100 * change the function once the db is opened anyway */
2101 if (self->btCompareCallback != NULL) {
2102 PyErr_SetString (PyExc_RuntimeError, "set_bt_compare () cannot be called more than once");
2103 return NULL;
2106 Py_INCREF (comparator);
2107 self->btCompareCallback = comparator;
2109 /* This is to workaround a problem with un-initialized threads (see
2110 comment in DB_associate) */
2111 #ifdef WITH_THREAD
2112 PyEval_InitThreads();
2113 #endif
2115 err = self->db->set_bt_compare (self->db,
2116 (comparator != NULL ?
2117 _db_compareCallback : NULL));
2119 if (err) {
2120 /* restore the old state in case of error */
2121 Py_DECREF (comparator);
2122 self->btCompareCallback = NULL;
2125 RETURN_IF_ERR ();
2126 RETURN_NONE ();
2128 #endif /* DBVER >= 33 */
2131 static PyObject*
2132 DB_set_cachesize(DBObject* self, PyObject* args)
2134 int err;
2135 int gbytes = 0, bytes = 0, ncache = 0;
2137 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2138 &gbytes,&bytes,&ncache))
2139 return NULL;
2140 CHECK_DB_NOT_CLOSED(self);
2142 MYDB_BEGIN_ALLOW_THREADS;
2143 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2144 MYDB_END_ALLOW_THREADS;
2145 RETURN_IF_ERR();
2146 RETURN_NONE();
2150 static PyObject*
2151 DB_set_flags(DBObject* self, PyObject* args)
2153 int err, flags;
2155 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2156 return NULL;
2157 CHECK_DB_NOT_CLOSED(self);
2159 MYDB_BEGIN_ALLOW_THREADS;
2160 err = self->db->set_flags(self->db, flags);
2161 MYDB_END_ALLOW_THREADS;
2162 RETURN_IF_ERR();
2164 self->setflags |= flags;
2165 RETURN_NONE();
2169 static PyObject*
2170 DB_set_h_ffactor(DBObject* self, PyObject* args)
2172 int err, ffactor;
2174 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2175 return NULL;
2176 CHECK_DB_NOT_CLOSED(self);
2178 MYDB_BEGIN_ALLOW_THREADS;
2179 err = self->db->set_h_ffactor(self->db, ffactor);
2180 MYDB_END_ALLOW_THREADS;
2181 RETURN_IF_ERR();
2182 RETURN_NONE();
2186 static PyObject*
2187 DB_set_h_nelem(DBObject* self, PyObject* args)
2189 int err, nelem;
2191 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2192 return NULL;
2193 CHECK_DB_NOT_CLOSED(self);
2195 MYDB_BEGIN_ALLOW_THREADS;
2196 err = self->db->set_h_nelem(self->db, nelem);
2197 MYDB_END_ALLOW_THREADS;
2198 RETURN_IF_ERR();
2199 RETURN_NONE();
2203 static PyObject*
2204 DB_set_lorder(DBObject* self, PyObject* args)
2206 int err, lorder;
2208 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2209 return NULL;
2210 CHECK_DB_NOT_CLOSED(self);
2212 MYDB_BEGIN_ALLOW_THREADS;
2213 err = self->db->set_lorder(self->db, lorder);
2214 MYDB_END_ALLOW_THREADS;
2215 RETURN_IF_ERR();
2216 RETURN_NONE();
2220 static PyObject*
2221 DB_set_pagesize(DBObject* self, PyObject* args)
2223 int err, pagesize;
2225 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2226 return NULL;
2227 CHECK_DB_NOT_CLOSED(self);
2229 MYDB_BEGIN_ALLOW_THREADS;
2230 err = self->db->set_pagesize(self->db, pagesize);
2231 MYDB_END_ALLOW_THREADS;
2232 RETURN_IF_ERR();
2233 RETURN_NONE();
2237 static PyObject*
2238 DB_set_re_delim(DBObject* self, PyObject* args)
2240 int err;
2241 char delim;
2243 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2244 PyErr_Clear();
2245 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2246 return NULL;
2249 CHECK_DB_NOT_CLOSED(self);
2251 MYDB_BEGIN_ALLOW_THREADS;
2252 err = self->db->set_re_delim(self->db, delim);
2253 MYDB_END_ALLOW_THREADS;
2254 RETURN_IF_ERR();
2255 RETURN_NONE();
2258 static PyObject*
2259 DB_set_re_len(DBObject* self, PyObject* args)
2261 int err, len;
2263 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_re_len(self->db, len);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271 RETURN_NONE();
2275 static PyObject*
2276 DB_set_re_pad(DBObject* self, PyObject* args)
2278 int err;
2279 char pad;
2281 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2282 PyErr_Clear();
2283 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2284 return NULL;
2286 CHECK_DB_NOT_CLOSED(self);
2288 MYDB_BEGIN_ALLOW_THREADS;
2289 err = self->db->set_re_pad(self->db, pad);
2290 MYDB_END_ALLOW_THREADS;
2291 RETURN_IF_ERR();
2292 RETURN_NONE();
2296 static PyObject*
2297 DB_set_re_source(DBObject* self, PyObject* args)
2299 int err;
2300 char *re_source;
2302 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2303 return NULL;
2304 CHECK_DB_NOT_CLOSED(self);
2306 MYDB_BEGIN_ALLOW_THREADS;
2307 err = self->db->set_re_source(self->db, re_source);
2308 MYDB_END_ALLOW_THREADS;
2309 RETURN_IF_ERR();
2310 RETURN_NONE();
2314 #if (DBVER >= 32)
2315 static PyObject*
2316 DB_set_q_extentsize(DBObject* self, PyObject* args)
2318 int err;
2319 int extentsize;
2321 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2322 return NULL;
2323 CHECK_DB_NOT_CLOSED(self);
2325 MYDB_BEGIN_ALLOW_THREADS;
2326 err = self->db->set_q_extentsize(self->db, extentsize);
2327 MYDB_END_ALLOW_THREADS;
2328 RETURN_IF_ERR();
2329 RETURN_NONE();
2331 #endif
2333 static PyObject*
2334 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2336 int err, flags = 0, type;
2337 void* sp;
2338 PyObject* d;
2339 #if (DBVER >= 43)
2340 PyObject* txnobj = NULL;
2341 DB_TXN *txn = NULL;
2342 static const char* kwnames[] = { "txn", "flags", NULL };
2343 #else
2344 static const char* kwnames[] = { "flags", NULL };
2345 #endif
2347 #if (DBVER >= 43)
2348 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2349 &flags, &txnobj))
2350 return NULL;
2351 if (!checkTxnObj(txnobj, &txn))
2352 return NULL;
2353 #else
2354 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2355 return NULL;
2356 #endif
2357 CHECK_DB_NOT_CLOSED(self);
2359 MYDB_BEGIN_ALLOW_THREADS;
2360 #if (DBVER >= 43)
2361 err = self->db->stat(self->db, txn, &sp, flags);
2362 #elif (DBVER >= 33)
2363 err = self->db->stat(self->db, &sp, flags);
2364 #else
2365 err = self->db->stat(self->db, &sp, NULL, flags);
2366 #endif
2367 MYDB_END_ALLOW_THREADS;
2368 RETURN_IF_ERR();
2370 self->haveStat = 1;
2372 /* Turn the stat structure into a dictionary */
2373 type = _DB_get_type(self);
2374 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2375 free(sp);
2376 return NULL;
2379 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2380 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2381 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2383 switch (type) {
2384 case DB_HASH:
2385 MAKE_HASH_ENTRY(magic);
2386 MAKE_HASH_ENTRY(version);
2387 MAKE_HASH_ENTRY(nkeys);
2388 MAKE_HASH_ENTRY(ndata);
2389 MAKE_HASH_ENTRY(pagesize);
2390 #if (DBVER < 41)
2391 MAKE_HASH_ENTRY(nelem);
2392 #endif
2393 MAKE_HASH_ENTRY(ffactor);
2394 MAKE_HASH_ENTRY(buckets);
2395 MAKE_HASH_ENTRY(free);
2396 MAKE_HASH_ENTRY(bfree);
2397 MAKE_HASH_ENTRY(bigpages);
2398 MAKE_HASH_ENTRY(big_bfree);
2399 MAKE_HASH_ENTRY(overflows);
2400 MAKE_HASH_ENTRY(ovfl_free);
2401 MAKE_HASH_ENTRY(dup);
2402 MAKE_HASH_ENTRY(dup_free);
2403 break;
2405 case DB_BTREE:
2406 case DB_RECNO:
2407 MAKE_BT_ENTRY(magic);
2408 MAKE_BT_ENTRY(version);
2409 MAKE_BT_ENTRY(nkeys);
2410 MAKE_BT_ENTRY(ndata);
2411 MAKE_BT_ENTRY(pagesize);
2412 MAKE_BT_ENTRY(minkey);
2413 MAKE_BT_ENTRY(re_len);
2414 MAKE_BT_ENTRY(re_pad);
2415 MAKE_BT_ENTRY(levels);
2416 MAKE_BT_ENTRY(int_pg);
2417 MAKE_BT_ENTRY(leaf_pg);
2418 MAKE_BT_ENTRY(dup_pg);
2419 MAKE_BT_ENTRY(over_pg);
2420 MAKE_BT_ENTRY(free);
2421 MAKE_BT_ENTRY(int_pgfree);
2422 MAKE_BT_ENTRY(leaf_pgfree);
2423 MAKE_BT_ENTRY(dup_pgfree);
2424 MAKE_BT_ENTRY(over_pgfree);
2425 break;
2427 case DB_QUEUE:
2428 MAKE_QUEUE_ENTRY(magic);
2429 MAKE_QUEUE_ENTRY(version);
2430 MAKE_QUEUE_ENTRY(nkeys);
2431 MAKE_QUEUE_ENTRY(ndata);
2432 MAKE_QUEUE_ENTRY(pagesize);
2433 MAKE_QUEUE_ENTRY(pages);
2434 MAKE_QUEUE_ENTRY(re_len);
2435 MAKE_QUEUE_ENTRY(re_pad);
2436 MAKE_QUEUE_ENTRY(pgfree);
2437 #if (DBVER == 31)
2438 MAKE_QUEUE_ENTRY(start);
2439 #endif
2440 MAKE_QUEUE_ENTRY(first_recno);
2441 MAKE_QUEUE_ENTRY(cur_recno);
2442 break;
2444 default:
2445 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2446 Py_DECREF(d);
2447 d = NULL;
2450 #undef MAKE_HASH_ENTRY
2451 #undef MAKE_BT_ENTRY
2452 #undef MAKE_QUEUE_ENTRY
2454 free(sp);
2455 return d;
2458 static PyObject*
2459 DB_sync(DBObject* self, PyObject* args)
2461 int err;
2462 int flags = 0;
2464 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2465 return NULL;
2466 CHECK_DB_NOT_CLOSED(self);
2468 MYDB_BEGIN_ALLOW_THREADS;
2469 err = self->db->sync(self->db, flags);
2470 MYDB_END_ALLOW_THREADS;
2471 RETURN_IF_ERR();
2472 RETURN_NONE();
2476 #if (DBVER >= 33)
2477 static PyObject*
2478 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2480 int err, flags=0;
2481 u_int32_t count=0;
2482 PyObject* txnobj = NULL;
2483 DB_TXN *txn = NULL;
2484 static const char* kwnames[] = { "txn", "flags", NULL };
2486 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2487 &txnobj, &flags))
2488 return NULL;
2489 CHECK_DB_NOT_CLOSED(self);
2490 if (!checkTxnObj(txnobj, &txn))
2491 return NULL;
2493 MYDB_BEGIN_ALLOW_THREADS;
2494 err = self->db->truncate(self->db, txn, &count, flags);
2495 MYDB_END_ALLOW_THREADS;
2496 RETURN_IF_ERR();
2497 return PyInt_FromLong(count);
2499 #endif
2502 static PyObject*
2503 DB_upgrade(DBObject* self, PyObject* args)
2505 int err, flags=0;
2506 char *filename;
2508 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2509 return NULL;
2510 CHECK_DB_NOT_CLOSED(self);
2512 MYDB_BEGIN_ALLOW_THREADS;
2513 err = self->db->upgrade(self->db, filename, flags);
2514 MYDB_END_ALLOW_THREADS;
2515 RETURN_IF_ERR();
2516 RETURN_NONE();
2520 static PyObject*
2521 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2523 int err, flags=0;
2524 char* fileName;
2525 char* dbName=NULL;
2526 char* outFileName=NULL;
2527 FILE* outFile=NULL;
2528 static const char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2529 NULL };
2531 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2532 &fileName, &dbName, &outFileName, &flags))
2533 return NULL;
2535 CHECK_DB_NOT_CLOSED(self);
2536 if (outFileName)
2537 outFile = fopen(outFileName, "w");
2539 MYDB_BEGIN_ALLOW_THREADS;
2540 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2541 MYDB_END_ALLOW_THREADS;
2542 if (outFileName)
2543 fclose(outFile);
2545 /* DB.verify acts as a DB handle destructor (like close); this was
2546 * documented in BerkeleyDB 4.2 but had the undocumented effect
2547 * of not being safe in prior versions while still requiring an explicit
2548 * DB.close call afterwards. Lets call close for the user to emulate
2549 * the safe 4.2 behaviour. */
2550 #if (DBVER <= 41)
2551 self->db->close(self->db, 0);
2552 #endif
2553 self->db = NULL;
2555 RETURN_IF_ERR();
2556 RETURN_NONE();
2560 static PyObject*
2561 DB_set_get_returns_none(DBObject* self, PyObject* args)
2563 int flags=0;
2564 int oldValue=0;
2566 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2567 return NULL;
2568 CHECK_DB_NOT_CLOSED(self);
2570 if (self->moduleFlags.getReturnsNone)
2571 ++oldValue;
2572 if (self->moduleFlags.cursorSetReturnsNone)
2573 ++oldValue;
2574 self->moduleFlags.getReturnsNone = (flags >= 1);
2575 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2576 return PyInt_FromLong(oldValue);
2579 #if (DBVER >= 41)
2580 static PyObject*
2581 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2583 int err;
2584 u_int32_t flags=0;
2585 char *passwd = NULL;
2586 static const char* kwnames[] = { "passwd", "flags", NULL };
2588 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2589 &passwd, &flags)) {
2590 return NULL;
2593 MYDB_BEGIN_ALLOW_THREADS;
2594 err = self->db->set_encrypt(self->db, passwd, flags);
2595 MYDB_END_ALLOW_THREADS;
2597 RETURN_IF_ERR();
2598 RETURN_NONE();
2600 #endif /* DBVER >= 41 */
2603 /*-------------------------------------------------------------- */
2604 /* Mapping and Dictionary-like access routines */
2606 int DB_length(DBObject* self)
2608 int err;
2609 long size = 0;
2610 int flags = 0;
2611 void* sp;
2613 if (self->db == NULL) {
2614 PyErr_SetObject(DBError,
2615 Py_BuildValue("(is)", 0, "DB object has been closed"));
2616 return -1;
2619 if (self->haveStat) { /* Has the stat function been called recently? If
2620 so, we can use the cached value. */
2621 flags = DB_CACHED_COUNTS;
2624 MYDB_BEGIN_ALLOW_THREADS;
2625 #if (DBVER >= 43)
2626 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2627 #elif (DBVER >= 33)
2628 err = self->db->stat(self->db, &sp, flags);
2629 #else
2630 err = self->db->stat(self->db, &sp, NULL, flags);
2631 #endif
2632 MYDB_END_ALLOW_THREADS;
2634 if (err)
2635 return -1;
2637 self->haveStat = 1;
2639 /* All the stat structures have matching fields upto the ndata field,
2640 so we can use any of them for the type cast */
2641 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2642 free(sp);
2643 return size;
2647 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2649 int err;
2650 PyObject* retval;
2651 DBT key;
2652 DBT data;
2654 CHECK_DB_NOT_CLOSED(self);
2655 if (!make_key_dbt(self, keyobj, &key, NULL))
2656 return NULL;
2658 CLEAR_DBT(data);
2659 if (CHECK_DBFLAG(self, DB_THREAD)) {
2660 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2661 data.flags = DB_DBT_MALLOC;
2663 MYDB_BEGIN_ALLOW_THREADS;
2664 err = self->db->get(self->db, NULL, &key, &data, 0);
2665 MYDB_END_ALLOW_THREADS;
2666 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2667 PyErr_SetObject(PyExc_KeyError, keyobj);
2668 retval = NULL;
2670 else if (makeDBError(err)) {
2671 retval = NULL;
2673 else {
2674 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2675 FREE_DBT(data);
2678 FREE_DBT(key);
2679 return retval;
2683 static int
2684 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2686 DBT key, data;
2687 int retval;
2688 int flags = 0;
2690 if (self->db == NULL) {
2691 PyErr_SetObject(DBError,
2692 Py_BuildValue("(is)", 0, "DB object has been closed"));
2693 return -1;
2696 if (!make_key_dbt(self, keyobj, &key, NULL))
2697 return -1;
2699 if (dataobj != NULL) {
2700 if (!make_dbt(dataobj, &data))
2701 retval = -1;
2702 else {
2703 if (self->setflags & (DB_DUP|DB_DUPSORT))
2704 /* dictionaries shouldn't have duplicate keys */
2705 flags = DB_NOOVERWRITE;
2706 retval = _DB_put(self, NULL, &key, &data, flags);
2708 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2709 /* try deleting any old record that matches and then PUT it
2710 * again... */
2711 _DB_delete(self, NULL, &key, 0);
2712 PyErr_Clear();
2713 retval = _DB_put(self, NULL, &key, &data, flags);
2717 else {
2718 /* dataobj == NULL, so delete the key */
2719 retval = _DB_delete(self, NULL, &key, 0);
2721 FREE_DBT(key);
2722 return retval;
2726 static PyObject*
2727 DB_has_key(DBObject* self, PyObject* args)
2729 int err;
2730 PyObject* keyobj;
2731 DBT key, data;
2732 PyObject* txnobj = NULL;
2733 DB_TXN *txn = NULL;
2735 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2736 return NULL;
2737 CHECK_DB_NOT_CLOSED(self);
2738 if (!make_key_dbt(self, keyobj, &key, NULL))
2739 return NULL;
2740 if (!checkTxnObj(txnobj, &txn)) {
2741 FREE_DBT(key);
2742 return NULL;
2745 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2746 it has a record but can't allocate a buffer for the data. This saves
2747 having to deal with data we won't be using.
2749 CLEAR_DBT(data);
2750 data.flags = DB_DBT_USERMEM;
2752 MYDB_BEGIN_ALLOW_THREADS;
2753 err = self->db->get(self->db, txn, &key, &data, 0);
2754 MYDB_END_ALLOW_THREADS;
2755 FREE_DBT(key);
2757 if (err == DB_BUFFER_SMALL || err == 0) {
2758 return PyInt_FromLong(1);
2759 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2760 return PyInt_FromLong(0);
2763 makeDBError(err);
2764 return NULL;
2768 #define _KEYS_LIST 1
2769 #define _VALUES_LIST 2
2770 #define _ITEMS_LIST 3
2772 static PyObject*
2773 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2775 int err, dbtype;
2776 DBT key;
2777 DBT data;
2778 DBC *cursor;
2779 PyObject* list;
2780 PyObject* item = NULL;
2782 CHECK_DB_NOT_CLOSED(self);
2783 CLEAR_DBT(key);
2784 CLEAR_DBT(data);
2786 dbtype = _DB_get_type(self);
2787 if (dbtype == -1)
2788 return NULL;
2790 list = PyList_New(0);
2791 if (list == NULL) {
2792 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2793 return NULL;
2796 /* get a cursor */
2797 MYDB_BEGIN_ALLOW_THREADS;
2798 err = self->db->cursor(self->db, txn, &cursor, 0);
2799 MYDB_END_ALLOW_THREADS;
2800 RETURN_IF_ERR();
2802 if (CHECK_DBFLAG(self, DB_THREAD)) {
2803 key.flags = DB_DBT_REALLOC;
2804 data.flags = DB_DBT_REALLOC;
2807 while (1) { /* use the cursor to traverse the DB, collecting items */
2808 MYDB_BEGIN_ALLOW_THREADS;
2809 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2810 MYDB_END_ALLOW_THREADS;
2812 if (err) {
2813 /* for any error, break out of the loop */
2814 break;
2817 switch (type) {
2818 case _KEYS_LIST:
2819 switch(dbtype) {
2820 case DB_BTREE:
2821 case DB_HASH:
2822 default:
2823 item = PyString_FromStringAndSize((char*)key.data, key.size);
2824 break;
2825 case DB_RECNO:
2826 case DB_QUEUE:
2827 item = PyInt_FromLong(*((db_recno_t*)key.data));
2828 break;
2830 break;
2832 case _VALUES_LIST:
2833 item = PyString_FromStringAndSize((char*)data.data, data.size);
2834 break;
2836 case _ITEMS_LIST:
2837 switch(dbtype) {
2838 case DB_BTREE:
2839 case DB_HASH:
2840 default:
2841 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2842 data.size);
2843 break;
2844 case DB_RECNO:
2845 case DB_QUEUE:
2846 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2847 data.data, data.size);
2848 break;
2850 break;
2852 if (item == NULL) {
2853 Py_DECREF(list);
2854 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2855 list = NULL;
2856 goto done;
2858 PyList_Append(list, item);
2859 Py_DECREF(item);
2862 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2863 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2864 Py_DECREF(list);
2865 list = NULL;
2868 done:
2869 FREE_DBT(key);
2870 FREE_DBT(data);
2871 MYDB_BEGIN_ALLOW_THREADS;
2872 cursor->c_close(cursor);
2873 MYDB_END_ALLOW_THREADS;
2874 return list;
2878 static PyObject*
2879 DB_keys(DBObject* self, PyObject* args)
2881 PyObject* txnobj = NULL;
2882 DB_TXN *txn = NULL;
2884 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2885 return NULL;
2886 if (!checkTxnObj(txnobj, &txn))
2887 return NULL;
2888 return _DB_make_list(self, txn, _KEYS_LIST);
2892 static PyObject*
2893 DB_items(DBObject* self, PyObject* args)
2895 PyObject* txnobj = NULL;
2896 DB_TXN *txn = NULL;
2898 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2899 return NULL;
2900 if (!checkTxnObj(txnobj, &txn))
2901 return NULL;
2902 return _DB_make_list(self, txn, _ITEMS_LIST);
2906 static PyObject*
2907 DB_values(DBObject* self, PyObject* args)
2909 PyObject* txnobj = NULL;
2910 DB_TXN *txn = NULL;
2912 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2913 return NULL;
2914 if (!checkTxnObj(txnobj, &txn))
2915 return NULL;
2916 return _DB_make_list(self, txn, _VALUES_LIST);
2919 /* --------------------------------------------------------------------- */
2920 /* DBCursor methods */
2923 static PyObject*
2924 DBC_close(DBCursorObject* self, PyObject* args)
2926 int err = 0;
2928 if (!PyArg_ParseTuple(args, ":close"))
2929 return NULL;
2931 if (self->dbc != NULL) {
2932 MYDB_BEGIN_ALLOW_THREADS;
2933 err = self->dbc->c_close(self->dbc);
2934 self->dbc = NULL;
2935 MYDB_END_ALLOW_THREADS;
2937 RETURN_IF_ERR();
2938 RETURN_NONE();
2942 static PyObject*
2943 DBC_count(DBCursorObject* self, PyObject* args)
2945 int err = 0;
2946 db_recno_t count;
2947 int flags = 0;
2949 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2950 return NULL;
2952 CHECK_CURSOR_NOT_CLOSED(self);
2954 MYDB_BEGIN_ALLOW_THREADS;
2955 err = self->dbc->c_count(self->dbc, &count, flags);
2956 MYDB_END_ALLOW_THREADS;
2957 RETURN_IF_ERR();
2959 return PyInt_FromLong(count);
2963 static PyObject*
2964 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2966 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2970 static PyObject*
2971 DBC_delete(DBCursorObject* self, PyObject* args)
2973 int err, flags=0;
2975 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2976 return NULL;
2978 CHECK_CURSOR_NOT_CLOSED(self);
2980 MYDB_BEGIN_ALLOW_THREADS;
2981 err = self->dbc->c_del(self->dbc, flags);
2982 MYDB_END_ALLOW_THREADS;
2983 RETURN_IF_ERR();
2985 self->mydb->haveStat = 0;
2986 RETURN_NONE();
2990 static PyObject*
2991 DBC_dup(DBCursorObject* self, PyObject* args)
2993 int err, flags =0;
2994 DBC* dbc = NULL;
2996 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2997 return NULL;
2999 CHECK_CURSOR_NOT_CLOSED(self);
3001 MYDB_BEGIN_ALLOW_THREADS;
3002 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3003 MYDB_END_ALLOW_THREADS;
3004 RETURN_IF_ERR();
3006 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3009 static PyObject*
3010 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3012 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3016 static PyObject*
3017 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3019 int err, flags=0;
3020 PyObject* keyobj = NULL;
3021 PyObject* dataobj = NULL;
3022 PyObject* retval = NULL;
3023 int dlen = -1;
3024 int doff = -1;
3025 DBT key, data;
3026 static const char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3027 NULL };
3029 CLEAR_DBT(key);
3030 CLEAR_DBT(data);
3031 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3032 &flags, &dlen, &doff))
3034 PyErr_Clear();
3035 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3036 &kwnames[1],
3037 &keyobj, &flags, &dlen, &doff))
3039 PyErr_Clear();
3040 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3041 kwnames, &keyobj, &dataobj,
3042 &flags, &dlen, &doff))
3044 return NULL;
3049 CHECK_CURSOR_NOT_CLOSED(self);
3051 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3052 return NULL;
3053 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3054 (!add_partial_dbt(&data, dlen, doff)) )
3056 FREE_DBT(key);
3057 return NULL;
3060 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3061 data.flags = DB_DBT_MALLOC;
3062 if (!(key.flags & DB_DBT_REALLOC)) {
3063 key.flags |= DB_DBT_MALLOC;
3067 MYDB_BEGIN_ALLOW_THREADS;
3068 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3069 MYDB_END_ALLOW_THREADS;
3071 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3072 && self->mydb->moduleFlags.getReturnsNone) {
3073 Py_INCREF(Py_None);
3074 retval = Py_None;
3076 else if (makeDBError(err)) {
3077 retval = NULL;
3079 else {
3080 switch (_DB_get_type(self->mydb)) {
3081 case -1:
3082 retval = NULL;
3083 break;
3084 case DB_BTREE:
3085 case DB_HASH:
3086 default:
3087 retval = Py_BuildValue("s#s#", key.data, key.size,
3088 data.data, data.size);
3089 break;
3090 case DB_RECNO:
3091 case DB_QUEUE:
3092 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3093 data.data, data.size);
3094 break;
3096 FREE_DBT(data);
3098 FREE_DBT(key);
3099 return retval;
3102 #if (DBVER >= 33)
3103 static PyObject*
3104 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3106 int err, flags=0;
3107 PyObject* keyobj = NULL;
3108 PyObject* dataobj = NULL;
3109 PyObject* retval = NULL;
3110 int dlen = -1;
3111 int doff = -1;
3112 DBT key, pkey, data;
3113 static const char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3114 NULL };
3116 CLEAR_DBT(key);
3117 CLEAR_DBT(data);
3118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3119 &flags, &dlen, &doff))
3121 PyErr_Clear();
3122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3123 &kwnames[1],
3124 &keyobj, &flags, &dlen, &doff))
3126 PyErr_Clear();
3127 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3128 kwnames, &keyobj, &dataobj,
3129 &flags, &dlen, &doff))
3131 return NULL;
3136 CHECK_CURSOR_NOT_CLOSED(self);
3138 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3139 return NULL;
3140 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3141 (!add_partial_dbt(&data, dlen, doff)) ) {
3142 FREE_DBT(key);
3143 return NULL;
3146 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3147 data.flags = DB_DBT_MALLOC;
3148 if (!(key.flags & DB_DBT_REALLOC)) {
3149 key.flags |= DB_DBT_MALLOC;
3153 CLEAR_DBT(pkey);
3154 pkey.flags = DB_DBT_MALLOC;
3156 MYDB_BEGIN_ALLOW_THREADS;
3157 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3158 MYDB_END_ALLOW_THREADS;
3160 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3161 && self->mydb->moduleFlags.getReturnsNone) {
3162 Py_INCREF(Py_None);
3163 retval = Py_None;
3165 else if (makeDBError(err)) {
3166 retval = NULL;
3168 else {
3169 PyObject *pkeyObj;
3170 PyObject *dataObj;
3171 dataObj = PyString_FromStringAndSize(data.data, data.size);
3173 if (self->mydb->primaryDBType == DB_RECNO ||
3174 self->mydb->primaryDBType == DB_QUEUE)
3175 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3176 else
3177 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3179 if (flags & DB_SET_RECNO) /* return key, pkey and data */
3181 PyObject *keyObj;
3182 int type = _DB_get_type(self->mydb);
3183 if (type == DB_RECNO || type == DB_QUEUE)
3184 keyObj = PyInt_FromLong(*(int *)key.data);
3185 else
3186 keyObj = PyString_FromStringAndSize(key.data, key.size);
3187 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3188 FREE_DBT(key);
3190 else /* return just the pkey and data */
3192 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3194 FREE_DBT(pkey);
3195 FREE_DBT(data);
3197 /* the only time REALLOC should be set is if we used an integer
3198 * key that make_key_dbt malloc'd for us. always free these. */
3199 if (key.flags & DB_DBT_REALLOC) {
3200 FREE_DBT(key);
3202 return retval;
3204 #endif
3207 static PyObject*
3208 DBC_get_recno(DBCursorObject* self, PyObject* args)
3210 int err;
3211 db_recno_t recno;
3212 DBT key;
3213 DBT data;
3215 if (!PyArg_ParseTuple(args, ":get_recno"))
3216 return NULL;
3218 CHECK_CURSOR_NOT_CLOSED(self);
3220 CLEAR_DBT(key);
3221 CLEAR_DBT(data);
3222 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3223 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3224 data.flags = DB_DBT_MALLOC;
3225 key.flags = DB_DBT_MALLOC;
3228 MYDB_BEGIN_ALLOW_THREADS;
3229 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3230 MYDB_END_ALLOW_THREADS;
3231 RETURN_IF_ERR();
3233 recno = *((db_recno_t*)data.data);
3234 FREE_DBT(key);
3235 FREE_DBT(data);
3236 return PyInt_FromLong(recno);
3240 static PyObject*
3241 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3243 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3247 static PyObject*
3248 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3250 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3254 static PyObject*
3255 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3257 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3261 static PyObject*
3262 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3264 int err, flags = 0;
3265 PyObject* keyobj, *dataobj;
3266 DBT key, data;
3267 static const char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3268 NULL };
3269 int dlen = -1;
3270 int doff = -1;
3272 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3273 &keyobj, &dataobj, &flags, &dlen, &doff))
3274 return NULL;
3276 CHECK_CURSOR_NOT_CLOSED(self);
3278 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3279 return NULL;
3280 if (!make_dbt(dataobj, &data) ||
3281 !add_partial_dbt(&data, dlen, doff) )
3283 FREE_DBT(key);
3284 return NULL;
3287 MYDB_BEGIN_ALLOW_THREADS;
3288 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3289 MYDB_END_ALLOW_THREADS;
3290 FREE_DBT(key);
3291 RETURN_IF_ERR();
3292 self->mydb->haveStat = 0;
3293 RETURN_NONE();
3297 static PyObject*
3298 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3300 int err, flags = 0;
3301 DBT key, data;
3302 PyObject* retval, *keyobj;
3303 static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3304 int dlen = -1;
3305 int doff = -1;
3307 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3308 &keyobj, &flags, &dlen, &doff))
3309 return NULL;
3311 CHECK_CURSOR_NOT_CLOSED(self);
3313 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3314 return NULL;
3316 CLEAR_DBT(data);
3317 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3318 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3319 data.flags = DB_DBT_MALLOC;
3321 if (!add_partial_dbt(&data, dlen, doff)) {
3322 FREE_DBT(key);
3323 return NULL;
3326 MYDB_BEGIN_ALLOW_THREADS;
3327 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3328 MYDB_END_ALLOW_THREADS;
3329 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3330 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3331 Py_INCREF(Py_None);
3332 retval = Py_None;
3334 else if (makeDBError(err)) {
3335 retval = NULL;
3337 else {
3338 switch (_DB_get_type(self->mydb)) {
3339 case -1:
3340 retval = NULL;
3341 break;
3342 case DB_BTREE:
3343 case DB_HASH:
3344 default:
3345 retval = Py_BuildValue("s#s#", key.data, key.size,
3346 data.data, data.size);
3347 break;
3348 case DB_RECNO:
3349 case DB_QUEUE:
3350 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3351 data.data, data.size);
3352 break;
3354 FREE_DBT(data);
3355 FREE_DBT(key);
3357 /* the only time REALLOC should be set is if we used an integer
3358 * key that make_key_dbt malloc'd for us. always free these. */
3359 if (key.flags & DB_DBT_REALLOC) {
3360 FREE_DBT(key);
3363 return retval;
3367 static PyObject*
3368 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3370 int err, flags = 0;
3371 DBT key, data;
3372 PyObject* retval, *keyobj;
3373 static const char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3374 int dlen = -1;
3375 int doff = -1;
3377 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3378 &keyobj, &flags, &dlen, &doff))
3379 return NULL;
3381 CHECK_CURSOR_NOT_CLOSED(self);
3383 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3384 return NULL;
3386 CLEAR_DBT(data);
3387 if (!add_partial_dbt(&data, dlen, doff)) {
3388 FREE_DBT(key);
3389 return NULL;
3391 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3392 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3393 data.flags |= DB_DBT_MALLOC;
3394 /* only BTREE databases will return anything in the key */
3395 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3396 key.flags |= DB_DBT_MALLOC;
3399 MYDB_BEGIN_ALLOW_THREADS;
3400 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3401 MYDB_END_ALLOW_THREADS;
3402 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3403 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3404 Py_INCREF(Py_None);
3405 retval = Py_None;
3407 else if (makeDBError(err)) {
3408 retval = NULL;
3410 else {
3411 switch (_DB_get_type(self->mydb)) {
3412 case -1:
3413 retval = NULL;
3414 break;
3415 case DB_BTREE:
3416 case DB_HASH:
3417 default:
3418 retval = Py_BuildValue("s#s#", key.data, key.size,
3419 data.data, data.size);
3420 break;
3421 case DB_RECNO:
3422 case DB_QUEUE:
3423 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3424 data.data, data.size);
3425 break;
3427 FREE_DBT(key);
3428 FREE_DBT(data);
3430 /* the only time REALLOC should be set is if we used an integer
3431 * key that make_key_dbt malloc'd for us. always free these. */
3432 if (key.flags & DB_DBT_REALLOC) {
3433 FREE_DBT(key);
3436 return retval;
3439 static PyObject*
3440 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3441 int flags, unsigned int returnsNone)
3443 int err;
3444 DBT key, data;
3445 PyObject* retval;
3447 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3448 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3449 return NULL;
3450 if (!make_dbt(dataobj, &data)) {
3451 FREE_DBT(key);
3452 return NULL;
3455 MYDB_BEGIN_ALLOW_THREADS;
3456 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3457 MYDB_END_ALLOW_THREADS;
3458 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3459 Py_INCREF(Py_None);
3460 retval = Py_None;
3462 else if (makeDBError(err)) {
3463 retval = NULL;
3465 else {
3466 switch (_DB_get_type(self->mydb)) {
3467 case -1:
3468 retval = NULL;
3469 break;
3470 case DB_BTREE:
3471 case DB_HASH:
3472 default:
3473 retval = Py_BuildValue("s#s#", key.data, key.size,
3474 data.data, data.size);
3475 break;
3476 case DB_RECNO:
3477 case DB_QUEUE:
3478 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3479 data.data, data.size);
3480 break;
3484 FREE_DBT(key);
3485 return retval;
3488 static PyObject*
3489 DBC_get_both(DBCursorObject* self, PyObject* args)
3491 int flags=0;
3492 PyObject *keyobj, *dataobj;
3494 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3495 return NULL;
3497 /* if the cursor is closed, self->mydb may be invalid */
3498 CHECK_CURSOR_NOT_CLOSED(self);
3500 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3501 self->mydb->moduleFlags.getReturnsNone);
3504 /* Return size of entry */
3505 static PyObject*
3506 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3508 int err, flags=DB_CURRENT;
3509 PyObject* retval = NULL;
3510 DBT key, data;
3512 if (!PyArg_ParseTuple(args, ":get_current_size"))
3513 return NULL;
3514 CHECK_CURSOR_NOT_CLOSED(self);
3515 CLEAR_DBT(key);
3516 CLEAR_DBT(data);
3518 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3519 getting the record size. */
3520 data.flags = DB_DBT_USERMEM;
3521 data.ulen = 0;
3522 MYDB_BEGIN_ALLOW_THREADS;
3523 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3524 MYDB_END_ALLOW_THREADS;
3525 if (err == DB_BUFFER_SMALL || !err) {
3526 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3527 retval = PyInt_FromLong((long)data.size);
3528 err = 0;
3531 FREE_DBT(key);
3532 FREE_DBT(data);
3533 RETURN_IF_ERR();
3534 return retval;
3537 static PyObject*
3538 DBC_set_both(DBCursorObject* self, PyObject* args)
3540 int flags=0;
3541 PyObject *keyobj, *dataobj;
3543 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3544 return NULL;
3546 /* if the cursor is closed, self->mydb may be invalid */
3547 CHECK_CURSOR_NOT_CLOSED(self);
3549 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3550 self->mydb->moduleFlags.cursorSetReturnsNone);
3554 static PyObject*
3555 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3557 int err, irecno, flags=0;
3558 db_recno_t recno;
3559 DBT key, data;
3560 PyObject* retval;
3561 int dlen = -1;
3562 int doff = -1;
3563 static const char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3565 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3566 &irecno, &flags, &dlen, &doff))
3567 return NULL;
3569 CHECK_CURSOR_NOT_CLOSED(self);
3571 CLEAR_DBT(key);
3572 recno = (db_recno_t) irecno;
3573 /* use allocated space so DB will be able to realloc room for the real
3574 * key */
3575 key.data = malloc(sizeof(db_recno_t));
3576 if (key.data == NULL) {
3577 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3578 return NULL;
3580 key.size = sizeof(db_recno_t);
3581 key.ulen = key.size;
3582 memcpy(key.data, &recno, sizeof(db_recno_t));
3583 key.flags = DB_DBT_REALLOC;
3585 CLEAR_DBT(data);
3586 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3587 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3588 data.flags = DB_DBT_MALLOC;
3590 if (!add_partial_dbt(&data, dlen, doff)) {
3591 FREE_DBT(key);
3592 return NULL;
3595 MYDB_BEGIN_ALLOW_THREADS;
3596 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3597 MYDB_END_ALLOW_THREADS;
3598 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3599 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3600 Py_INCREF(Py_None);
3601 retval = Py_None;
3603 else if (makeDBError(err)) {
3604 retval = NULL;
3606 else { /* Can only be used for BTrees, so no need to return int key */
3607 retval = Py_BuildValue("s#s#", key.data, key.size,
3608 data.data, data.size);
3609 FREE_DBT(data);
3611 FREE_DBT(key);
3613 return retval;
3617 static PyObject*
3618 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3620 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3624 static PyObject*
3625 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3627 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3631 static PyObject*
3632 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3634 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3638 static PyObject*
3639 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3641 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3645 static PyObject*
3646 DBC_join_item(DBCursorObject* self, PyObject* args)
3648 int err, flags=0;
3649 DBT key, data;
3650 PyObject* retval;
3652 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3653 return NULL;
3655 CHECK_CURSOR_NOT_CLOSED(self);
3657 CLEAR_DBT(key);
3658 CLEAR_DBT(data);
3659 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3660 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3661 key.flags = DB_DBT_MALLOC;
3664 MYDB_BEGIN_ALLOW_THREADS;
3665 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3666 MYDB_END_ALLOW_THREADS;
3667 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3668 && self->mydb->moduleFlags.getReturnsNone) {
3669 Py_INCREF(Py_None);
3670 retval = Py_None;
3672 else if (makeDBError(err)) {
3673 retval = NULL;
3675 else {
3676 retval = Py_BuildValue("s#", key.data, key.size);
3677 FREE_DBT(key);
3680 return retval;
3685 /* --------------------------------------------------------------------- */
3686 /* DBEnv methods */
3689 static PyObject*
3690 DBEnv_close(DBEnvObject* self, PyObject* args)
3692 int err, flags = 0;
3694 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3695 return NULL;
3696 if (!self->closed) { /* Don't close more than once */
3697 MYDB_BEGIN_ALLOW_THREADS;
3698 err = self->db_env->close(self->db_env, flags);
3699 MYDB_END_ALLOW_THREADS;
3700 /* after calling DBEnv->close, regardless of error, this DBEnv
3701 * may not be accessed again (BerkeleyDB docs). */
3702 self->closed = 1;
3703 self->db_env = NULL;
3704 RETURN_IF_ERR();
3706 RETURN_NONE();
3710 static PyObject*
3711 DBEnv_open(DBEnvObject* self, PyObject* args)
3713 int err, flags=0, mode=0660;
3714 char *db_home;
3716 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3717 return NULL;
3719 CHECK_ENV_NOT_CLOSED(self);
3721 MYDB_BEGIN_ALLOW_THREADS;
3722 err = self->db_env->open(self->db_env, db_home, flags, mode);
3723 MYDB_END_ALLOW_THREADS;
3724 RETURN_IF_ERR();
3725 self->closed = 0;
3726 self->flags = flags;
3727 RETURN_NONE();
3731 static PyObject*
3732 DBEnv_remove(DBEnvObject* self, PyObject* args)
3734 int err, flags=0;
3735 char *db_home;
3737 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3738 return NULL;
3739 CHECK_ENV_NOT_CLOSED(self);
3740 MYDB_BEGIN_ALLOW_THREADS;
3741 err = self->db_env->remove(self->db_env, db_home, flags);
3742 MYDB_END_ALLOW_THREADS;
3743 RETURN_IF_ERR();
3744 RETURN_NONE();
3747 #if (DBVER >= 41)
3748 static PyObject*
3749 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3751 int err;
3752 u_int32_t flags=0;
3753 char *file = NULL;
3754 char *database = NULL;
3755 PyObject *txnobj = NULL;
3756 DB_TXN *txn = NULL;
3757 static const char* kwnames[] = { "file", "database", "txn", "flags",
3758 NULL };
3760 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3761 &file, &database, &txnobj, &flags)) {
3762 return NULL;
3764 if (!checkTxnObj(txnobj, &txn)) {
3765 return NULL;
3767 CHECK_ENV_NOT_CLOSED(self);
3768 MYDB_BEGIN_ALLOW_THREADS;
3769 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3770 MYDB_END_ALLOW_THREADS;
3771 RETURN_IF_ERR();
3772 RETURN_NONE();
3775 static PyObject*
3776 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3778 int err;
3779 u_int32_t flags=0;
3780 char *file = NULL;
3781 char *database = NULL;
3782 char *newname = NULL;
3783 PyObject *txnobj = NULL;
3784 DB_TXN *txn = NULL;
3785 static const char* kwnames[] = { "file", "database", "newname", "txn",
3786 "flags", NULL };
3788 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3789 &file, &database, &newname, &txnobj, &flags)) {
3790 return NULL;
3792 if (!checkTxnObj(txnobj, &txn)) {
3793 return NULL;
3795 CHECK_ENV_NOT_CLOSED(self);
3796 MYDB_BEGIN_ALLOW_THREADS;
3797 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3798 flags);
3799 MYDB_END_ALLOW_THREADS;
3800 RETURN_IF_ERR();
3801 RETURN_NONE();
3804 static PyObject*
3805 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3807 int err;
3808 u_int32_t flags=0;
3809 char *passwd = NULL;
3810 static const char* kwnames[] = { "passwd", "flags", NULL };
3812 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3813 &passwd, &flags)) {
3814 return NULL;
3817 MYDB_BEGIN_ALLOW_THREADS;
3818 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3819 MYDB_END_ALLOW_THREADS;
3821 RETURN_IF_ERR();
3822 RETURN_NONE();
3824 #endif /* DBVER >= 41 */
3826 #if (DBVER >= 40)
3827 static PyObject*
3828 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3830 int err;
3831 u_int32_t flags=0;
3832 u_int32_t timeout = 0;
3833 static const char* kwnames[] = { "timeout", "flags", NULL };
3835 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3836 &timeout, &flags)) {
3837 return NULL;
3840 MYDB_BEGIN_ALLOW_THREADS;
3841 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3842 MYDB_END_ALLOW_THREADS;
3844 RETURN_IF_ERR();
3845 RETURN_NONE();
3847 #endif /* DBVER >= 40 */
3849 static PyObject*
3850 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3852 int err;
3853 long shm_key = 0;
3855 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3856 return NULL;
3857 CHECK_ENV_NOT_CLOSED(self);
3859 err = self->db_env->set_shm_key(self->db_env, shm_key);
3860 RETURN_IF_ERR();
3861 RETURN_NONE();
3864 static PyObject*
3865 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3867 int err, gbytes=0, bytes=0, ncache=0;
3869 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3870 &gbytes, &bytes, &ncache))
3871 return NULL;
3872 CHECK_ENV_NOT_CLOSED(self);
3874 MYDB_BEGIN_ALLOW_THREADS;
3875 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3876 MYDB_END_ALLOW_THREADS;
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3882 #if (DBVER >= 32)
3883 static PyObject*
3884 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3886 int err, flags=0, onoff=0;
3888 if (!PyArg_ParseTuple(args, "ii:set_flags",
3889 &flags, &onoff))
3890 return NULL;
3891 CHECK_ENV_NOT_CLOSED(self);
3893 MYDB_BEGIN_ALLOW_THREADS;
3894 err = self->db_env->set_flags(self->db_env, flags, onoff);
3895 MYDB_END_ALLOW_THREADS;
3896 RETURN_IF_ERR();
3897 RETURN_NONE();
3899 #endif
3902 static PyObject*
3903 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3905 int err;
3906 char *dir;
3908 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3909 return NULL;
3910 CHECK_ENV_NOT_CLOSED(self);
3912 MYDB_BEGIN_ALLOW_THREADS;
3913 err = self->db_env->set_data_dir(self->db_env, dir);
3914 MYDB_END_ALLOW_THREADS;
3915 RETURN_IF_ERR();
3916 RETURN_NONE();
3920 static PyObject*
3921 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3923 int err, lg_bsize;
3925 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3926 return NULL;
3927 CHECK_ENV_NOT_CLOSED(self);
3929 MYDB_BEGIN_ALLOW_THREADS;
3930 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3931 MYDB_END_ALLOW_THREADS;
3932 RETURN_IF_ERR();
3933 RETURN_NONE();
3937 static PyObject*
3938 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3940 int err;
3941 char *dir;
3943 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3944 return NULL;
3945 CHECK_ENV_NOT_CLOSED(self);
3947 MYDB_BEGIN_ALLOW_THREADS;
3948 err = self->db_env->set_lg_dir(self->db_env, dir);
3949 MYDB_END_ALLOW_THREADS;
3950 RETURN_IF_ERR();
3951 RETURN_NONE();
3954 static PyObject*
3955 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3957 int err, lg_max;
3959 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3960 return NULL;
3961 CHECK_ENV_NOT_CLOSED(self);
3963 MYDB_BEGIN_ALLOW_THREADS;
3964 err = self->db_env->set_lg_max(self->db_env, lg_max);
3965 MYDB_END_ALLOW_THREADS;
3966 RETURN_IF_ERR();
3967 RETURN_NONE();
3971 #if (DBVER >= 33)
3972 static PyObject*
3973 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3975 int err, lg_max;
3977 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3978 return NULL;
3979 CHECK_ENV_NOT_CLOSED(self);
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3983 MYDB_END_ALLOW_THREADS;
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3987 #endif
3990 static PyObject*
3991 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3993 int err, lk_detect;
3995 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3996 return NULL;
3997 CHECK_ENV_NOT_CLOSED(self);
3999 MYDB_BEGIN_ALLOW_THREADS;
4000 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4001 MYDB_END_ALLOW_THREADS;
4002 RETURN_IF_ERR();
4003 RETURN_NONE();
4007 static PyObject*
4008 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4010 int err, max;
4012 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_lk_max(self->db_env, max);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4024 #if (DBVER >= 32)
4026 static PyObject*
4027 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4029 int err, max;
4031 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_lk_max_locks(self->db_env, max);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4043 static PyObject*
4044 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4046 int err, max;
4048 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4049 return NULL;
4050 CHECK_ENV_NOT_CLOSED(self);
4052 MYDB_BEGIN_ALLOW_THREADS;
4053 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4054 MYDB_END_ALLOW_THREADS;
4055 RETURN_IF_ERR();
4056 RETURN_NONE();
4060 static PyObject*
4061 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4063 int err, max;
4065 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4066 return NULL;
4067 CHECK_ENV_NOT_CLOSED(self);
4069 MYDB_BEGIN_ALLOW_THREADS;
4070 err = self->db_env->set_lk_max_objects(self->db_env, max);
4071 MYDB_END_ALLOW_THREADS;
4072 RETURN_IF_ERR();
4073 RETURN_NONE();
4076 #endif
4079 static PyObject*
4080 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4082 int err, mp_mmapsize;
4084 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4096 static PyObject*
4097 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4099 int err;
4100 char *dir;
4102 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_tmp_dir(self->db_env, dir);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4114 static PyObject*
4115 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4117 int flags = 0;
4118 PyObject* txnobj = NULL;
4119 DB_TXN *txn = NULL;
4120 static const char* kwnames[] = { "parent", "flags", NULL };
4122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4123 &txnobj, &flags))
4124 return NULL;
4126 if (!checkTxnObj(txnobj, &txn))
4127 return NULL;
4128 CHECK_ENV_NOT_CLOSED(self);
4130 return (PyObject*)newDBTxnObject(self, txn, flags);
4134 static PyObject*
4135 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4137 int err, kbyte=0, min=0, flags=0;
4139 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4140 return NULL;
4141 CHECK_ENV_NOT_CLOSED(self);
4143 MYDB_BEGIN_ALLOW_THREADS;
4144 #if (DBVER >= 40)
4145 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4146 #else
4147 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4148 #endif
4149 MYDB_END_ALLOW_THREADS;
4150 RETURN_IF_ERR();
4151 RETURN_NONE();
4155 static PyObject*
4156 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4158 int err, max;
4160 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4161 return NULL;
4162 CHECK_ENV_NOT_CLOSED(self);
4164 MYDB_BEGIN_ALLOW_THREADS;
4165 err = self->db_env->set_tx_max(self->db_env, max);
4166 MYDB_END_ALLOW_THREADS;
4167 RETURN_IF_ERR();
4168 RETURN_NONE();
4172 static PyObject*
4173 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4175 int err, atype, flags=0;
4176 int aborted = 0;
4178 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4179 return NULL;
4180 CHECK_ENV_NOT_CLOSED(self);
4182 MYDB_BEGIN_ALLOW_THREADS;
4183 #if (DBVER >= 40)
4184 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4185 #else
4186 err = lock_detect(self->db_env, flags, atype, &aborted);
4187 #endif
4188 MYDB_END_ALLOW_THREADS;
4189 RETURN_IF_ERR();
4190 return PyInt_FromLong(aborted);
4194 static PyObject*
4195 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4197 int flags=0;
4198 int locker, lock_mode;
4199 DBT obj;
4200 PyObject* objobj;
4202 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4203 return NULL;
4206 if (!make_dbt(objobj, &obj))
4207 return NULL;
4209 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4213 static PyObject*
4214 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4216 int err;
4217 u_int32_t theID;
4219 if (!PyArg_ParseTuple(args, ":lock_id"))
4220 return NULL;
4222 CHECK_ENV_NOT_CLOSED(self);
4223 MYDB_BEGIN_ALLOW_THREADS;
4224 #if (DBVER >= 40)
4225 err = self->db_env->lock_id(self->db_env, &theID);
4226 #else
4227 err = lock_id(self->db_env, &theID);
4228 #endif
4229 MYDB_END_ALLOW_THREADS;
4230 RETURN_IF_ERR();
4232 return PyInt_FromLong((long)theID);
4236 static PyObject*
4237 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4239 int err;
4240 DBLockObject* dblockobj;
4242 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4243 return NULL;
4245 CHECK_ENV_NOT_CLOSED(self);
4246 MYDB_BEGIN_ALLOW_THREADS;
4247 #if (DBVER >= 40)
4248 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4249 #else
4250 err = lock_put(self->db_env, &dblockobj->lock);
4251 #endif
4252 MYDB_END_ALLOW_THREADS;
4253 RETURN_IF_ERR();
4254 RETURN_NONE();
4258 static PyObject*
4259 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4261 int err;
4262 DB_LOCK_STAT* sp;
4263 PyObject* d = NULL;
4264 u_int32_t flags = 0;
4266 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4267 return NULL;
4268 CHECK_ENV_NOT_CLOSED(self);
4270 MYDB_BEGIN_ALLOW_THREADS;
4271 #if (DBVER >= 40)
4272 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4273 #else
4274 #if (DBVER >= 33)
4275 err = lock_stat(self->db_env, &sp);
4276 #else
4277 err = lock_stat(self->db_env, &sp, NULL);
4278 #endif
4279 #endif
4280 MYDB_END_ALLOW_THREADS;
4281 RETURN_IF_ERR();
4283 /* Turn the stat structure into a dictionary */
4284 d = PyDict_New();
4285 if (d == NULL) {
4286 free(sp);
4287 return NULL;
4290 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4292 #if (DBVER < 41)
4293 MAKE_ENTRY(lastid);
4294 #endif
4295 MAKE_ENTRY(nmodes);
4296 #if (DBVER >= 32)
4297 MAKE_ENTRY(maxlocks);
4298 MAKE_ENTRY(maxlockers);
4299 MAKE_ENTRY(maxobjects);
4300 MAKE_ENTRY(nlocks);
4301 MAKE_ENTRY(maxnlocks);
4302 #endif
4303 MAKE_ENTRY(nlockers);
4304 MAKE_ENTRY(maxnlockers);
4305 #if (DBVER >= 32)
4306 MAKE_ENTRY(nobjects);
4307 MAKE_ENTRY(maxnobjects);
4308 #endif
4309 MAKE_ENTRY(nrequests);
4310 MAKE_ENTRY(nreleases);
4311 MAKE_ENTRY(nnowaits);
4312 MAKE_ENTRY(nconflicts);
4313 MAKE_ENTRY(ndeadlocks);
4314 MAKE_ENTRY(regsize);
4315 MAKE_ENTRY(region_wait);
4316 MAKE_ENTRY(region_nowait);
4318 #undef MAKE_ENTRY
4319 free(sp);
4320 return d;
4324 static PyObject*
4325 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4327 int flags=0;
4328 int err;
4329 char **log_list_start, **log_list;
4330 PyObject* list;
4331 PyObject* item = NULL;
4333 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4334 return NULL;
4336 CHECK_ENV_NOT_CLOSED(self);
4337 MYDB_BEGIN_ALLOW_THREADS;
4338 #if (DBVER >= 40)
4339 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4340 #elif (DBVER == 33)
4341 err = log_archive(self->db_env, &log_list, flags);
4342 #else
4343 err = log_archive(self->db_env, &log_list, flags, NULL);
4344 #endif
4345 MYDB_END_ALLOW_THREADS;
4346 RETURN_IF_ERR();
4348 list = PyList_New(0);
4349 if (list == NULL) {
4350 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4351 return NULL;
4354 if (log_list) {
4355 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4356 item = PyString_FromString (*log_list);
4357 if (item == NULL) {
4358 Py_DECREF(list);
4359 PyErr_SetString(PyExc_MemoryError,
4360 "List item creation failed");
4361 list = NULL;
4362 break;
4364 PyList_Append(list, item);
4365 Py_DECREF(item);
4367 free(log_list_start);
4369 return list;
4373 static PyObject*
4374 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4376 int err;
4377 DB_TXN_STAT* sp;
4378 PyObject* d = NULL;
4379 u_int32_t flags=0;
4381 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4382 return NULL;
4383 CHECK_ENV_NOT_CLOSED(self);
4385 MYDB_BEGIN_ALLOW_THREADS;
4386 #if (DBVER >= 40)
4387 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4388 #elif (DBVER == 33)
4389 err = txn_stat(self->db_env, &sp);
4390 #else
4391 err = txn_stat(self->db_env, &sp, NULL);
4392 #endif
4393 MYDB_END_ALLOW_THREADS;
4394 RETURN_IF_ERR();
4396 /* Turn the stat structure into a dictionary */
4397 d = PyDict_New();
4398 if (d == NULL) {
4399 free(sp);
4400 return NULL;
4403 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4405 MAKE_ENTRY(time_ckp);
4406 MAKE_ENTRY(last_txnid);
4407 MAKE_ENTRY(maxtxns);
4408 MAKE_ENTRY(nactive);
4409 MAKE_ENTRY(maxnactive);
4410 MAKE_ENTRY(nbegins);
4411 MAKE_ENTRY(naborts);
4412 MAKE_ENTRY(ncommits);
4413 MAKE_ENTRY(regsize);
4414 MAKE_ENTRY(region_wait);
4415 MAKE_ENTRY(region_nowait);
4417 #undef MAKE_ENTRY
4418 free(sp);
4419 return d;
4423 static PyObject*
4424 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4426 int flags=0;
4427 int oldValue=0;
4429 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4430 return NULL;
4431 CHECK_ENV_NOT_CLOSED(self);
4433 if (self->moduleFlags.getReturnsNone)
4434 ++oldValue;
4435 if (self->moduleFlags.cursorSetReturnsNone)
4436 ++oldValue;
4437 self->moduleFlags.getReturnsNone = (flags >= 1);
4438 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4439 return PyInt_FromLong(oldValue);
4443 /* --------------------------------------------------------------------- */
4444 /* DBTxn methods */
4447 static PyObject*
4448 DBTxn_commit(DBTxnObject* self, PyObject* args)
4450 int flags=0, err;
4451 DB_TXN *txn;
4453 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4454 return NULL;
4456 if (!self->txn) {
4457 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4458 "DBTxn must not be used after txn_commit or txn_abort"));
4459 return NULL;
4461 txn = self->txn;
4462 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4463 MYDB_BEGIN_ALLOW_THREADS;
4464 #if (DBVER >= 40)
4465 err = txn->commit(txn, flags);
4466 #else
4467 err = txn_commit(txn, flags);
4468 #endif
4469 MYDB_END_ALLOW_THREADS;
4470 RETURN_IF_ERR();
4471 RETURN_NONE();
4474 static PyObject*
4475 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4477 #if (DBVER >= 33)
4478 int err;
4479 char* gid=NULL;
4480 int gid_size=0;
4482 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4483 return NULL;
4485 if (gid_size != DB_XIDDATASIZE) {
4486 PyErr_SetString(PyExc_TypeError,
4487 "gid must be DB_XIDDATASIZE bytes long");
4488 return NULL;
4491 if (!self->txn) {
4492 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4493 "DBTxn must not be used after txn_commit or txn_abort"));
4494 return NULL;
4496 MYDB_BEGIN_ALLOW_THREADS;
4497 #if (DBVER >= 40)
4498 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4499 #else
4500 err = txn_prepare(self->txn, (u_int8_t*)gid);
4501 #endif
4502 MYDB_END_ALLOW_THREADS;
4503 RETURN_IF_ERR();
4504 RETURN_NONE();
4505 #else
4506 int err;
4508 if (!PyArg_ParseTuple(args, ":prepare"))
4509 return NULL;
4511 if (!self->txn) {
4512 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4513 "DBTxn must not be used after txn_commit or txn_abort"));
4514 return NULL;
4516 MYDB_BEGIN_ALLOW_THREADS;
4517 err = txn_prepare(self->txn);
4518 MYDB_END_ALLOW_THREADS;
4519 RETURN_IF_ERR();
4520 RETURN_NONE();
4521 #endif
4525 static PyObject*
4526 DBTxn_abort(DBTxnObject* self, PyObject* args)
4528 int err;
4529 DB_TXN *txn;
4531 if (!PyArg_ParseTuple(args, ":abort"))
4532 return NULL;
4534 if (!self->txn) {
4535 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4536 "DBTxn must not be used after txn_commit or txn_abort"));
4537 return NULL;
4539 txn = self->txn;
4540 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4541 MYDB_BEGIN_ALLOW_THREADS;
4542 #if (DBVER >= 40)
4543 err = txn->abort(txn);
4544 #else
4545 err = txn_abort(txn);
4546 #endif
4547 MYDB_END_ALLOW_THREADS;
4548 RETURN_IF_ERR();
4549 RETURN_NONE();
4553 static PyObject*
4554 DBTxn_id(DBTxnObject* self, PyObject* args)
4556 int id;
4558 if (!PyArg_ParseTuple(args, ":id"))
4559 return NULL;
4561 if (!self->txn) {
4562 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4563 "DBTxn must not be used after txn_commit or txn_abort"));
4564 return NULL;
4566 MYDB_BEGIN_ALLOW_THREADS;
4567 #if (DBVER >= 40)
4568 id = self->txn->id(self->txn);
4569 #else
4570 id = txn_id(self->txn);
4571 #endif
4572 MYDB_END_ALLOW_THREADS;
4573 return PyInt_FromLong(id);
4576 /* --------------------------------------------------------------------- */
4577 /* Method definition tables and type objects */
4579 static PyMethodDef DB_methods[] = {
4580 {"append", (PyCFunction)DB_append, METH_VARARGS},
4581 #if (DBVER >= 33)
4582 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4583 #endif
4584 {"close", (PyCFunction)DB_close, METH_VARARGS},
4585 #if (DBVER >= 32)
4586 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4587 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4588 #endif
4589 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4590 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4591 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4592 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4593 #if (DBVER >= 33)
4594 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
4595 #endif
4596 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4597 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4598 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4599 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4600 {"join", (PyCFunction)DB_join, METH_VARARGS},
4601 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4602 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4603 {"items", (PyCFunction)DB_items, METH_VARARGS},
4604 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4605 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4606 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4607 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4608 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4609 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4610 #if (DBVER >= 33)
4611 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
4612 #endif
4613 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
4614 #if (DBVER >= 41)
4615 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4616 #endif
4617 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4618 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4619 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4620 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4621 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4622 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4623 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4624 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4625 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4626 #if (DBVER >= 32)
4627 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4628 #endif
4629 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
4630 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4631 #if (DBVER >= 33)
4632 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4633 #endif
4634 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4635 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4636 {"values", (PyCFunction)DB_values, METH_VARARGS},
4637 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4638 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4639 {NULL, NULL} /* sentinel */
4643 static PyMappingMethods DB_mapping = {
4644 (inquiry)DB_length, /*mp_length*/
4645 (binaryfunc)DB_subscript, /*mp_subscript*/
4646 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4650 static PyMethodDef DBCursor_methods[] = {
4651 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4652 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4653 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4654 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4655 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4656 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4657 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4658 #if (DBVER >= 33)
4659 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
4660 #endif
4661 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4662 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4663 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4664 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4665 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4666 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4667 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4668 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
4669 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
4670 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
4671 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4672 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4673 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4674 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4675 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4676 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4677 {NULL, NULL} /* sentinel */
4681 static PyMethodDef DBEnv_methods[] = {
4682 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4683 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4684 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
4685 #if (DBVER >= 41)
4686 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4687 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4688 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4689 #endif
4690 #if (DBVER >= 40)
4691 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4692 #endif
4693 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
4694 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4695 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4696 #if (DBVER >= 32)
4697 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4698 #endif
4699 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4700 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4701 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4702 #if (DBVER >= 33)
4703 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
4704 #endif
4705 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4706 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4707 #if (DBVER >= 32)
4708 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4709 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4710 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4711 #endif
4712 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4713 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4714 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4715 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4716 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4717 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4718 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4719 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4720 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4721 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4722 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4723 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4724 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4725 {NULL, NULL} /* sentinel */
4729 static PyMethodDef DBTxn_methods[] = {
4730 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4731 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4732 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4733 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4734 {NULL, NULL} /* sentinel */
4738 static PyObject*
4739 DB_getattr(DBObject* self, char *name)
4741 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4745 static PyObject*
4746 DBEnv_getattr(DBEnvObject* self, char *name)
4748 if (!strcmp(name, "db_home")) {
4749 CHECK_ENV_NOT_CLOSED(self);
4750 if (self->db_env->db_home == NULL) {
4751 RETURN_NONE();
4753 return PyString_FromString(self->db_env->db_home);
4756 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4760 static PyObject*
4761 DBCursor_getattr(DBCursorObject* self, char *name)
4763 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4766 static PyObject*
4767 DBTxn_getattr(DBTxnObject* self, char *name)
4769 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4772 static PyObject*
4773 DBLock_getattr(DBLockObject* self, char *name)
4775 return NULL;
4778 statichere PyTypeObject DB_Type = {
4779 PyObject_HEAD_INIT(NULL)
4780 0, /*ob_size*/
4781 "DB", /*tp_name*/
4782 sizeof(DBObject), /*tp_basicsize*/
4783 0, /*tp_itemsize*/
4784 /* methods */
4785 (destructor)DB_dealloc, /*tp_dealloc*/
4786 0, /*tp_print*/
4787 (getattrfunc)DB_getattr, /*tp_getattr*/
4788 0, /*tp_setattr*/
4789 0, /*tp_compare*/
4790 0, /*tp_repr*/
4791 0, /*tp_as_number*/
4792 0, /*tp_as_sequence*/
4793 &DB_mapping,/*tp_as_mapping*/
4794 0, /*tp_hash*/
4795 #ifdef HAVE_WEAKREF
4796 0, /* tp_call */
4797 0, /* tp_str */
4798 0, /* tp_getattro */
4799 0, /* tp_setattro */
4800 0, /* tp_as_buffer */
4801 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4802 0, /* tp_doc */
4803 0, /* tp_traverse */
4804 0, /* tp_clear */
4805 0, /* tp_richcompare */
4806 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4807 #endif
4811 statichere PyTypeObject DBCursor_Type = {
4812 PyObject_HEAD_INIT(NULL)
4813 0, /*ob_size*/
4814 "DBCursor", /*tp_name*/
4815 sizeof(DBCursorObject), /*tp_basicsize*/
4816 0, /*tp_itemsize*/
4817 /* methods */
4818 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4819 0, /*tp_print*/
4820 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4821 0, /*tp_setattr*/
4822 0, /*tp_compare*/
4823 0, /*tp_repr*/
4824 0, /*tp_as_number*/
4825 0, /*tp_as_sequence*/
4826 0, /*tp_as_mapping*/
4827 0, /*tp_hash*/
4828 #ifdef HAVE_WEAKREF
4829 0, /* tp_call */
4830 0, /* tp_str */
4831 0, /* tp_getattro */
4832 0, /* tp_setattro */
4833 0, /* tp_as_buffer */
4834 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4835 0, /* tp_doc */
4836 0, /* tp_traverse */
4837 0, /* tp_clear */
4838 0, /* tp_richcompare */
4839 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4840 #endif
4844 statichere PyTypeObject DBEnv_Type = {
4845 PyObject_HEAD_INIT(NULL)
4846 0, /*ob_size*/
4847 "DBEnv", /*tp_name*/
4848 sizeof(DBEnvObject), /*tp_basicsize*/
4849 0, /*tp_itemsize*/
4850 /* methods */
4851 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4852 0, /*tp_print*/
4853 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4854 0, /*tp_setattr*/
4855 0, /*tp_compare*/
4856 0, /*tp_repr*/
4857 0, /*tp_as_number*/
4858 0, /*tp_as_sequence*/
4859 0, /*tp_as_mapping*/
4860 0, /*tp_hash*/
4861 #ifdef HAVE_WEAKREF
4862 0, /* tp_call */
4863 0, /* tp_str */
4864 0, /* tp_getattro */
4865 0, /* tp_setattro */
4866 0, /* tp_as_buffer */
4867 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4868 0, /* tp_doc */
4869 0, /* tp_traverse */
4870 0, /* tp_clear */
4871 0, /* tp_richcompare */
4872 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4873 #endif
4876 statichere PyTypeObject DBTxn_Type = {
4877 PyObject_HEAD_INIT(NULL)
4878 0, /*ob_size*/
4879 "DBTxn", /*tp_name*/
4880 sizeof(DBTxnObject), /*tp_basicsize*/
4881 0, /*tp_itemsize*/
4882 /* methods */
4883 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4884 0, /*tp_print*/
4885 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4886 0, /*tp_setattr*/
4887 0, /*tp_compare*/
4888 0, /*tp_repr*/
4889 0, /*tp_as_number*/
4890 0, /*tp_as_sequence*/
4891 0, /*tp_as_mapping*/
4892 0, /*tp_hash*/
4893 #ifdef HAVE_WEAKREF
4894 0, /* tp_call */
4895 0, /* tp_str */
4896 0, /* tp_getattro */
4897 0, /* tp_setattro */
4898 0, /* tp_as_buffer */
4899 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4900 0, /* tp_doc */
4901 0, /* tp_traverse */
4902 0, /* tp_clear */
4903 0, /* tp_richcompare */
4904 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4905 #endif
4909 statichere PyTypeObject DBLock_Type = {
4910 PyObject_HEAD_INIT(NULL)
4911 0, /*ob_size*/
4912 "DBLock", /*tp_name*/
4913 sizeof(DBLockObject), /*tp_basicsize*/
4914 0, /*tp_itemsize*/
4915 /* methods */
4916 (destructor)DBLock_dealloc, /*tp_dealloc*/
4917 0, /*tp_print*/
4918 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4919 0, /*tp_setattr*/
4920 0, /*tp_compare*/
4921 0, /*tp_repr*/
4922 0, /*tp_as_number*/
4923 0, /*tp_as_sequence*/
4924 0, /*tp_as_mapping*/
4925 0, /*tp_hash*/
4926 #ifdef HAVE_WEAKREF
4927 0, /* tp_call */
4928 0, /* tp_str */
4929 0, /* tp_getattro */
4930 0, /* tp_setattro */
4931 0, /* tp_as_buffer */
4932 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4933 0, /* tp_doc */
4934 0, /* tp_traverse */
4935 0, /* tp_clear */
4936 0, /* tp_richcompare */
4937 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4938 #endif
4942 /* --------------------------------------------------------------------- */
4943 /* Module-level functions */
4945 static PyObject*
4946 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4948 PyObject* dbenvobj = NULL;
4949 int flags = 0;
4950 static const char* kwnames[] = { "dbEnv", "flags", NULL};
4952 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4953 &dbenvobj, &flags))
4954 return NULL;
4955 if (dbenvobj == Py_None)
4956 dbenvobj = NULL;
4957 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4958 makeTypeError("DBEnv", dbenvobj);
4959 return NULL;
4962 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4966 static PyObject*
4967 DBEnv_construct(PyObject* self, PyObject* args)
4969 int flags = 0;
4970 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4971 return (PyObject* )newDBEnvObject(flags);
4975 static char bsddb_version_doc[] =
4976 "Returns a tuple of major, minor, and patch release numbers of the\n\
4977 underlying DB library.";
4979 static PyObject*
4980 bsddb_version(PyObject* self, PyObject* args)
4982 int major, minor, patch;
4984 if (!PyArg_ParseTuple(args, ":version"))
4985 return NULL;
4986 db_version(&major, &minor, &patch);
4987 return Py_BuildValue("(iii)", major, minor, patch);
4991 /* List of functions defined in the module */
4993 static PyMethodDef bsddb_methods[] = {
4994 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4995 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4996 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4997 {NULL, NULL} /* sentinel */
5001 /* --------------------------------------------------------------------- */
5002 /* Module initialization */
5005 /* Convenience routine to export an integer value.
5006 * Errors are silently ignored, for better or for worse...
5008 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5010 #define MODULE_NAME_MAX_LEN 11
5011 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5013 DL_EXPORT(void) init_bsddb(void)
5015 PyObject* m;
5016 PyObject* d;
5017 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5018 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5019 PyObject* cvsid_s = PyString_FromString( rcs_id );
5021 /* Initialize the type of the new type objects here; doing it here
5022 is required for portability to Windows without requiring C++. */
5023 DB_Type.ob_type = &PyType_Type;
5024 DBCursor_Type.ob_type = &PyType_Type;
5025 DBEnv_Type.ob_type = &PyType_Type;
5026 DBTxn_Type.ob_type = &PyType_Type;
5027 DBLock_Type.ob_type = &PyType_Type;
5030 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5031 /* Save the current interpreter, so callbacks can do the right thing. */
5032 _db_interpreterState = PyThreadState_GET()->interp;
5033 #endif
5035 /* Create the module and add the functions */
5036 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5038 /* Add some symbolic constants to the module */
5039 d = PyModule_GetDict(m);
5040 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5041 PyDict_SetItemString(d, "cvsid", cvsid_s);
5042 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5043 Py_DECREF(pybsddb_version_s);
5044 pybsddb_version_s = NULL;
5045 Py_DECREF(cvsid_s);
5046 cvsid_s = NULL;
5047 Py_DECREF(db_version_s);
5048 db_version_s = NULL;
5050 ADD_INT(d, DB_VERSION_MAJOR);
5051 ADD_INT(d, DB_VERSION_MINOR);
5052 ADD_INT(d, DB_VERSION_PATCH);
5054 ADD_INT(d, DB_MAX_PAGES);
5055 ADD_INT(d, DB_MAX_RECORDS);
5057 #if (DBVER >= 42)
5058 ADD_INT(d, DB_RPCCLIENT);
5059 #else
5060 ADD_INT(d, DB_CLIENT);
5061 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5062 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5063 #endif
5064 ADD_INT(d, DB_XA_CREATE);
5066 ADD_INT(d, DB_CREATE);
5067 ADD_INT(d, DB_NOMMAP);
5068 ADD_INT(d, DB_THREAD);
5070 ADD_INT(d, DB_FORCE);
5071 ADD_INT(d, DB_INIT_CDB);
5072 ADD_INT(d, DB_INIT_LOCK);
5073 ADD_INT(d, DB_INIT_LOG);
5074 ADD_INT(d, DB_INIT_MPOOL);
5075 ADD_INT(d, DB_INIT_TXN);
5076 #if (DBVER >= 32)
5077 ADD_INT(d, DB_JOINENV);
5078 #endif
5080 ADD_INT(d, DB_RECOVER);
5081 ADD_INT(d, DB_RECOVER_FATAL);
5082 ADD_INT(d, DB_TXN_NOSYNC);
5083 ADD_INT(d, DB_USE_ENVIRON);
5084 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5086 ADD_INT(d, DB_LOCKDOWN);
5087 ADD_INT(d, DB_PRIVATE);
5088 ADD_INT(d, DB_SYSTEM_MEM);
5090 ADD_INT(d, DB_TXN_SYNC);
5091 ADD_INT(d, DB_TXN_NOWAIT);
5093 ADD_INT(d, DB_EXCL);
5094 ADD_INT(d, DB_FCNTL_LOCKING);
5095 ADD_INT(d, DB_ODDFILESIZE);
5096 ADD_INT(d, DB_RDWRMASTER);
5097 ADD_INT(d, DB_RDONLY);
5098 ADD_INT(d, DB_TRUNCATE);
5099 #if (DBVER >= 32)
5100 ADD_INT(d, DB_EXTENT);
5101 ADD_INT(d, DB_CDB_ALLDB);
5102 ADD_INT(d, DB_VERIFY);
5103 #endif
5104 ADD_INT(d, DB_UPGRADE);
5106 ADD_INT(d, DB_AGGRESSIVE);
5107 ADD_INT(d, DB_NOORDERCHK);
5108 ADD_INT(d, DB_ORDERCHKONLY);
5109 ADD_INT(d, DB_PR_PAGE);
5110 #if ! (DBVER >= 33)
5111 ADD_INT(d, DB_VRFY_FLAGMASK);
5112 ADD_INT(d, DB_PR_HEADERS);
5113 #endif
5114 ADD_INT(d, DB_PR_RECOVERYTEST);
5115 ADD_INT(d, DB_SALVAGE);
5117 ADD_INT(d, DB_LOCK_NORUN);
5118 ADD_INT(d, DB_LOCK_DEFAULT);
5119 ADD_INT(d, DB_LOCK_OLDEST);
5120 ADD_INT(d, DB_LOCK_RANDOM);
5121 ADD_INT(d, DB_LOCK_YOUNGEST);
5122 #if (DBVER >= 33)
5123 ADD_INT(d, DB_LOCK_MAXLOCKS);
5124 ADD_INT(d, DB_LOCK_MINLOCKS);
5125 ADD_INT(d, DB_LOCK_MINWRITE);
5126 #endif
5129 #if (DBVER >= 33)
5130 /* docs say to use zero instead */
5131 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5132 #else
5133 ADD_INT(d, DB_LOCK_CONFLICT);
5134 #endif
5136 ADD_INT(d, DB_LOCK_DUMP);
5137 ADD_INT(d, DB_LOCK_GET);
5138 ADD_INT(d, DB_LOCK_INHERIT);
5139 ADD_INT(d, DB_LOCK_PUT);
5140 ADD_INT(d, DB_LOCK_PUT_ALL);
5141 ADD_INT(d, DB_LOCK_PUT_OBJ);
5143 ADD_INT(d, DB_LOCK_NG);
5144 ADD_INT(d, DB_LOCK_READ);
5145 ADD_INT(d, DB_LOCK_WRITE);
5146 ADD_INT(d, DB_LOCK_NOWAIT);
5147 #if (DBVER >= 32)
5148 ADD_INT(d, DB_LOCK_WAIT);
5149 #endif
5150 ADD_INT(d, DB_LOCK_IWRITE);
5151 ADD_INT(d, DB_LOCK_IREAD);
5152 ADD_INT(d, DB_LOCK_IWR);
5153 #if (DBVER >= 33)
5154 ADD_INT(d, DB_LOCK_DIRTY);
5155 ADD_INT(d, DB_LOCK_WWRITE);
5156 #endif
5158 ADD_INT(d, DB_LOCK_RECORD);
5159 ADD_INT(d, DB_LOCK_UPGRADE);
5160 #if (DBVER >= 32)
5161 ADD_INT(d, DB_LOCK_SWITCH);
5162 #endif
5163 #if (DBVER >= 33)
5164 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5165 #endif
5167 ADD_INT(d, DB_LOCK_NOWAIT);
5168 ADD_INT(d, DB_LOCK_RECORD);
5169 ADD_INT(d, DB_LOCK_UPGRADE);
5171 #if (DBVER >= 33)
5172 ADD_INT(d, DB_LSTAT_ABORTED);
5173 #if (DBVER < 43)
5174 ADD_INT(d, DB_LSTAT_ERR);
5175 #endif
5176 ADD_INT(d, DB_LSTAT_FREE);
5177 ADD_INT(d, DB_LSTAT_HELD);
5178 #if (DBVER == 33)
5179 ADD_INT(d, DB_LSTAT_NOGRANT);
5180 #endif
5181 ADD_INT(d, DB_LSTAT_PENDING);
5182 ADD_INT(d, DB_LSTAT_WAITING);
5183 #endif
5185 ADD_INT(d, DB_ARCH_ABS);
5186 ADD_INT(d, DB_ARCH_DATA);
5187 ADD_INT(d, DB_ARCH_LOG);
5189 ADD_INT(d, DB_BTREE);
5190 ADD_INT(d, DB_HASH);
5191 ADD_INT(d, DB_RECNO);
5192 ADD_INT(d, DB_QUEUE);
5193 ADD_INT(d, DB_UNKNOWN);
5195 ADD_INT(d, DB_DUP);
5196 ADD_INT(d, DB_DUPSORT);
5197 ADD_INT(d, DB_RECNUM);
5198 ADD_INT(d, DB_RENUMBER);
5199 ADD_INT(d, DB_REVSPLITOFF);
5200 ADD_INT(d, DB_SNAPSHOT);
5202 ADD_INT(d, DB_JOIN_NOSORT);
5204 ADD_INT(d, DB_AFTER);
5205 ADD_INT(d, DB_APPEND);
5206 ADD_INT(d, DB_BEFORE);
5207 ADD_INT(d, DB_CACHED_COUNTS);
5208 #if (DBVER >= 41)
5209 _addIntToDict(d, "DB_CHECKPOINT", 0);
5210 #else
5211 ADD_INT(d, DB_CHECKPOINT);
5212 ADD_INT(d, DB_CURLSN);
5213 #endif
5214 #if ((DBVER >= 33) && (DBVER <= 41))
5215 ADD_INT(d, DB_COMMIT);
5216 #endif
5217 ADD_INT(d, DB_CONSUME);
5218 #if (DBVER >= 32)
5219 ADD_INT(d, DB_CONSUME_WAIT);
5220 #endif
5221 ADD_INT(d, DB_CURRENT);
5222 #if (DBVER >= 33)
5223 ADD_INT(d, DB_FAST_STAT);
5224 #endif
5225 ADD_INT(d, DB_FIRST);
5226 ADD_INT(d, DB_FLUSH);
5227 ADD_INT(d, DB_GET_BOTH);
5228 ADD_INT(d, DB_GET_RECNO);
5229 ADD_INT(d, DB_JOIN_ITEM);
5230 ADD_INT(d, DB_KEYFIRST);
5231 ADD_INT(d, DB_KEYLAST);
5232 ADD_INT(d, DB_LAST);
5233 ADD_INT(d, DB_NEXT);
5234 ADD_INT(d, DB_NEXT_DUP);
5235 ADD_INT(d, DB_NEXT_NODUP);
5236 ADD_INT(d, DB_NODUPDATA);
5237 ADD_INT(d, DB_NOOVERWRITE);
5238 ADD_INT(d, DB_NOSYNC);
5239 ADD_INT(d, DB_POSITION);
5240 ADD_INT(d, DB_PREV);
5241 ADD_INT(d, DB_PREV_NODUP);
5242 ADD_INT(d, DB_RECORDCOUNT);
5243 ADD_INT(d, DB_SET);
5244 ADD_INT(d, DB_SET_RANGE);
5245 ADD_INT(d, DB_SET_RECNO);
5246 ADD_INT(d, DB_WRITECURSOR);
5248 ADD_INT(d, DB_OPFLAGS_MASK);
5249 ADD_INT(d, DB_RMW);
5250 #if (DBVER >= 33)
5251 ADD_INT(d, DB_DIRTY_READ);
5252 ADD_INT(d, DB_MULTIPLE);
5253 ADD_INT(d, DB_MULTIPLE_KEY);
5254 #endif
5256 #if (DBVER >= 33)
5257 ADD_INT(d, DB_DONOTINDEX);
5258 #endif
5260 #if (DBVER >= 41)
5261 _addIntToDict(d, "DB_INCOMPLETE", 0);
5262 #else
5263 ADD_INT(d, DB_INCOMPLETE);
5264 #endif
5265 ADD_INT(d, DB_KEYEMPTY);
5266 ADD_INT(d, DB_KEYEXIST);
5267 ADD_INT(d, DB_LOCK_DEADLOCK);
5268 ADD_INT(d, DB_LOCK_NOTGRANTED);
5269 ADD_INT(d, DB_NOSERVER);
5270 ADD_INT(d, DB_NOSERVER_HOME);
5271 ADD_INT(d, DB_NOSERVER_ID);
5272 ADD_INT(d, DB_NOTFOUND);
5273 ADD_INT(d, DB_OLD_VERSION);
5274 ADD_INT(d, DB_RUNRECOVERY);
5275 ADD_INT(d, DB_VERIFY_BAD);
5276 #if (DBVER >= 33)
5277 ADD_INT(d, DB_PAGE_NOTFOUND);
5278 ADD_INT(d, DB_SECONDARY_BAD);
5279 #endif
5280 #if (DBVER >= 40)
5281 ADD_INT(d, DB_STAT_CLEAR);
5282 ADD_INT(d, DB_REGION_INIT);
5283 ADD_INT(d, DB_NOLOCKING);
5284 ADD_INT(d, DB_YIELDCPU);
5285 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5286 ADD_INT(d, DB_NOPANIC);
5287 #endif
5289 #if (DBVER >= 42)
5290 ADD_INT(d, DB_TIME_NOTGRANTED);
5291 ADD_INT(d, DB_TXN_NOT_DURABLE);
5292 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5293 ADD_INT(d, DB_LOG_AUTOREMOVE);
5294 ADD_INT(d, DB_DIRECT_LOG);
5295 ADD_INT(d, DB_DIRECT_DB);
5296 ADD_INT(d, DB_INIT_REP);
5297 ADD_INT(d, DB_ENCRYPT);
5298 ADD_INT(d, DB_CHKSUM);
5299 #endif
5301 #if (DBVER >= 43)
5302 ADD_INT(d, DB_LOG_INMEMORY);
5303 ADD_INT(d, DB_BUFFER_SMALL);
5304 #endif
5306 #if (DBVER >= 41)
5307 ADD_INT(d, DB_ENCRYPT_AES);
5308 ADD_INT(d, DB_AUTO_COMMIT);
5309 #else
5310 /* allow berkeleydb 4.1 aware apps to run on older versions */
5311 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5312 #endif
5314 ADD_INT(d, EINVAL);
5315 ADD_INT(d, EACCES);
5316 ADD_INT(d, ENOSPC);
5317 ADD_INT(d, ENOMEM);
5318 ADD_INT(d, EAGAIN);
5319 ADD_INT(d, EBUSY);
5320 ADD_INT(d, EEXIST);
5321 ADD_INT(d, ENOENT);
5322 ADD_INT(d, EPERM);
5324 #if (DBVER >= 40)
5325 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5326 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5327 #endif
5329 /* The base exception class is DBError */
5330 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
5331 PyDict_SetItemString(d, "DBError", DBError);
5333 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5334 * from both DBError and KeyError, since the API only supports
5335 * using one base class. */
5336 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5337 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5338 "class DBKeyEmptyError(DBError, KeyError): pass",
5339 Py_file_input, d, d);
5340 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5341 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5342 PyDict_DelItemString(d, "KeyError");
5345 /* All the rest of the exceptions derive only from DBError */
5346 #define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
5347 PyDict_SetItemString(d, #name, name)
5349 #if !INCOMPLETE_IS_WARNING
5350 MAKE_EX(DBIncompleteError);
5351 #endif
5352 MAKE_EX(DBCursorClosedError);
5353 MAKE_EX(DBKeyEmptyError);
5354 MAKE_EX(DBKeyExistError);
5355 MAKE_EX(DBLockDeadlockError);
5356 MAKE_EX(DBLockNotGrantedError);
5357 MAKE_EX(DBOldVersionError);
5358 MAKE_EX(DBRunRecoveryError);
5359 MAKE_EX(DBVerifyBadError);
5360 MAKE_EX(DBNoServerError);
5361 MAKE_EX(DBNoServerHomeError);
5362 MAKE_EX(DBNoServerIDError);
5363 #if (DBVER >= 33)
5364 MAKE_EX(DBPageNotFoundError);
5365 MAKE_EX(DBSecondaryBadError);
5366 #endif
5368 MAKE_EX(DBInvalidArgError);
5369 MAKE_EX(DBAccessError);
5370 MAKE_EX(DBNoSpaceError);
5371 MAKE_EX(DBNoMemoryError);
5372 MAKE_EX(DBAgainError);
5373 MAKE_EX(DBBusyError);
5374 MAKE_EX(DBFileExistsError);
5375 MAKE_EX(DBNoSuchFileError);
5376 MAKE_EX(DBPermissionsError);
5378 #undef MAKE_EX
5380 /* Check for errors */
5381 if (PyErr_Occurred()) {
5382 PyErr_Print();
5383 Py_FatalError("can't initialize module _bsddb");
5387 /* allow this module to be named _pybsddb so that it can be installed
5388 * and imported on top of python >= 2.3 that includes its own older
5389 * copy of the library named _bsddb without importing the old version. */
5390 DL_EXPORT(void) init_pybsddb(void)
5392 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5393 init_bsddb();