Whitespace normalization.
[python/dscho.git] / Modules / _bsddb.c
blobb7f651861f016974fbd677cbf119d9e01dbe8703
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.2.8"
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 */
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; /* ENOMEM */
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 */
188 /* --------------------------------------------------------------------- */
189 /* Structure definitions */
191 #if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
192 #define HAVE_WEAKREF
193 #else
194 #undef HAVE_WEAKREF
195 #endif
197 /* if Python >= 2.1 better support warnings */
198 #if PYTHON_API_VERSION >= 1010
199 #define HAVE_WARNINGS
200 #else
201 #undef HAVE_WARNINGS
202 #endif
204 struct behaviourFlags {
205 /* What is the default behaviour when DB->get or DBCursor->get returns a
206 DB_NOTFOUND error? Return None or raise an exception? */
207 unsigned int getReturnsNone : 1;
208 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
209 * returns a DB_NOTFOUND error? Return None or raise an exception? */
210 unsigned int cursorSetReturnsNone : 1;
213 #define DEFAULT_GET_RETURNS_NONE 1
214 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
216 typedef struct {
217 PyObject_HEAD
218 DB_ENV* db_env;
219 u_int32_t flags; /* saved flags from open() */
220 int closed;
221 struct behaviourFlags moduleFlags;
222 #ifdef HAVE_WEAKREF
223 PyObject *in_weakreflist; /* List of weak references */
224 #endif
225 } DBEnvObject;
228 typedef struct {
229 PyObject_HEAD
230 DB* db;
231 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
232 u_int32_t flags; /* saved flags from open() */
233 u_int32_t setflags; /* saved flags from set_flags() */
234 int haveStat;
235 struct behaviourFlags moduleFlags;
236 #if (DBVER >= 33)
237 PyObject* associateCallback;
238 int primaryDBType;
239 #endif
240 #ifdef HAVE_WEAKREF
241 PyObject *in_weakreflist; /* List of weak references */
242 #endif
243 } DBObject;
246 typedef struct {
247 PyObject_HEAD
248 DBC* dbc;
249 DBObject* mydb;
250 #ifdef HAVE_WEAKREF
251 PyObject *in_weakreflist; /* List of weak references */
252 #endif
253 } DBCursorObject;
256 typedef struct {
257 PyObject_HEAD
258 DB_TXN* txn;
259 #ifdef HAVE_WEAKREF
260 PyObject *in_weakreflist; /* List of weak references */
261 #endif
262 } DBTxnObject;
265 typedef struct {
266 PyObject_HEAD
267 DB_LOCK lock;
268 #ifdef HAVE_WEAKREF
269 PyObject *in_weakreflist; /* List of weak references */
270 #endif
271 } DBLockObject;
275 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
277 #define DBObject_Check(v) ((v)->ob_type == &DB_Type)
278 #define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
279 #define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
280 #define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
281 #define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
284 /* --------------------------------------------------------------------- */
285 /* Utility macros and functions */
287 #define RETURN_IF_ERR() \
288 if (makeDBError(err)) { \
289 return NULL; \
292 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
294 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
295 if ((nonNull) == NULL) { \
296 PyObject *errTuple = NULL; \
297 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
298 PyErr_SetObject((pyErrObj), errTuple); \
299 Py_DECREF(errTuple); \
300 return NULL; \
303 #define CHECK_DB_NOT_CLOSED(dbobj) \
304 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
306 #define CHECK_ENV_NOT_CLOSED(env) \
307 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
309 #define CHECK_CURSOR_NOT_CLOSED(curs) \
310 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
313 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
314 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
316 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
318 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
319 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
322 static int makeDBError(int err);
325 /* Return the access method type of the DBObject */
326 static int _DB_get_type(DBObject* self)
328 #if (DBVER >= 33)
329 DBTYPE type;
330 int err;
331 err = self->db->get_type(self->db, &type);
332 if (makeDBError(err)) {
333 return -1;
335 return type;
336 #else
337 return self->db->get_type(self->db);
338 #endif
342 /* Create a DBT structure (containing key and data values) from Python
343 strings. Returns 1 on success, 0 on an error. */
344 static int make_dbt(PyObject* obj, DBT* dbt)
346 CLEAR_DBT(*dbt);
347 if (obj == Py_None) {
348 /* no need to do anything, the structure has already been zeroed */
350 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
351 PyErr_SetString(PyExc_TypeError,
352 "Data values must be of type string or None.");
353 return 0;
355 return 1;
359 /* Recno and Queue DBs can have integer keys. This function figures out
360 what's been given, verifies that it's allowed, and then makes the DBT.
362 Caller MUST call FREE_DBT(key) when done. */
363 static int
364 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
366 db_recno_t recno;
367 int type;
369 CLEAR_DBT(*key);
370 if (keyobj == Py_None) {
371 type = _DB_get_type(self);
372 if (type == -1)
373 return 0;
374 if (type == DB_RECNO || type == DB_QUEUE) {
375 PyErr_SetString(
376 PyExc_TypeError,
377 "None keys not allowed for Recno and Queue DB's");
378 return 0;
380 /* no need to do anything, the structure has already been zeroed */
383 else if (PyString_Check(keyobj)) {
384 /* verify access method type */
385 type = _DB_get_type(self);
386 if (type == -1)
387 return 0;
388 if (type == DB_RECNO || type == DB_QUEUE) {
389 PyErr_SetString(
390 PyExc_TypeError,
391 "String keys not allowed for Recno and Queue DB's");
392 return 0;
395 key->data = PyString_AS_STRING(keyobj);
396 key->size = PyString_GET_SIZE(keyobj);
399 else if (PyInt_Check(keyobj)) {
400 /* verify access method type */
401 type = _DB_get_type(self);
402 if (type == -1)
403 return 0;
404 if (type == DB_BTREE && pflags != NULL) {
405 /* if BTREE then an Integer key is allowed with the
406 * DB_SET_RECNO flag */
407 *pflags |= DB_SET_RECNO;
409 else if (type != DB_RECNO && type != DB_QUEUE) {
410 PyErr_SetString(
411 PyExc_TypeError,
412 "Integer keys only allowed for Recno and Queue DB's");
413 return 0;
416 /* Make a key out of the requested recno, use allocated space so DB
417 * will be able to realloc room for the real key if needed. */
418 recno = PyInt_AS_LONG(keyobj);
419 key->data = malloc(sizeof(db_recno_t));
420 if (key->data == NULL) {
421 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
422 return 0;
424 key->ulen = key->size = sizeof(db_recno_t);
425 memcpy(key->data, &recno, sizeof(db_recno_t));
426 key->flags = DB_DBT_REALLOC;
428 else {
429 PyErr_Format(PyExc_TypeError,
430 "String or Integer object expected for key, %s found",
431 keyobj->ob_type->tp_name);
432 return 0;
435 return 1;
439 /* Add partial record access to an existing DBT data struct.
440 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
441 and the data storage/retrieval will be done using dlen and doff. */
442 static int add_partial_dbt(DBT* d, int dlen, int doff) {
443 /* if neither were set we do nothing (-1 is the default value) */
444 if ((dlen == -1) && (doff == -1)) {
445 return 1;
448 if ((dlen < 0) || (doff < 0)) {
449 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
450 return 0;
453 d->flags = d->flags | DB_DBT_PARTIAL;
454 d->dlen = (unsigned int) dlen;
455 d->doff = (unsigned int) doff;
456 return 1;
460 /* Callback used to save away more information about errors from the DB
461 * library. */
462 static char _db_errmsg[1024];
463 static void _db_errorCallback(const char* prefix, char* msg)
465 strcpy(_db_errmsg, msg);
469 /* make a nice exception object to raise for errors. */
470 static int makeDBError(int err)
472 char errTxt[2048]; /* really big, just in case... */
473 PyObject *errObj = NULL;
474 PyObject *errTuple = NULL;
475 int exceptionRaised = 0;
477 switch (err) {
478 case 0: /* successful, no error */ break;
480 #if (DBVER < 41)
481 case DB_INCOMPLETE:
482 #if INCOMPLETE_IS_WARNING
483 strcpy(errTxt, db_strerror(err));
484 if (_db_errmsg[0]) {
485 strcat(errTxt, " -- ");
486 strcat(errTxt, _db_errmsg);
487 _db_errmsg[0] = 0;
489 #ifdef HAVE_WARNINGS
490 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
491 #else
492 fprintf(stderr, errTxt);
493 fprintf(stderr, "\n");
494 #endif
496 #else /* do an exception instead */
497 errObj = DBIncompleteError;
498 #endif
499 break;
500 #endif /* DBVER < 41 */
502 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
503 case DB_KEYEXIST: errObj = DBKeyExistError; break;
504 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
505 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
506 case DB_NOTFOUND: errObj = DBNotFoundError; break;
507 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
508 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
509 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
510 case DB_NOSERVER: errObj = DBNoServerError; break;
511 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
512 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
513 #if (DBVER >= 33)
514 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
515 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
516 #endif
518 case EINVAL: errObj = DBInvalidArgError; break;
519 case EACCES: errObj = DBAccessError; break;
520 case ENOSPC: errObj = DBNoSpaceError; break;
521 case ENOMEM: errObj = DBNoMemoryError; break;
522 case EAGAIN: errObj = DBAgainError; break;
523 case EBUSY : errObj = DBBusyError; break;
524 case EEXIST: errObj = DBFileExistsError; break;
525 case ENOENT: errObj = DBNoSuchFileError; break;
526 case EPERM : errObj = DBPermissionsError; break;
528 default: errObj = DBError; break;
531 if (errObj != NULL) {
532 /* FIXME this needs proper bounds checking on errTxt */
533 strcpy(errTxt, db_strerror(err));
534 if (_db_errmsg[0]) {
535 strcat(errTxt, " -- ");
536 strcat(errTxt, _db_errmsg);
537 _db_errmsg[0] = 0;
540 errTuple = Py_BuildValue("(is)", err, errTxt);
541 PyErr_SetObject(errObj, errTuple);
542 Py_DECREF(errTuple);
545 return ((errObj != NULL) || exceptionRaised);
550 /* set a type exception */
551 static void makeTypeError(char* expected, PyObject* found)
553 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
554 expected, found->ob_type->tp_name);
558 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
559 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
561 if (txnobj == Py_None || txnobj == NULL) {
562 *txn = NULL;
563 return 1;
565 if (DBTxnObject_Check(txnobj)) {
566 *txn = ((DBTxnObject*)txnobj)->txn;
567 return 1;
569 else
570 makeTypeError("DBTxn", txnobj);
571 return 0;
575 /* Delete a key from a database
576 Returns 0 on success, -1 on an error. */
577 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
579 int err;
581 MYDB_BEGIN_ALLOW_THREADS;
582 err = self->db->del(self->db, txn, key, 0);
583 MYDB_END_ALLOW_THREADS;
584 if (makeDBError(err)) {
585 return -1;
587 self->haveStat = 0;
588 return 0;
592 /* Store a key into a database
593 Returns 0 on success, -1 on an error. */
594 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
596 int err;
598 MYDB_BEGIN_ALLOW_THREADS;
599 err = self->db->put(self->db, txn, key, data, flags);
600 MYDB_END_ALLOW_THREADS;
601 if (makeDBError(err)) {
602 return -1;
604 self->haveStat = 0;
605 return 0;
608 /* Get a key/data pair from a cursor */
609 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
610 PyObject *args, PyObject *kwargs, char *format)
612 int err;
613 PyObject* retval = NULL;
614 DBT key, data;
615 int dlen = -1;
616 int doff = -1;
617 int flags = 0;
618 char* kwnames[] = { "flags", "dlen", "doff", NULL };
620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
621 &flags, &dlen, &doff))
622 return NULL;
624 CHECK_CURSOR_NOT_CLOSED(self);
626 flags |= extra_flags;
627 CLEAR_DBT(key);
628 CLEAR_DBT(data);
629 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
630 /* Tell BerkeleyDB to malloc the return value (thread safe) */
631 data.flags = DB_DBT_MALLOC;
632 key.flags = DB_DBT_MALLOC;
634 if (!add_partial_dbt(&data, dlen, doff))
635 return NULL;
637 MYDB_BEGIN_ALLOW_THREADS;
638 err = self->dbc->c_get(self->dbc, &key, &data, flags);
639 MYDB_END_ALLOW_THREADS;
641 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
642 Py_INCREF(Py_None);
643 retval = Py_None;
645 else if (makeDBError(err)) {
646 retval = NULL;
648 else { /* otherwise, success! */
650 /* if Recno or Queue, return the key as an Int */
651 switch (_DB_get_type(self->mydb)) {
652 case -1:
653 retval = NULL;
654 break;
656 case DB_RECNO:
657 case DB_QUEUE:
658 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
659 data.data, data.size);
660 break;
661 case DB_HASH:
662 case DB_BTREE:
663 default:
664 retval = Py_BuildValue("s#s#", key.data, key.size,
665 data.data, data.size);
666 break;
669 if (!err) {
670 FREE_DBT(key);
671 FREE_DBT(data);
673 return retval;
677 /* add an integer to a dictionary using the given name as a key */
678 static void _addIntToDict(PyObject* dict, char *name, int value)
680 PyObject* v = PyInt_FromLong((long) value);
681 if (!v || PyDict_SetItemString(dict, name, v))
682 PyErr_Clear();
684 Py_XDECREF(v);
690 /* --------------------------------------------------------------------- */
691 /* Allocators and deallocators */
693 static DBObject*
694 newDBObject(DBEnvObject* arg, int flags)
696 DBObject* self;
697 DB_ENV* db_env = NULL;
698 int err;
700 #if PYTHON_API_VERSION <= 1007
701 /* 1.5 compatibility */
702 self = PyObject_NEW(DBObject, &DB_Type);
703 #else
704 self = PyObject_New(DBObject, &DB_Type);
705 #endif
707 if (self == NULL)
708 return NULL;
710 self->haveStat = 0;
711 self->flags = 0;
712 self->setflags = 0;
713 self->myenvobj = NULL;
714 #if (DBVER >= 33)
715 self->associateCallback = NULL;
716 self->primaryDBType = 0;
717 #endif
718 #ifdef HAVE_WEAKREF
719 self->in_weakreflist = NULL;
720 #endif
722 /* keep a reference to our python DBEnv object */
723 if (arg) {
724 Py_INCREF(arg);
725 self->myenvobj = arg;
726 db_env = arg->db_env;
729 if (self->myenvobj)
730 self->moduleFlags = self->myenvobj->moduleFlags;
731 else
732 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
733 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
735 MYDB_BEGIN_ALLOW_THREADS;
736 err = db_create(&self->db, db_env, flags);
737 self->db->set_errcall(self->db, _db_errorCallback);
738 #if (DBVER >= 33)
739 self->db->app_private = (void*)self;
740 #endif
741 MYDB_END_ALLOW_THREADS;
742 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
743 * list so that a DBEnv can refuse to close without aborting any open
744 * open DBTxns and closing any open DBs first. */
745 if (makeDBError(err)) {
746 if (self->myenvobj) {
747 Py_DECREF(self->myenvobj);
748 self->myenvobj = NULL;
750 self = NULL;
752 return self;
756 static void
757 DB_dealloc(DBObject* self)
759 if (self->db != NULL) {
760 /* avoid closing a DB when its DBEnv has been closed out from under
761 * it */
762 if (!self->myenvobj ||
763 (self->myenvobj && self->myenvobj->db_env))
765 MYDB_BEGIN_ALLOW_THREADS;
766 self->db->close(self->db, 0);
767 MYDB_END_ALLOW_THREADS;
768 #ifdef HAVE_WARNINGS
769 } else {
770 PyErr_Warn(PyExc_RuntimeWarning,
771 "DB could not be closed in destructor: DBEnv already closed");
772 #endif
774 self->db = NULL;
776 #ifdef HAVE_WEAKREF
777 if (self->in_weakreflist != NULL) {
778 PyObject_ClearWeakRefs((PyObject *) self);
780 #endif
781 if (self->myenvobj) {
782 Py_DECREF(self->myenvobj);
783 self->myenvobj = NULL;
785 #if (DBVER >= 33)
786 if (self->associateCallback != NULL) {
787 Py_DECREF(self->associateCallback);
788 self->associateCallback = NULL;
790 #endif
791 #if PYTHON_API_VERSION <= 1007
792 PyMem_DEL(self);
793 #else
794 PyObject_Del(self);
795 #endif
799 static DBCursorObject*
800 newDBCursorObject(DBC* dbc, DBObject* db)
802 DBCursorObject* self;
803 #if PYTHON_API_VERSION <= 1007
804 self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
805 #else
806 self = PyObject_New(DBCursorObject, &DBCursor_Type);
807 #endif
808 if (self == NULL)
809 return NULL;
811 self->dbc = dbc;
812 self->mydb = db;
813 #ifdef HAVE_WEAKREF
814 self->in_weakreflist = NULL;
815 #endif
816 Py_INCREF(self->mydb);
817 return self;
821 static void
822 DBCursor_dealloc(DBCursorObject* self)
824 int err;
826 #ifdef HAVE_WEAKREF
827 if (self->in_weakreflist != NULL) {
828 PyObject_ClearWeakRefs((PyObject *) self);
830 #endif
832 if (self->dbc != NULL) {
833 MYDB_BEGIN_ALLOW_THREADS;
834 /* If the underlying database has been closed, we don't
835 need to do anything. If the environment has been closed
836 we need to leak, as BerkeleyDB will crash trying to access
837 the environment. There was an exception when the
838 user closed the environment even though there still was
839 a database open. */
840 if (self->mydb->db && self->mydb->myenvobj &&
841 !self->mydb->myenvobj->closed)
842 err = self->dbc->c_close(self->dbc);
843 self->dbc = NULL;
844 MYDB_END_ALLOW_THREADS;
846 Py_XDECREF( self->mydb );
847 #if PYTHON_API_VERSION <= 1007
848 PyMem_DEL(self);
849 #else
850 PyObject_Del(self);
851 #endif
855 static DBEnvObject*
856 newDBEnvObject(int flags)
858 int err;
859 DBEnvObject* self;
860 #if PYTHON_API_VERSION <= 1007
861 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
862 #else
863 self = PyObject_New(DBEnvObject, &DBEnv_Type);
864 #endif
866 if (self == NULL)
867 return NULL;
869 self->closed = 1;
870 self->flags = flags;
871 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
872 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
873 #ifdef HAVE_WEAKREF
874 self->in_weakreflist = NULL;
875 #endif
877 MYDB_BEGIN_ALLOW_THREADS;
878 err = db_env_create(&self->db_env, flags);
879 MYDB_END_ALLOW_THREADS;
880 if (makeDBError(err)) {
881 self = NULL;
883 else {
884 self->db_env->set_errcall(self->db_env, _db_errorCallback);
886 return self;
890 static void
891 DBEnv_dealloc(DBEnvObject* self)
893 #ifdef HAVE_WEAKREF
894 if (self->in_weakreflist != NULL) {
895 PyObject_ClearWeakRefs((PyObject *) self);
897 #endif
899 if (!self->closed) {
900 MYDB_BEGIN_ALLOW_THREADS;
901 self->db_env->close(self->db_env, 0);
902 MYDB_END_ALLOW_THREADS;
904 #if PYTHON_API_VERSION <= 1007
905 PyMem_DEL(self);
906 #else
907 PyObject_Del(self);
908 #endif
912 static DBTxnObject*
913 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
915 int err;
916 DBTxnObject* self;
918 #if PYTHON_API_VERSION <= 1007
919 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
920 #else
921 self = PyObject_New(DBTxnObject, &DBTxn_Type);
922 #endif
923 if (self == NULL)
924 return NULL;
925 #ifdef HAVE_WEAKREF
926 self->in_weakreflist = NULL;
927 #endif
929 MYDB_BEGIN_ALLOW_THREADS;
930 #if (DBVER >= 40)
931 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
932 #else
933 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
934 #endif
935 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
936 * list so that a DBEnv can refuse to close without aborting any open
937 * open DBTxns and closing any open DBs first. */
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
940 self = NULL;
942 return self;
946 static void
947 DBTxn_dealloc(DBTxnObject* self)
949 #ifdef HAVE_WEAKREF
950 if (self->in_weakreflist != NULL) {
951 PyObject_ClearWeakRefs((PyObject *) self);
953 #endif
955 #ifdef HAVE_WARNINGS
956 if (self->txn) {
957 /* it hasn't been finalized, abort it! */
958 MYDB_BEGIN_ALLOW_THREADS;
959 #if (DBVER >= 40)
960 self->txn->abort(self->txn);
961 #else
962 txn_abort(self->txn);
963 #endif
964 MYDB_END_ALLOW_THREADS;
965 PyErr_Warn(PyExc_RuntimeWarning,
966 "DBTxn aborted in destructor. No prior commit() or abort().");
968 #endif
970 #if PYTHON_API_VERSION <= 1007
971 PyMem_DEL(self);
972 #else
973 PyObject_Del(self);
974 #endif
978 static DBLockObject*
979 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
980 db_lockmode_t lock_mode, int flags)
982 int err;
983 DBLockObject* self;
985 #if PYTHON_API_VERSION <= 1007
986 self = PyObject_NEW(DBLockObject, &DBLock_Type);
987 #else
988 self = PyObject_New(DBLockObject, &DBLock_Type);
989 #endif
990 if (self == NULL)
991 return NULL;
992 #ifdef HAVE_WEAKREF
993 self->in_weakreflist = NULL;
994 #endif
996 MYDB_BEGIN_ALLOW_THREADS;
997 #if (DBVER >= 40)
998 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
999 &self->lock);
1000 #else
1001 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1002 #endif
1003 MYDB_END_ALLOW_THREADS;
1004 if (makeDBError(err)) {
1005 self = NULL;
1008 return self;
1012 static void
1013 DBLock_dealloc(DBLockObject* self)
1015 #ifdef HAVE_WEAKREF
1016 if (self->in_weakreflist != NULL) {
1017 PyObject_ClearWeakRefs((PyObject *) self);
1019 #endif
1020 /* TODO: is this lock held? should we release it? */
1022 #if PYTHON_API_VERSION <= 1007
1023 PyMem_DEL(self);
1024 #else
1025 PyObject_Del(self);
1026 #endif
1030 /* --------------------------------------------------------------------- */
1031 /* DB methods */
1033 static PyObject*
1034 DB_append(DBObject* self, PyObject* args)
1036 PyObject* txnobj = NULL;
1037 PyObject* dataobj;
1038 db_recno_t recno;
1039 DBT key, data;
1040 DB_TXN *txn = NULL;
1042 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
1043 return NULL;
1045 CHECK_DB_NOT_CLOSED(self);
1047 /* make a dummy key out of a recno */
1048 recno = 0;
1049 CLEAR_DBT(key);
1050 key.data = &recno;
1051 key.size = sizeof(recno);
1052 key.ulen = key.size;
1053 key.flags = DB_DBT_USERMEM;
1055 if (!make_dbt(dataobj, &data)) return NULL;
1056 if (!checkTxnObj(txnobj, &txn)) return NULL;
1058 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1059 return NULL;
1061 return PyInt_FromLong(recno);
1065 #if (DBVER >= 33)
1067 static int
1068 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1069 DBT* secKey)
1071 int retval = DB_DONOTINDEX;
1072 DBObject* secondaryDB = (DBObject*)db->app_private;
1073 PyObject* callback = secondaryDB->associateCallback;
1074 int type = secondaryDB->primaryDBType;
1075 PyObject* key;
1076 PyObject* data;
1077 PyObject* args;
1078 PyObject* result;
1081 if (callback != NULL) {
1082 MYDB_BEGIN_BLOCK_THREADS;
1084 if (type == DB_RECNO || type == DB_QUEUE) {
1085 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
1087 else {
1088 key = PyString_FromStringAndSize(priKey->data, priKey->size);
1090 data = PyString_FromStringAndSize(priData->data, priData->size);
1091 args = PyTuple_New(2);
1092 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
1093 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
1095 result = PyEval_CallObject(callback, args);
1097 if (result == NULL) {
1098 PyErr_Print();
1100 else if (result == Py_None) {
1101 retval = DB_DONOTINDEX;
1103 else if (PyInt_Check(result)) {
1104 retval = PyInt_AsLong(result);
1106 else if (PyString_Check(result)) {
1107 char* data;
1108 int size;
1110 CLEAR_DBT(*secKey);
1111 #if PYTHON_API_VERSION <= 1007
1112 /* 1.5 compatibility */
1113 size = PyString_Size(result);
1114 data = PyString_AsString(result);
1115 #else
1116 PyString_AsStringAndSize(result, &data, &size);
1117 #endif
1118 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1119 secKey->data = malloc(size); /* TODO, check this */
1120 if (secKey->data) {
1121 memcpy(secKey->data, data, size);
1122 secKey->size = size;
1123 retval = 0;
1125 else {
1126 PyErr_SetString(PyExc_MemoryError,
1127 "malloc failed in _db_associateCallback");
1128 PyErr_Print();
1131 else {
1132 PyErr_SetString(
1133 PyExc_TypeError,
1134 "DB associate callback should return DB_DONOTINDEX or string.");
1135 PyErr_Print();
1138 Py_DECREF(args);
1139 if (result) {
1140 Py_DECREF(result);
1143 MYDB_END_BLOCK_THREADS;
1145 return retval;
1149 static PyObject*
1150 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1152 int err, flags=0;
1153 DBObject* secondaryDB;
1154 PyObject* callback;
1155 #if (DBVER >= 41)
1156 PyObject *txnobj = NULL;
1157 DB_TXN *txn = NULL;
1158 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1159 #else
1160 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1161 #endif
1163 #if (DBVER >= 41)
1164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1165 &secondaryDB, &callback, &flags,
1166 &txnobj)) {
1167 #else
1168 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1169 &secondaryDB, &callback, &flags)) {
1170 #endif
1171 return NULL;
1174 #if (DBVER >= 41)
1175 if (!checkTxnObj(txnobj, &txn)) return NULL;
1176 #endif
1178 CHECK_DB_NOT_CLOSED(self);
1179 if (!DBObject_Check(secondaryDB)) {
1180 makeTypeError("DB", (PyObject*)secondaryDB);
1181 return NULL;
1183 if (callback == Py_None) {
1184 callback = NULL;
1186 else if (!PyCallable_Check(callback)) {
1187 makeTypeError("Callable", callback);
1188 return NULL;
1191 /* Save a reference to the callback in the secondary DB. */
1192 if (self->associateCallback != NULL) {
1193 Py_DECREF(self->associateCallback);
1195 Py_INCREF(callback);
1196 secondaryDB->associateCallback = callback;
1197 secondaryDB->primaryDBType = _DB_get_type(self);
1199 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1200 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1201 * The global interepreter lock is not initialized until the first
1202 * thread is created using thread.start_new_thread() or fork() is
1203 * called. that would cause the ALLOW_THREADS here to segfault due
1204 * to a null pointer reference if no threads or child processes
1205 * have been created. This works around that and is a no-op if
1206 * threads have already been initialized.
1207 * (see pybsddb-users mailing list post on 2002-08-07)
1209 #ifdef WITH_THREAD
1210 PyEval_InitThreads();
1211 #endif
1212 MYDB_BEGIN_ALLOW_THREADS;
1213 #if (DBVER >= 41)
1214 err = self->db->associate(self->db,
1215 txn,
1216 secondaryDB->db,
1217 _db_associateCallback,
1218 flags);
1219 #else
1220 err = self->db->associate(self->db,
1221 secondaryDB->db,
1222 _db_associateCallback,
1223 flags);
1224 #endif
1225 MYDB_END_ALLOW_THREADS;
1227 if (err) {
1228 Py_DECREF(self->associateCallback);
1229 self->associateCallback = NULL;
1230 secondaryDB->primaryDBType = 0;
1233 RETURN_IF_ERR();
1234 RETURN_NONE();
1238 #endif
1241 static PyObject*
1242 DB_close(DBObject* self, PyObject* args)
1244 int err, flags=0;
1245 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1246 return NULL;
1247 if (self->db != NULL) {
1248 if (self->myenvobj)
1249 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1250 err = self->db->close(self->db, flags);
1251 self->db = NULL;
1252 RETURN_IF_ERR();
1254 RETURN_NONE();
1258 #if (DBVER >= 32)
1259 static PyObject*
1260 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1262 int err, flags=0, type;
1263 PyObject* txnobj = NULL;
1264 PyObject* retval = NULL;
1265 DBT key, data;
1266 DB_TXN *txn = NULL;
1267 char* kwnames[] = { "txn", "flags", NULL };
1269 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1270 &txnobj, &flags))
1271 return NULL;
1273 CHECK_DB_NOT_CLOSED(self);
1274 type = _DB_get_type(self);
1275 if (type == -1)
1276 return NULL;
1277 if (type != DB_QUEUE) {
1278 PyErr_SetString(PyExc_TypeError,
1279 "Consume methods only allowed for Queue DB's");
1280 return NULL;
1282 if (!checkTxnObj(txnobj, &txn))
1283 return NULL;
1285 CLEAR_DBT(key);
1286 CLEAR_DBT(data);
1287 if (CHECK_DBFLAG(self, DB_THREAD)) {
1288 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1289 data.flags = DB_DBT_MALLOC;
1290 key.flags = DB_DBT_MALLOC;
1293 MYDB_BEGIN_ALLOW_THREADS;
1294 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1295 MYDB_END_ALLOW_THREADS;
1297 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1298 err = 0;
1299 Py_INCREF(Py_None);
1300 retval = Py_None;
1302 else if (!err) {
1303 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1304 data.size);
1305 FREE_DBT(key);
1306 FREE_DBT(data);
1309 RETURN_IF_ERR();
1310 return retval;
1313 static PyObject*
1314 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1316 return _DB_consume(self, args, kwargs, DB_CONSUME);
1319 static PyObject*
1320 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1321 int consume_flag)
1323 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1325 #endif
1329 static PyObject*
1330 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1332 int err, flags=0;
1333 DBC* dbc;
1334 PyObject* txnobj = NULL;
1335 DB_TXN *txn = NULL;
1336 char* kwnames[] = { "txn", "flags", NULL };
1338 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1339 &txnobj, &flags))
1340 return NULL;
1341 CHECK_DB_NOT_CLOSED(self);
1342 if (!checkTxnObj(txnobj, &txn))
1343 return NULL;
1345 MYDB_BEGIN_ALLOW_THREADS;
1346 err = self->db->cursor(self->db, txn, &dbc, flags);
1347 MYDB_END_ALLOW_THREADS;
1348 RETURN_IF_ERR();
1349 return (PyObject*) newDBCursorObject(dbc, self);
1353 static PyObject*
1354 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1356 PyObject* txnobj = NULL;
1357 int flags = 0;
1358 PyObject* keyobj;
1359 DBT key;
1360 DB_TXN *txn = NULL;
1361 char* kwnames[] = { "key", "txn", "flags", NULL };
1363 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1364 &keyobj, &txnobj, &flags))
1365 return NULL;
1366 CHECK_DB_NOT_CLOSED(self);
1367 if (!make_key_dbt(self, keyobj, &key, NULL))
1368 return NULL;
1369 if (!checkTxnObj(txnobj, &txn)) {
1370 FREE_DBT(key);
1371 return NULL;
1374 if (-1 == _DB_delete(self, txn, &key, 0)) {
1375 FREE_DBT(key);
1376 return NULL;
1379 FREE_DBT(key);
1380 RETURN_NONE();
1384 static PyObject*
1385 DB_fd(DBObject* self, PyObject* args)
1387 int err, the_fd;
1389 if (!PyArg_ParseTuple(args,":fd"))
1390 return NULL;
1391 CHECK_DB_NOT_CLOSED(self);
1393 MYDB_BEGIN_ALLOW_THREADS;
1394 err = self->db->fd(self->db, &the_fd);
1395 MYDB_END_ALLOW_THREADS;
1396 RETURN_IF_ERR();
1397 return PyInt_FromLong(the_fd);
1401 static PyObject*
1402 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1404 int err, flags=0;
1405 PyObject* txnobj = NULL;
1406 PyObject* keyobj;
1407 PyObject* dfltobj = NULL;
1408 PyObject* retval = NULL;
1409 int dlen = -1;
1410 int doff = -1;
1411 DBT key, data;
1412 DB_TXN *txn = NULL;
1413 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1415 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1416 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1417 &doff))
1418 return NULL;
1420 CHECK_DB_NOT_CLOSED(self);
1421 if (!make_key_dbt(self, keyobj, &key, &flags))
1422 return NULL;
1423 if (!checkTxnObj(txnobj, &txn)) {
1424 FREE_DBT(key);
1425 return NULL;
1428 CLEAR_DBT(data);
1429 if (CHECK_DBFLAG(self, DB_THREAD)) {
1430 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1431 data.flags = DB_DBT_MALLOC;
1433 if (!add_partial_dbt(&data, dlen, doff)) {
1434 FREE_DBT(key);
1435 return NULL;
1438 MYDB_BEGIN_ALLOW_THREADS;
1439 err = self->db->get(self->db, txn, &key, &data, flags);
1440 MYDB_END_ALLOW_THREADS;
1442 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1443 err = 0;
1444 Py_INCREF(dfltobj);
1445 retval = dfltobj;
1447 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1448 err = 0;
1449 Py_INCREF(Py_None);
1450 retval = Py_None;
1452 else if (!err) {
1453 if (flags & DB_SET_RECNO) /* return both key and data */
1454 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1455 data.size);
1456 else /* return just the data */
1457 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1458 FREE_DBT(data);
1460 FREE_DBT(key);
1462 RETURN_IF_ERR();
1463 return retval;
1466 static PyObject*
1467 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1469 int err, flags=0;
1470 PyObject* txnobj = NULL;
1471 PyObject* keyobj;
1472 PyObject* dfltobj = NULL;
1473 PyObject* retval = NULL;
1474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, pkey, data;
1477 DB_TXN *txn = NULL;
1478 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1480 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1481 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1482 &doff))
1483 return NULL;
1485 CHECK_DB_NOT_CLOSED(self);
1486 if (!make_key_dbt(self, keyobj, &key, &flags))
1487 return NULL;
1488 if (!checkTxnObj(txnobj, &txn)) {
1489 FREE_DBT(key);
1490 return NULL;
1493 CLEAR_DBT(data);
1494 if (CHECK_DBFLAG(self, DB_THREAD)) {
1495 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1496 data.flags = DB_DBT_MALLOC;
1498 if (!add_partial_dbt(&data, dlen, doff)) {
1499 FREE_DBT(key);
1500 return NULL;
1503 CLEAR_DBT(pkey);
1504 pkey.flags = DB_DBT_MALLOC;
1506 MYDB_BEGIN_ALLOW_THREADS;
1507 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1508 MYDB_END_ALLOW_THREADS;
1510 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1511 err = 0;
1512 Py_INCREF(dfltobj);
1513 retval = dfltobj;
1515 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1516 err = 0;
1517 Py_INCREF(Py_None);
1518 retval = Py_None;
1520 else if (!err) {
1521 PyObject *pkeyObj;
1522 PyObject *dataObj;
1523 dataObj = PyString_FromStringAndSize(data.data, data.size);
1525 if (self->primaryDBType == DB_RECNO ||
1526 self->primaryDBType == DB_QUEUE)
1527 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
1528 else
1529 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1531 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1533 PyObject *keyObj;
1534 int type = _DB_get_type(self);
1535 if (type == DB_RECNO || type == DB_QUEUE)
1536 keyObj = PyInt_FromLong(*(long *)key.data);
1537 else
1538 keyObj = PyString_FromStringAndSize(key.data, key.size);
1539 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1541 else /* return just the pkey and data */
1543 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1545 FREE_DBT(pkey);
1546 FREE_DBT(data);
1548 FREE_DBT(key);
1550 RETURN_IF_ERR();
1551 return retval;
1555 /* Return size of entry */
1556 static PyObject*
1557 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1559 int err, flags=0;
1560 PyObject* txnobj = NULL;
1561 PyObject* keyobj;
1562 PyObject* retval = NULL;
1563 DBT key, data;
1564 DB_TXN *txn = NULL;
1565 char* kwnames[] = { "key", "txn", NULL };
1567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1568 &keyobj, &txnobj))
1569 return NULL;
1570 CHECK_DB_NOT_CLOSED(self);
1571 if (!make_key_dbt(self, keyobj, &key, &flags))
1572 return NULL;
1573 if (!checkTxnObj(txnobj, &txn)) {
1574 FREE_DBT(key);
1575 return NULL;
1577 CLEAR_DBT(data);
1579 /* We don't allocate any memory, forcing a ENOMEM error and thus
1580 getting the record size. */
1581 data.flags = DB_DBT_USERMEM;
1582 data.ulen = 0;
1583 MYDB_BEGIN_ALLOW_THREADS;
1584 err = self->db->get(self->db, txn, &key, &data, flags);
1585 MYDB_END_ALLOW_THREADS;
1586 if (err == ENOMEM) {
1587 retval = PyInt_FromLong((long)data.size);
1588 err = 0;
1591 FREE_DBT(key);
1592 FREE_DBT(data);
1593 RETURN_IF_ERR();
1594 return retval;
1598 static PyObject*
1599 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1601 int err, flags=0;
1602 PyObject* txnobj = NULL;
1603 PyObject* keyobj;
1604 PyObject* dataobj;
1605 PyObject* retval = NULL;
1606 DBT key, data;
1607 DB_TXN *txn = NULL;
1608 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1611 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1612 &keyobj, &dataobj, &txnobj, &flags))
1613 return NULL;
1615 CHECK_DB_NOT_CLOSED(self);
1616 if (!make_key_dbt(self, keyobj, &key, NULL))
1617 return NULL;
1618 if ( !make_dbt(dataobj, &data) ||
1619 !checkTxnObj(txnobj, &txn) )
1621 FREE_DBT(key);
1622 return NULL;
1625 flags |= DB_GET_BOTH;
1627 if (CHECK_DBFLAG(self, DB_THREAD)) {
1628 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1629 data.flags = DB_DBT_MALLOC;
1630 /* TODO: Is this flag needed? We're passing a data object that should
1631 match what's in the DB, so there should be no need to malloc.
1632 We run the risk of freeing something twice! Check this. */
1635 MYDB_BEGIN_ALLOW_THREADS;
1636 err = self->db->get(self->db, txn, &key, &data, flags);
1637 MYDB_END_ALLOW_THREADS;
1639 if ((err == DB_NOTFOUND) && 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 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 char* kwnames[] = {
1790 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1791 /* without dbname */
1792 char* kwnames_basic[] = {
1793 "filename", "dbtype", "flags", "mode", "txn", NULL};
1794 #else
1795 /* with dbname */
1796 char* kwnames[] = {
1797 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1798 /* without dbname */
1799 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 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1885 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1886 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1887 return NULL;
1889 CHECK_DB_NOT_CLOSED(self);
1890 if (!make_key_dbt(self, keyobj, &key, NULL))
1891 return NULL;
1892 if ( !make_dbt(dataobj, &data) ||
1893 !add_partial_dbt(&data, dlen, doff) ||
1894 !checkTxnObj(txnobj, &txn) )
1896 FREE_DBT(key);
1897 return NULL;
1900 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1901 FREE_DBT(key);
1902 return NULL;
1905 if (flags & DB_APPEND)
1906 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1907 else {
1908 retval = Py_None;
1909 Py_INCREF(retval);
1911 FREE_DBT(key);
1912 return retval;
1917 static PyObject*
1918 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1920 char* filename;
1921 char* database = NULL;
1922 int err, flags=0;
1923 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1925 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1926 &filename, &database, &flags))
1927 return NULL;
1928 CHECK_DB_NOT_CLOSED(self);
1930 err = self->db->remove(self->db, filename, database, flags);
1931 self->db = NULL;
1932 RETURN_IF_ERR();
1933 RETURN_NONE();
1938 static PyObject*
1939 DB_rename(DBObject* self, PyObject* args)
1941 char* filename;
1942 char* database;
1943 char* newname;
1944 int err, flags=0;
1946 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1947 &flags))
1948 return NULL;
1949 CHECK_DB_NOT_CLOSED(self);
1951 MYDB_BEGIN_ALLOW_THREADS;
1952 err = self->db->rename(self->db, filename, database, newname, flags);
1953 MYDB_END_ALLOW_THREADS;
1954 RETURN_IF_ERR();
1955 RETURN_NONE();
1959 static PyObject*
1960 DB_set_bt_minkey(DBObject* self, PyObject* args)
1962 int err, minkey;
1964 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1965 return NULL;
1966 CHECK_DB_NOT_CLOSED(self);
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->set_bt_minkey(self->db, minkey);
1970 MYDB_END_ALLOW_THREADS;
1971 RETURN_IF_ERR();
1972 RETURN_NONE();
1976 static PyObject*
1977 DB_set_cachesize(DBObject* self, PyObject* args)
1979 int err;
1980 int gbytes = 0, bytes = 0, ncache = 0;
1982 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1983 &gbytes,&bytes,&ncache))
1984 return NULL;
1985 CHECK_DB_NOT_CLOSED(self);
1987 MYDB_BEGIN_ALLOW_THREADS;
1988 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1989 MYDB_END_ALLOW_THREADS;
1990 RETURN_IF_ERR();
1991 RETURN_NONE();
1995 static PyObject*
1996 DB_set_flags(DBObject* self, PyObject* args)
1998 int err, flags;
2000 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2001 return NULL;
2002 CHECK_DB_NOT_CLOSED(self);
2004 MYDB_BEGIN_ALLOW_THREADS;
2005 err = self->db->set_flags(self->db, flags);
2006 MYDB_END_ALLOW_THREADS;
2007 RETURN_IF_ERR();
2009 self->setflags |= flags;
2010 RETURN_NONE();
2014 static PyObject*
2015 DB_set_h_ffactor(DBObject* self, PyObject* args)
2017 int err, ffactor;
2019 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2020 return NULL;
2021 CHECK_DB_NOT_CLOSED(self);
2023 MYDB_BEGIN_ALLOW_THREADS;
2024 err = self->db->set_h_ffactor(self->db, ffactor);
2025 MYDB_END_ALLOW_THREADS;
2026 RETURN_IF_ERR();
2027 RETURN_NONE();
2031 static PyObject*
2032 DB_set_h_nelem(DBObject* self, PyObject* args)
2034 int err, nelem;
2036 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2037 return NULL;
2038 CHECK_DB_NOT_CLOSED(self);
2040 MYDB_BEGIN_ALLOW_THREADS;
2041 err = self->db->set_h_nelem(self->db, nelem);
2042 MYDB_END_ALLOW_THREADS;
2043 RETURN_IF_ERR();
2044 RETURN_NONE();
2048 static PyObject*
2049 DB_set_lorder(DBObject* self, PyObject* args)
2051 int err, lorder;
2053 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2054 return NULL;
2055 CHECK_DB_NOT_CLOSED(self);
2057 MYDB_BEGIN_ALLOW_THREADS;
2058 err = self->db->set_lorder(self->db, lorder);
2059 MYDB_END_ALLOW_THREADS;
2060 RETURN_IF_ERR();
2061 RETURN_NONE();
2065 static PyObject*
2066 DB_set_pagesize(DBObject* self, PyObject* args)
2068 int err, pagesize;
2070 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2071 return NULL;
2072 CHECK_DB_NOT_CLOSED(self);
2074 MYDB_BEGIN_ALLOW_THREADS;
2075 err = self->db->set_pagesize(self->db, pagesize);
2076 MYDB_END_ALLOW_THREADS;
2077 RETURN_IF_ERR();
2078 RETURN_NONE();
2082 static PyObject*
2083 DB_set_re_delim(DBObject* self, PyObject* args)
2085 int err;
2086 char delim;
2088 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2089 PyErr_Clear();
2090 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2091 return NULL;
2094 CHECK_DB_NOT_CLOSED(self);
2096 MYDB_BEGIN_ALLOW_THREADS;
2097 err = self->db->set_re_delim(self->db, delim);
2098 MYDB_END_ALLOW_THREADS;
2099 RETURN_IF_ERR();
2100 RETURN_NONE();
2103 static PyObject*
2104 DB_set_re_len(DBObject* self, PyObject* args)
2106 int err, len;
2108 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2109 return NULL;
2110 CHECK_DB_NOT_CLOSED(self);
2112 MYDB_BEGIN_ALLOW_THREADS;
2113 err = self->db->set_re_len(self->db, len);
2114 MYDB_END_ALLOW_THREADS;
2115 RETURN_IF_ERR();
2116 RETURN_NONE();
2120 static PyObject*
2121 DB_set_re_pad(DBObject* self, PyObject* args)
2123 int err;
2124 char pad;
2126 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2127 PyErr_Clear();
2128 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2129 return NULL;
2131 CHECK_DB_NOT_CLOSED(self);
2133 MYDB_BEGIN_ALLOW_THREADS;
2134 err = self->db->set_re_pad(self->db, pad);
2135 MYDB_END_ALLOW_THREADS;
2136 RETURN_IF_ERR();
2137 RETURN_NONE();
2141 static PyObject*
2142 DB_set_re_source(DBObject* self, PyObject* args)
2144 int err;
2145 char *re_source;
2147 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2148 return NULL;
2149 CHECK_DB_NOT_CLOSED(self);
2151 MYDB_BEGIN_ALLOW_THREADS;
2152 err = self->db->set_re_source(self->db, re_source);
2153 MYDB_END_ALLOW_THREADS;
2154 RETURN_IF_ERR();
2155 RETURN_NONE();
2159 #if (DBVER >= 32)
2160 static PyObject*
2161 DB_set_q_extentsize(DBObject* self, PyObject* args)
2163 int err;
2164 int extentsize;
2166 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2167 return NULL;
2168 CHECK_DB_NOT_CLOSED(self);
2170 MYDB_BEGIN_ALLOW_THREADS;
2171 err = self->db->set_q_extentsize(self->db, extentsize);
2172 MYDB_END_ALLOW_THREADS;
2173 RETURN_IF_ERR();
2174 RETURN_NONE();
2176 #endif
2178 static PyObject*
2179 DB_stat(DBObject* self, PyObject* args)
2181 int err, flags = 0, type;
2182 void* sp;
2183 PyObject* d;
2186 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
2187 return NULL;
2188 CHECK_DB_NOT_CLOSED(self);
2190 MYDB_BEGIN_ALLOW_THREADS;
2191 #if (DBVER >= 33)
2192 err = self->db->stat(self->db, &sp, flags);
2193 #else
2194 err = self->db->stat(self->db, &sp, NULL, flags);
2195 #endif
2196 MYDB_END_ALLOW_THREADS;
2197 RETURN_IF_ERR();
2199 self->haveStat = 1;
2201 /* Turn the stat structure into a dictionary */
2202 type = _DB_get_type(self);
2203 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2204 free(sp);
2205 return NULL;
2208 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2209 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2210 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2212 switch (type) {
2213 case DB_HASH:
2214 MAKE_HASH_ENTRY(magic);
2215 MAKE_HASH_ENTRY(version);
2216 MAKE_HASH_ENTRY(nkeys);
2217 MAKE_HASH_ENTRY(ndata);
2218 MAKE_HASH_ENTRY(pagesize);
2219 #if (DBVER < 41)
2220 MAKE_HASH_ENTRY(nelem);
2221 #endif
2222 MAKE_HASH_ENTRY(ffactor);
2223 MAKE_HASH_ENTRY(buckets);
2224 MAKE_HASH_ENTRY(free);
2225 MAKE_HASH_ENTRY(bfree);
2226 MAKE_HASH_ENTRY(bigpages);
2227 MAKE_HASH_ENTRY(big_bfree);
2228 MAKE_HASH_ENTRY(overflows);
2229 MAKE_HASH_ENTRY(ovfl_free);
2230 MAKE_HASH_ENTRY(dup);
2231 MAKE_HASH_ENTRY(dup_free);
2232 break;
2234 case DB_BTREE:
2235 case DB_RECNO:
2236 MAKE_BT_ENTRY(magic);
2237 MAKE_BT_ENTRY(version);
2238 MAKE_BT_ENTRY(nkeys);
2239 MAKE_BT_ENTRY(ndata);
2240 MAKE_BT_ENTRY(pagesize);
2241 MAKE_BT_ENTRY(minkey);
2242 MAKE_BT_ENTRY(re_len);
2243 MAKE_BT_ENTRY(re_pad);
2244 MAKE_BT_ENTRY(levels);
2245 MAKE_BT_ENTRY(int_pg);
2246 MAKE_BT_ENTRY(leaf_pg);
2247 MAKE_BT_ENTRY(dup_pg);
2248 MAKE_BT_ENTRY(over_pg);
2249 MAKE_BT_ENTRY(free);
2250 MAKE_BT_ENTRY(int_pgfree);
2251 MAKE_BT_ENTRY(leaf_pgfree);
2252 MAKE_BT_ENTRY(dup_pgfree);
2253 MAKE_BT_ENTRY(over_pgfree);
2254 break;
2256 case DB_QUEUE:
2257 MAKE_QUEUE_ENTRY(magic);
2258 MAKE_QUEUE_ENTRY(version);
2259 MAKE_QUEUE_ENTRY(nkeys);
2260 MAKE_QUEUE_ENTRY(ndata);
2261 MAKE_QUEUE_ENTRY(pagesize);
2262 MAKE_QUEUE_ENTRY(pages);
2263 MAKE_QUEUE_ENTRY(re_len);
2264 MAKE_QUEUE_ENTRY(re_pad);
2265 MAKE_QUEUE_ENTRY(pgfree);
2266 #if (DBVER == 31)
2267 MAKE_QUEUE_ENTRY(start);
2268 #endif
2269 MAKE_QUEUE_ENTRY(first_recno);
2270 MAKE_QUEUE_ENTRY(cur_recno);
2271 break;
2273 default:
2274 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2275 Py_DECREF(d);
2276 d = NULL;
2279 #undef MAKE_HASH_ENTRY
2280 #undef MAKE_BT_ENTRY
2281 #undef MAKE_QUEUE_ENTRY
2283 free(sp);
2284 return d;
2287 static PyObject*
2288 DB_sync(DBObject* self, PyObject* args)
2290 int err;
2291 int flags = 0;
2293 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2294 return NULL;
2295 CHECK_DB_NOT_CLOSED(self);
2297 MYDB_BEGIN_ALLOW_THREADS;
2298 err = self->db->sync(self->db, flags);
2299 MYDB_END_ALLOW_THREADS;
2300 RETURN_IF_ERR();
2301 RETURN_NONE();
2305 #if (DBVER >= 33)
2306 static PyObject*
2307 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2309 int err, flags=0;
2310 u_int32_t count=0;
2311 PyObject* txnobj = NULL;
2312 DB_TXN *txn = NULL;
2313 char* kwnames[] = { "txn", "flags", NULL };
2315 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2316 &txnobj, &flags))
2317 return NULL;
2318 CHECK_DB_NOT_CLOSED(self);
2319 if (!checkTxnObj(txnobj, &txn))
2320 return NULL;
2322 MYDB_BEGIN_ALLOW_THREADS;
2323 err = self->db->truncate(self->db, txn, &count, flags);
2324 MYDB_END_ALLOW_THREADS;
2325 RETURN_IF_ERR();
2326 return PyInt_FromLong(count);
2328 #endif
2331 static PyObject*
2332 DB_upgrade(DBObject* self, PyObject* args)
2334 int err, flags=0;
2335 char *filename;
2337 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2338 return NULL;
2339 CHECK_DB_NOT_CLOSED(self);
2341 MYDB_BEGIN_ALLOW_THREADS;
2342 err = self->db->upgrade(self->db, filename, flags);
2343 MYDB_END_ALLOW_THREADS;
2344 RETURN_IF_ERR();
2345 RETURN_NONE();
2349 static PyObject*
2350 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2352 int err, flags=0;
2353 char* fileName;
2354 char* dbName=NULL;
2355 char* outFileName=NULL;
2356 FILE* outFile=NULL;
2357 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2359 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2360 &fileName, &dbName, &outFileName, &flags))
2361 return NULL;
2363 CHECK_DB_NOT_CLOSED(self);
2364 if (outFileName)
2365 outFile = fopen(outFileName, "w");
2367 MYDB_BEGIN_ALLOW_THREADS;
2368 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2369 MYDB_END_ALLOW_THREADS;
2370 if (outFileName)
2371 fclose(outFile);
2373 /* DB.verify acts as a DB handle destructor (like close); this was
2374 * documented in BerkeleyDB 4.2 but had the undocumented effect
2375 * of not being safe in prior versions while still requiring an explicit
2376 * DB.close call afterwards. Lets call close for the user to emulate
2377 * the safe 4.2 behaviour. */
2378 #if (DBVER <= 41)
2379 self->db->close(self->db, 0);
2380 #endif
2381 self->db = NULL;
2383 RETURN_IF_ERR();
2384 RETURN_NONE();
2388 static PyObject*
2389 DB_set_get_returns_none(DBObject* self, PyObject* args)
2391 int flags=0;
2392 int oldValue=0;
2394 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2395 return NULL;
2396 CHECK_DB_NOT_CLOSED(self);
2398 if (self->moduleFlags.getReturnsNone)
2399 ++oldValue;
2400 if (self->moduleFlags.cursorSetReturnsNone)
2401 ++oldValue;
2402 self->moduleFlags.getReturnsNone = (flags >= 1);
2403 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2404 return PyInt_FromLong(oldValue);
2407 #if (DBVER >= 41)
2408 static PyObject*
2409 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2411 int err;
2412 u_int32_t flags=0;
2413 char *passwd = NULL;
2414 char* kwnames[] = { "passwd", "flags", NULL };
2416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2417 &passwd, &flags)) {
2418 return NULL;
2421 MYDB_BEGIN_ALLOW_THREADS;
2422 err = self->db->set_encrypt(self->db, passwd, flags);
2423 MYDB_END_ALLOW_THREADS;
2425 RETURN_IF_ERR();
2426 RETURN_NONE();
2428 #endif /* DBVER >= 41 */
2431 /*-------------------------------------------------------------- */
2432 /* Mapping and Dictionary-like access routines */
2434 int DB_length(DBObject* self)
2436 int err;
2437 long size = 0;
2438 int flags = 0;
2439 void* sp;
2441 if (self->db == NULL) {
2442 PyErr_SetObject(DBError,
2443 Py_BuildValue("(is)", 0, "DB object has been closed"));
2444 return -1;
2447 if (self->haveStat) { /* Has the stat function been called recently? If
2448 so, we can use the cached value. */
2449 flags = DB_CACHED_COUNTS;
2452 MYDB_BEGIN_ALLOW_THREADS;
2453 #if (DBVER >= 33)
2454 err = self->db->stat(self->db, &sp, flags);
2455 #else
2456 err = self->db->stat(self->db, &sp, NULL, flags);
2457 #endif
2458 MYDB_END_ALLOW_THREADS;
2460 if (err)
2461 return -1;
2463 self->haveStat = 1;
2465 /* All the stat structures have matching fields upto the ndata field,
2466 so we can use any of them for the type cast */
2467 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2468 free(sp);
2469 return size;
2473 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2475 int err;
2476 PyObject* retval;
2477 DBT key;
2478 DBT data;
2480 CHECK_DB_NOT_CLOSED(self);
2481 if (!make_key_dbt(self, keyobj, &key, NULL))
2482 return NULL;
2484 CLEAR_DBT(data);
2485 if (CHECK_DBFLAG(self, DB_THREAD)) {
2486 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2487 data.flags = DB_DBT_MALLOC;
2489 MYDB_BEGIN_ALLOW_THREADS;
2490 err = self->db->get(self->db, NULL, &key, &data, 0);
2491 MYDB_END_ALLOW_THREADS;
2492 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2493 PyErr_SetObject(PyExc_KeyError, keyobj);
2494 retval = NULL;
2496 else if (makeDBError(err)) {
2497 retval = NULL;
2499 else {
2500 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2501 FREE_DBT(data);
2504 FREE_DBT(key);
2505 return retval;
2509 static int
2510 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2512 DBT key, data;
2513 int retval;
2514 int flags = 0;
2516 if (self->db == NULL) {
2517 PyErr_SetObject(DBError,
2518 Py_BuildValue("(is)", 0, "DB object has been closed"));
2519 return -1;
2522 if (!make_key_dbt(self, keyobj, &key, NULL))
2523 return -1;
2525 if (dataobj != NULL) {
2526 if (!make_dbt(dataobj, &data))
2527 retval = -1;
2528 else {
2529 if (self->setflags & (DB_DUP|DB_DUPSORT))
2530 /* dictionaries shouldn't have duplicate keys */
2531 flags = DB_NOOVERWRITE;
2532 retval = _DB_put(self, NULL, &key, &data, flags);
2534 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2535 /* try deleting any old record that matches and then PUT it
2536 * again... */
2537 _DB_delete(self, NULL, &key, 0);
2538 PyErr_Clear();
2539 retval = _DB_put(self, NULL, &key, &data, flags);
2543 else {
2544 /* dataobj == NULL, so delete the key */
2545 retval = _DB_delete(self, NULL, &key, 0);
2547 FREE_DBT(key);
2548 return retval;
2552 static PyObject*
2553 DB_has_key(DBObject* self, PyObject* args)
2555 int err;
2556 PyObject* keyobj;
2557 DBT key, data;
2558 PyObject* txnobj = NULL;
2559 DB_TXN *txn = NULL;
2561 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2562 return NULL;
2563 CHECK_DB_NOT_CLOSED(self);
2564 if (!make_key_dbt(self, keyobj, &key, NULL))
2565 return NULL;
2566 if (!checkTxnObj(txnobj, &txn)) {
2567 FREE_DBT(key);
2568 return NULL;
2571 /* This causes ENOMEM to be returned when the db has the key because
2572 it has a record but can't allocate a buffer for the data. This saves
2573 having to deal with data we won't be using.
2575 CLEAR_DBT(data);
2576 data.flags = DB_DBT_USERMEM;
2578 MYDB_BEGIN_ALLOW_THREADS;
2579 err = self->db->get(self->db, txn, &key, &data, 0);
2580 MYDB_END_ALLOW_THREADS;
2581 FREE_DBT(key);
2582 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2586 #define _KEYS_LIST 1
2587 #define _VALUES_LIST 2
2588 #define _ITEMS_LIST 3
2590 static PyObject*
2591 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2593 int err, dbtype;
2594 DBT key;
2595 DBT data;
2596 DBC *cursor;
2597 PyObject* list;
2598 PyObject* item = NULL;
2600 CHECK_DB_NOT_CLOSED(self);
2601 CLEAR_DBT(key);
2602 CLEAR_DBT(data);
2604 dbtype = _DB_get_type(self);
2605 if (dbtype == -1)
2606 return NULL;
2608 list = PyList_New(0);
2609 if (list == NULL) {
2610 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2611 return NULL;
2614 /* get a cursor */
2615 MYDB_BEGIN_ALLOW_THREADS;
2616 err = self->db->cursor(self->db, NULL, &cursor, 0);
2617 MYDB_END_ALLOW_THREADS;
2618 RETURN_IF_ERR();
2620 if (CHECK_DBFLAG(self, DB_THREAD)) {
2621 key.flags = DB_DBT_REALLOC;
2622 data.flags = DB_DBT_REALLOC;
2625 while (1) { /* use the cursor to traverse the DB, collecting items */
2626 MYDB_BEGIN_ALLOW_THREADS;
2627 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2628 MYDB_END_ALLOW_THREADS;
2630 if (err) {
2631 /* for any error, break out of the loop */
2632 break;
2635 switch (type) {
2636 case _KEYS_LIST:
2637 switch(dbtype) {
2638 case DB_BTREE:
2639 case DB_HASH:
2640 default:
2641 item = PyString_FromStringAndSize((char*)key.data, key.size);
2642 break;
2643 case DB_RECNO:
2644 case DB_QUEUE:
2645 item = PyInt_FromLong(*((db_recno_t*)key.data));
2646 break;
2648 break;
2650 case _VALUES_LIST:
2651 item = PyString_FromStringAndSize((char*)data.data, data.size);
2652 break;
2654 case _ITEMS_LIST:
2655 switch(dbtype) {
2656 case DB_BTREE:
2657 case DB_HASH:
2658 default:
2659 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2660 data.size);
2661 break;
2662 case DB_RECNO:
2663 case DB_QUEUE:
2664 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2665 data.data, data.size);
2666 break;
2668 break;
2670 if (item == NULL) {
2671 Py_DECREF(list);
2672 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2673 list = NULL;
2674 goto done;
2676 PyList_Append(list, item);
2677 Py_DECREF(item);
2680 /* DB_NOTFOUND is okay, it just means we got to the end */
2681 if (err != DB_NOTFOUND && makeDBError(err)) {
2682 Py_DECREF(list);
2683 list = NULL;
2686 done:
2687 FREE_DBT(key);
2688 FREE_DBT(data);
2689 MYDB_BEGIN_ALLOW_THREADS;
2690 cursor->c_close(cursor);
2691 MYDB_END_ALLOW_THREADS;
2692 return list;
2696 static PyObject*
2697 DB_keys(DBObject* self, PyObject* args)
2699 PyObject* txnobj = NULL;
2700 DB_TXN *txn = NULL;
2702 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2703 return NULL;
2704 if (!checkTxnObj(txnobj, &txn))
2705 return NULL;
2706 return _DB_make_list(self, txn, _KEYS_LIST);
2710 static PyObject*
2711 DB_items(DBObject* self, PyObject* args)
2713 PyObject* txnobj = NULL;
2714 DB_TXN *txn = NULL;
2716 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2717 return NULL;
2718 if (!checkTxnObj(txnobj, &txn))
2719 return NULL;
2720 return _DB_make_list(self, txn, _ITEMS_LIST);
2724 static PyObject*
2725 DB_values(DBObject* self, PyObject* args)
2727 PyObject* txnobj = NULL;
2728 DB_TXN *txn = NULL;
2730 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2731 return NULL;
2732 if (!checkTxnObj(txnobj, &txn))
2733 return NULL;
2734 return _DB_make_list(self, txn, _VALUES_LIST);
2737 /* --------------------------------------------------------------------- */
2738 /* DBCursor methods */
2741 static PyObject*
2742 DBC_close(DBCursorObject* self, PyObject* args)
2744 int err = 0;
2746 if (!PyArg_ParseTuple(args, ":close"))
2747 return NULL;
2749 if (self->dbc != NULL) {
2750 MYDB_BEGIN_ALLOW_THREADS;
2751 err = self->dbc->c_close(self->dbc);
2752 self->dbc = NULL;
2753 MYDB_END_ALLOW_THREADS;
2755 RETURN_IF_ERR();
2756 RETURN_NONE();
2760 static PyObject*
2761 DBC_count(DBCursorObject* self, PyObject* args)
2763 int err = 0;
2764 db_recno_t count;
2765 int flags = 0;
2767 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2768 return NULL;
2770 CHECK_CURSOR_NOT_CLOSED(self);
2772 MYDB_BEGIN_ALLOW_THREADS;
2773 err = self->dbc->c_count(self->dbc, &count, flags);
2774 MYDB_END_ALLOW_THREADS;
2775 RETURN_IF_ERR();
2777 return PyInt_FromLong(count);
2781 static PyObject*
2782 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2784 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2788 static PyObject*
2789 DBC_delete(DBCursorObject* self, PyObject* args)
2791 int err, flags=0;
2793 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2794 return NULL;
2796 CHECK_CURSOR_NOT_CLOSED(self);
2798 MYDB_BEGIN_ALLOW_THREADS;
2799 err = self->dbc->c_del(self->dbc, flags);
2800 MYDB_END_ALLOW_THREADS;
2801 RETURN_IF_ERR();
2803 self->mydb->haveStat = 0;
2804 RETURN_NONE();
2808 static PyObject*
2809 DBC_dup(DBCursorObject* self, PyObject* args)
2811 int err, flags =0;
2812 DBC* dbc = NULL;
2814 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2815 return NULL;
2817 CHECK_CURSOR_NOT_CLOSED(self);
2819 MYDB_BEGIN_ALLOW_THREADS;
2820 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2821 MYDB_END_ALLOW_THREADS;
2822 RETURN_IF_ERR();
2824 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2827 static PyObject*
2828 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2830 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2834 static PyObject*
2835 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2837 int err, flags=0;
2838 PyObject* keyobj = NULL;
2839 PyObject* dataobj = NULL;
2840 PyObject* retval = NULL;
2841 int dlen = -1;
2842 int doff = -1;
2843 DBT key, data;
2844 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2846 CLEAR_DBT(key);
2847 CLEAR_DBT(data);
2848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
2849 &flags, &dlen, &doff))
2851 PyErr_Clear();
2852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2853 &kwnames[1],
2854 &keyobj, &flags, &dlen, &doff))
2856 PyErr_Clear();
2857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2858 kwnames, &keyobj, &dataobj,
2859 &flags, &dlen, &doff))
2861 return NULL;
2866 CHECK_CURSOR_NOT_CLOSED(self);
2868 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2869 return NULL;
2870 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2871 (!add_partial_dbt(&data, dlen, doff)) )
2873 FREE_DBT(key);
2874 return NULL;
2877 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2878 data.flags = DB_DBT_MALLOC;
2879 if (!(key.flags & DB_DBT_REALLOC)) {
2880 key.flags |= DB_DBT_MALLOC;
2884 MYDB_BEGIN_ALLOW_THREADS;
2885 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2886 MYDB_END_ALLOW_THREADS;
2888 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2889 Py_INCREF(Py_None);
2890 retval = Py_None;
2892 else if (makeDBError(err)) {
2893 retval = NULL;
2895 else {
2896 switch (_DB_get_type(self->mydb)) {
2897 case -1:
2898 retval = NULL;
2899 break;
2900 case DB_BTREE:
2901 case DB_HASH:
2902 default:
2903 retval = Py_BuildValue("s#s#", key.data, key.size,
2904 data.data, data.size);
2905 break;
2906 case DB_RECNO:
2907 case DB_QUEUE:
2908 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2909 data.data, data.size);
2910 break;
2912 FREE_DBT(data);
2914 FREE_DBT(key);
2915 return retval;
2918 static PyObject*
2919 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2921 int err, flags=0;
2922 PyObject* keyobj = NULL;
2923 PyObject* dataobj = NULL;
2924 PyObject* retval = NULL;
2925 int dlen = -1;
2926 int doff = -1;
2927 DBT key, pkey, data;
2928 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2930 CLEAR_DBT(key);
2931 CLEAR_DBT(data);
2932 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
2933 &flags, &dlen, &doff))
2935 PyErr_Clear();
2936 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
2937 &kwnames[1],
2938 &keyobj, &flags, &dlen, &doff))
2940 PyErr_Clear();
2941 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
2942 kwnames, &keyobj, &dataobj,
2943 &flags, &dlen, &doff))
2945 return NULL;
2950 CHECK_CURSOR_NOT_CLOSED(self);
2952 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2953 return NULL;
2954 if ( (dataobj && !make_dbt(dataobj, &data)) ||
2955 (!add_partial_dbt(&data, dlen, doff)) ) {
2956 FREE_DBT(key);
2957 return NULL;
2960 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2961 data.flags = DB_DBT_MALLOC;
2962 if (!(key.flags & DB_DBT_REALLOC)) {
2963 key.flags |= DB_DBT_MALLOC;
2967 CLEAR_DBT(pkey);
2968 pkey.flags = DB_DBT_MALLOC;
2970 MYDB_BEGIN_ALLOW_THREADS;
2971 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
2972 MYDB_END_ALLOW_THREADS;
2974 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2975 Py_INCREF(Py_None);
2976 retval = Py_None;
2978 else if (makeDBError(err)) {
2979 retval = NULL;
2981 else {
2982 PyObject *pkeyObj;
2983 PyObject *dataObj;
2984 dataObj = PyString_FromStringAndSize(data.data, data.size);
2986 if (self->mydb->primaryDBType == DB_RECNO ||
2987 self->mydb->primaryDBType == DB_QUEUE)
2988 pkeyObj = PyInt_FromLong(*(long *)pkey.data);
2989 else
2990 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
2992 if (flags & DB_SET_RECNO) /* return key, pkey and data */
2994 PyObject *keyObj;
2995 int type = _DB_get_type(self->mydb);
2996 if (type == DB_RECNO || type == DB_QUEUE)
2997 keyObj = PyInt_FromLong(*(long *)key.data);
2998 else
2999 keyObj = PyString_FromStringAndSize(key.data, key.size);
3000 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3001 FREE_DBT(key);
3003 else /* return just the pkey and data */
3005 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3007 FREE_DBT(pkey);
3008 FREE_DBT(data);
3010 /* the only time REALLOC should be set is if we used an integer
3011 * key that make_key_dbt malloc'd for us. always free these. */
3012 if (key.flags & DB_DBT_REALLOC) {
3013 FREE_DBT(key);
3015 return retval;
3019 static PyObject*
3020 DBC_get_recno(DBCursorObject* self, PyObject* args)
3022 int err;
3023 db_recno_t recno;
3024 DBT key;
3025 DBT data;
3027 if (!PyArg_ParseTuple(args, ":get_recno"))
3028 return NULL;
3030 CHECK_CURSOR_NOT_CLOSED(self);
3032 CLEAR_DBT(key);
3033 CLEAR_DBT(data);
3034 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3035 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3036 data.flags = DB_DBT_MALLOC;
3037 key.flags = DB_DBT_MALLOC;
3040 MYDB_BEGIN_ALLOW_THREADS;
3041 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3042 MYDB_END_ALLOW_THREADS;
3043 RETURN_IF_ERR();
3045 recno = *((db_recno_t*)data.data);
3046 FREE_DBT(key);
3047 FREE_DBT(data);
3048 return PyInt_FromLong(recno);
3052 static PyObject*
3053 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3055 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3059 static PyObject*
3060 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3062 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3066 static PyObject*
3067 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3069 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3073 static PyObject*
3074 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3076 int err, flags = 0;
3077 PyObject* keyobj, *dataobj;
3078 DBT key, data;
3079 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3080 int dlen = -1;
3081 int doff = -1;
3083 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3084 &keyobj, &dataobj, &flags, &dlen, &doff))
3085 return NULL;
3087 CHECK_CURSOR_NOT_CLOSED(self);
3089 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3090 return NULL;
3091 if (!make_dbt(dataobj, &data) ||
3092 !add_partial_dbt(&data, dlen, doff) )
3094 FREE_DBT(key);
3095 return NULL;
3098 MYDB_BEGIN_ALLOW_THREADS;
3099 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3100 MYDB_END_ALLOW_THREADS;
3101 FREE_DBT(key);
3102 RETURN_IF_ERR();
3103 self->mydb->haveStat = 0;
3104 RETURN_NONE();
3108 static PyObject*
3109 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3111 int err, flags = 0;
3112 DBT key, data;
3113 PyObject* retval, *keyobj;
3114 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3115 int dlen = -1;
3116 int doff = -1;
3118 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3119 &keyobj, &flags, &dlen, &doff))
3120 return NULL;
3122 CHECK_CURSOR_NOT_CLOSED(self);
3124 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3125 return NULL;
3127 CLEAR_DBT(data);
3128 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3129 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3130 data.flags = DB_DBT_MALLOC;
3132 if (!add_partial_dbt(&data, dlen, doff)) {
3133 FREE_DBT(key);
3134 return NULL;
3137 MYDB_BEGIN_ALLOW_THREADS;
3138 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3139 MYDB_END_ALLOW_THREADS;
3140 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3141 Py_INCREF(Py_None);
3142 retval = Py_None;
3144 else if (makeDBError(err)) {
3145 retval = NULL;
3147 else {
3148 switch (_DB_get_type(self->mydb)) {
3149 case -1:
3150 retval = NULL;
3151 break;
3152 case DB_BTREE:
3153 case DB_HASH:
3154 default:
3155 retval = Py_BuildValue("s#s#", key.data, key.size,
3156 data.data, data.size);
3157 break;
3158 case DB_RECNO:
3159 case DB_QUEUE:
3160 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3161 data.data, data.size);
3162 break;
3164 FREE_DBT(data);
3165 FREE_DBT(key);
3167 /* the only time REALLOC should be set is if we used an integer
3168 * key that make_key_dbt malloc'd for us. always free these. */
3169 if (key.flags & DB_DBT_REALLOC) {
3170 FREE_DBT(key);
3173 return retval;
3177 static PyObject*
3178 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3180 int err, flags = 0;
3181 DBT key, data;
3182 PyObject* retval, *keyobj;
3183 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3184 int dlen = -1;
3185 int doff = -1;
3187 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3188 &keyobj, &flags, &dlen, &doff))
3189 return NULL;
3191 CHECK_CURSOR_NOT_CLOSED(self);
3193 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3194 return NULL;
3196 CLEAR_DBT(data);
3197 if (!add_partial_dbt(&data, dlen, doff)) {
3198 FREE_DBT(key);
3199 return NULL;
3201 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3202 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3203 data.flags |= DB_DBT_MALLOC;
3204 /* only BTREE databases will return anything in the key */
3205 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3206 key.flags |= DB_DBT_MALLOC;
3209 MYDB_BEGIN_ALLOW_THREADS;
3210 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3211 MYDB_END_ALLOW_THREADS;
3212 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3213 Py_INCREF(Py_None);
3214 retval = Py_None;
3216 else if (makeDBError(err)) {
3217 retval = NULL;
3219 else {
3220 switch (_DB_get_type(self->mydb)) {
3221 case -1:
3222 retval = NULL;
3223 break;
3224 case DB_BTREE:
3225 case DB_HASH:
3226 default:
3227 retval = Py_BuildValue("s#s#", key.data, key.size,
3228 data.data, data.size);
3229 break;
3230 case DB_RECNO:
3231 case DB_QUEUE:
3232 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3233 data.data, data.size);
3234 break;
3236 FREE_DBT(key);
3237 FREE_DBT(data);
3239 /* the only time REALLOC should be set is if we used an integer
3240 * key that make_key_dbt malloc'd for us. always free these. */
3241 if (key.flags & DB_DBT_REALLOC) {
3242 FREE_DBT(key);
3245 return retval;
3248 static PyObject*
3249 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3250 int flags, unsigned int returnsNone)
3252 int err;
3253 DBT key, data;
3254 PyObject* retval;
3256 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3257 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3258 return NULL;
3259 if (!make_dbt(dataobj, &data)) {
3260 FREE_DBT(key);
3261 return NULL;
3264 MYDB_BEGIN_ALLOW_THREADS;
3265 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3266 MYDB_END_ALLOW_THREADS;
3267 if ((err == DB_NOTFOUND) && returnsNone) {
3268 Py_INCREF(Py_None);
3269 retval = Py_None;
3271 else if (makeDBError(err)) {
3272 retval = NULL;
3274 else {
3275 switch (_DB_get_type(self->mydb)) {
3276 case -1:
3277 retval = NULL;
3278 break;
3279 case DB_BTREE:
3280 case DB_HASH:
3281 default:
3282 retval = Py_BuildValue("s#s#", key.data, key.size,
3283 data.data, data.size);
3284 break;
3285 case DB_RECNO:
3286 case DB_QUEUE:
3287 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3288 data.data, data.size);
3289 break;
3293 FREE_DBT(key);
3294 return retval;
3297 static PyObject*
3298 DBC_get_both(DBCursorObject* self, PyObject* args)
3300 int flags=0;
3301 PyObject *keyobj, *dataobj;
3303 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3304 return NULL;
3306 /* if the cursor is closed, self->mydb may be invalid */
3307 CHECK_CURSOR_NOT_CLOSED(self);
3309 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3310 self->mydb->moduleFlags.getReturnsNone);
3313 /* Return size of entry */
3314 static PyObject*
3315 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3317 int err, flags=DB_CURRENT;
3318 PyObject* retval = NULL;
3319 DBT key, data;
3321 if (!PyArg_ParseTuple(args, ":get_current_size"))
3322 return NULL;
3323 CHECK_CURSOR_NOT_CLOSED(self);
3324 CLEAR_DBT(key);
3325 CLEAR_DBT(data);
3327 /* We don't allocate any memory, forcing a ENOMEM error and thus
3328 getting the record size. */
3329 data.flags = DB_DBT_USERMEM;
3330 data.ulen = 0;
3331 MYDB_BEGIN_ALLOW_THREADS;
3332 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3333 MYDB_END_ALLOW_THREADS;
3334 if (err == ENOMEM || !err) {
3335 /* ENOMEM means positive size, !err means zero length value */
3336 retval = PyInt_FromLong((long)data.size);
3337 err = 0;
3340 FREE_DBT(key);
3341 FREE_DBT(data);
3342 RETURN_IF_ERR();
3343 return retval;
3346 static PyObject*
3347 DBC_set_both(DBCursorObject* self, PyObject* args)
3349 int flags=0;
3350 PyObject *keyobj, *dataobj;
3352 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3353 return NULL;
3355 /* if the cursor is closed, self->mydb may be invalid */
3356 CHECK_CURSOR_NOT_CLOSED(self);
3358 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3359 self->mydb->moduleFlags.cursorSetReturnsNone);
3363 static PyObject*
3364 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3366 int err, irecno, flags=0;
3367 db_recno_t recno;
3368 DBT key, data;
3369 PyObject* retval;
3370 int dlen = -1;
3371 int doff = -1;
3372 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3374 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3375 &irecno, &flags, &dlen, &doff))
3376 return NULL;
3378 CHECK_CURSOR_NOT_CLOSED(self);
3380 CLEAR_DBT(key);
3381 recno = (db_recno_t) irecno;
3382 /* use allocated space so DB will be able to realloc room for the real
3383 * key */
3384 key.data = malloc(sizeof(db_recno_t));
3385 if (key.data == NULL) {
3386 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3387 return NULL;
3389 key.size = sizeof(db_recno_t);
3390 key.ulen = key.size;
3391 memcpy(key.data, &recno, sizeof(db_recno_t));
3392 key.flags = DB_DBT_REALLOC;
3394 CLEAR_DBT(data);
3395 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3396 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3397 data.flags = DB_DBT_MALLOC;
3399 if (!add_partial_dbt(&data, dlen, doff)) {
3400 FREE_DBT(key);
3401 return NULL;
3404 MYDB_BEGIN_ALLOW_THREADS;
3405 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3406 MYDB_END_ALLOW_THREADS;
3407 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3408 Py_INCREF(Py_None);
3409 retval = Py_None;
3411 else if (makeDBError(err)) {
3412 retval = NULL;
3414 else { /* Can only be used for BTrees, so no need to return int key */
3415 retval = Py_BuildValue("s#s#", key.data, key.size,
3416 data.data, data.size);
3417 FREE_DBT(data);
3419 FREE_DBT(key);
3421 return retval;
3425 static PyObject*
3426 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3428 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3432 static PyObject*
3433 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3435 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3439 static PyObject*
3440 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3442 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3446 static PyObject*
3447 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3449 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3453 static PyObject*
3454 DBC_join_item(DBCursorObject* self, PyObject* args)
3456 int err, flags=0;
3457 DBT key, data;
3458 PyObject* retval;
3460 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3461 return NULL;
3463 CHECK_CURSOR_NOT_CLOSED(self);
3465 CLEAR_DBT(key);
3466 CLEAR_DBT(data);
3467 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3468 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3469 key.flags = DB_DBT_MALLOC;
3472 MYDB_BEGIN_ALLOW_THREADS;
3473 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3474 MYDB_END_ALLOW_THREADS;
3475 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3476 Py_INCREF(Py_None);
3477 retval = Py_None;
3479 else if (makeDBError(err)) {
3480 retval = NULL;
3482 else {
3483 retval = Py_BuildValue("s#", key.data, key.size);
3484 FREE_DBT(key);
3487 return retval;
3492 /* --------------------------------------------------------------------- */
3493 /* DBEnv methods */
3496 static PyObject*
3497 DBEnv_close(DBEnvObject* self, PyObject* args)
3499 int err, flags = 0;
3501 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3502 return NULL;
3503 if (!self->closed) { /* Don't close more than once */
3504 MYDB_BEGIN_ALLOW_THREADS;
3505 err = self->db_env->close(self->db_env, flags);
3506 MYDB_END_ALLOW_THREADS;
3507 /* after calling DBEnv->close, regardless of error, this DBEnv
3508 * may not be accessed again (BerkeleyDB docs). */
3509 self->closed = 1;
3510 self->db_env = NULL;
3511 RETURN_IF_ERR();
3513 RETURN_NONE();
3517 static PyObject*
3518 DBEnv_open(DBEnvObject* self, PyObject* args)
3520 int err, flags=0, mode=0660;
3521 char *db_home;
3523 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3524 return NULL;
3526 CHECK_ENV_NOT_CLOSED(self);
3528 MYDB_BEGIN_ALLOW_THREADS;
3529 err = self->db_env->open(self->db_env, db_home, flags, mode);
3530 MYDB_END_ALLOW_THREADS;
3531 RETURN_IF_ERR();
3532 self->closed = 0;
3533 self->flags = flags;
3534 RETURN_NONE();
3538 static PyObject*
3539 DBEnv_remove(DBEnvObject* self, PyObject* args)
3541 int err, flags=0;
3542 char *db_home;
3544 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3545 return NULL;
3546 CHECK_ENV_NOT_CLOSED(self);
3547 MYDB_BEGIN_ALLOW_THREADS;
3548 err = self->db_env->remove(self->db_env, db_home, flags);
3549 MYDB_END_ALLOW_THREADS;
3550 RETURN_IF_ERR();
3551 RETURN_NONE();
3554 #if (DBVER >= 41)
3555 static PyObject*
3556 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3558 int err;
3559 u_int32_t flags=0;
3560 char *file = NULL;
3561 char *database = NULL;
3562 PyObject *txnobj = NULL;
3563 DB_TXN *txn = NULL;
3564 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3566 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3567 &file, &database, &txnobj, &flags)) {
3568 return NULL;
3570 if (!checkTxnObj(txnobj, &txn)) {
3571 return NULL;
3573 CHECK_ENV_NOT_CLOSED(self);
3574 MYDB_BEGIN_ALLOW_THREADS;
3575 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3576 MYDB_END_ALLOW_THREADS;
3577 RETURN_IF_ERR();
3578 RETURN_NONE();
3581 static PyObject*
3582 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3584 int err;
3585 u_int32_t flags=0;
3586 char *file = NULL;
3587 char *database = NULL;
3588 char *newname = NULL;
3589 PyObject *txnobj = NULL;
3590 DB_TXN *txn = NULL;
3591 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3593 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3594 &file, &database, &newname, &txnobj, &flags)) {
3595 return NULL;
3597 if (!checkTxnObj(txnobj, &txn)) {
3598 return NULL;
3600 CHECK_ENV_NOT_CLOSED(self);
3601 MYDB_BEGIN_ALLOW_THREADS;
3602 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3603 flags);
3604 MYDB_END_ALLOW_THREADS;
3605 RETURN_IF_ERR();
3606 RETURN_NONE();
3609 static PyObject*
3610 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3612 int err;
3613 u_int32_t flags=0;
3614 char *passwd = NULL;
3615 char* kwnames[] = { "passwd", "flags", NULL };
3617 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3618 &passwd, &flags)) {
3619 return NULL;
3622 MYDB_BEGIN_ALLOW_THREADS;
3623 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3624 MYDB_END_ALLOW_THREADS;
3626 RETURN_IF_ERR();
3627 RETURN_NONE();
3629 #endif /* DBVER >= 41 */
3631 #if (DBVER >= 40)
3632 static PyObject*
3633 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3635 int err;
3636 u_int32_t flags=0;
3637 u_int32_t timeout = 0;
3638 char* kwnames[] = { "timeout", "flags", NULL };
3640 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3641 &timeout, &flags)) {
3642 return NULL;
3645 MYDB_BEGIN_ALLOW_THREADS;
3646 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3647 MYDB_END_ALLOW_THREADS;
3649 RETURN_IF_ERR();
3650 RETURN_NONE();
3652 #endif /* DBVER >= 40 */
3654 static PyObject*
3655 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3657 int err;
3658 long shm_key = 0;
3660 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3661 return NULL;
3662 CHECK_ENV_NOT_CLOSED(self);
3664 err = self->db_env->set_shm_key(self->db_env, shm_key);
3665 RETURN_IF_ERR();
3666 RETURN_NONE();
3669 static PyObject*
3670 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3672 int err, gbytes=0, bytes=0, ncache=0;
3674 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3675 &gbytes, &bytes, &ncache))
3676 return NULL;
3677 CHECK_ENV_NOT_CLOSED(self);
3679 MYDB_BEGIN_ALLOW_THREADS;
3680 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3681 MYDB_END_ALLOW_THREADS;
3682 RETURN_IF_ERR();
3683 RETURN_NONE();
3687 #if (DBVER >= 32)
3688 static PyObject*
3689 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3691 int err, flags=0, onoff=0;
3693 if (!PyArg_ParseTuple(args, "ii:set_flags",
3694 &flags, &onoff))
3695 return NULL;
3696 CHECK_ENV_NOT_CLOSED(self);
3698 MYDB_BEGIN_ALLOW_THREADS;
3699 err = self->db_env->set_flags(self->db_env, flags, onoff);
3700 MYDB_END_ALLOW_THREADS;
3701 RETURN_IF_ERR();
3702 RETURN_NONE();
3704 #endif
3707 static PyObject*
3708 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3710 int err;
3711 char *dir;
3713 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3714 return NULL;
3715 CHECK_ENV_NOT_CLOSED(self);
3717 MYDB_BEGIN_ALLOW_THREADS;
3718 err = self->db_env->set_data_dir(self->db_env, dir);
3719 MYDB_END_ALLOW_THREADS;
3720 RETURN_IF_ERR();
3721 RETURN_NONE();
3725 static PyObject*
3726 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3728 int err, lg_bsize;
3730 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3731 return NULL;
3732 CHECK_ENV_NOT_CLOSED(self);
3734 MYDB_BEGIN_ALLOW_THREADS;
3735 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3736 MYDB_END_ALLOW_THREADS;
3737 RETURN_IF_ERR();
3738 RETURN_NONE();
3742 static PyObject*
3743 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3745 int err;
3746 char *dir;
3748 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3749 return NULL;
3750 CHECK_ENV_NOT_CLOSED(self);
3752 MYDB_BEGIN_ALLOW_THREADS;
3753 err = self->db_env->set_lg_dir(self->db_env, dir);
3754 MYDB_END_ALLOW_THREADS;
3755 RETURN_IF_ERR();
3756 RETURN_NONE();
3759 static PyObject*
3760 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3762 int err, lg_max;
3764 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3765 return NULL;
3766 CHECK_ENV_NOT_CLOSED(self);
3768 MYDB_BEGIN_ALLOW_THREADS;
3769 err = self->db_env->set_lg_max(self->db_env, lg_max);
3770 MYDB_END_ALLOW_THREADS;
3771 RETURN_IF_ERR();
3772 RETURN_NONE();
3776 static PyObject*
3777 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3779 int err, lk_detect;
3781 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3782 return NULL;
3783 CHECK_ENV_NOT_CLOSED(self);
3785 MYDB_BEGIN_ALLOW_THREADS;
3786 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3787 MYDB_END_ALLOW_THREADS;
3788 RETURN_IF_ERR();
3789 RETURN_NONE();
3793 static PyObject*
3794 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3796 int err, max;
3798 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3799 return NULL;
3800 CHECK_ENV_NOT_CLOSED(self);
3802 MYDB_BEGIN_ALLOW_THREADS;
3803 err = self->db_env->set_lk_max(self->db_env, max);
3804 MYDB_END_ALLOW_THREADS;
3805 RETURN_IF_ERR();
3806 RETURN_NONE();
3810 #if (DBVER >= 32)
3812 static PyObject*
3813 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3815 int err, max;
3817 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3818 return NULL;
3819 CHECK_ENV_NOT_CLOSED(self);
3821 MYDB_BEGIN_ALLOW_THREADS;
3822 err = self->db_env->set_lk_max_locks(self->db_env, max);
3823 MYDB_END_ALLOW_THREADS;
3824 RETURN_IF_ERR();
3825 RETURN_NONE();
3829 static PyObject*
3830 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3832 int err, max;
3834 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3835 return NULL;
3836 CHECK_ENV_NOT_CLOSED(self);
3838 MYDB_BEGIN_ALLOW_THREADS;
3839 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3840 MYDB_END_ALLOW_THREADS;
3841 RETURN_IF_ERR();
3842 RETURN_NONE();
3846 static PyObject*
3847 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3849 int err, max;
3851 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3852 return NULL;
3853 CHECK_ENV_NOT_CLOSED(self);
3855 MYDB_BEGIN_ALLOW_THREADS;
3856 err = self->db_env->set_lk_max_objects(self->db_env, max);
3857 MYDB_END_ALLOW_THREADS;
3858 RETURN_IF_ERR();
3859 RETURN_NONE();
3862 #endif
3865 static PyObject*
3866 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3868 int err, mp_mmapsize;
3870 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3871 return NULL;
3872 CHECK_ENV_NOT_CLOSED(self);
3874 MYDB_BEGIN_ALLOW_THREADS;
3875 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3876 MYDB_END_ALLOW_THREADS;
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3882 static PyObject*
3883 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3885 int err;
3886 char *dir;
3888 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3889 return NULL;
3890 CHECK_ENV_NOT_CLOSED(self);
3892 MYDB_BEGIN_ALLOW_THREADS;
3893 err = self->db_env->set_tmp_dir(self->db_env, dir);
3894 MYDB_END_ALLOW_THREADS;
3895 RETURN_IF_ERR();
3896 RETURN_NONE();
3900 static PyObject*
3901 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3903 int flags = 0;
3904 PyObject* txnobj = NULL;
3905 DB_TXN *txn = NULL;
3906 char* kwnames[] = { "parent", "flags", NULL };
3908 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3909 &txnobj, &flags))
3910 return NULL;
3912 if (!checkTxnObj(txnobj, &txn))
3913 return NULL;
3914 CHECK_ENV_NOT_CLOSED(self);
3916 return (PyObject*)newDBTxnObject(self, txn, flags);
3920 static PyObject*
3921 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3923 int err, kbyte=0, min=0, flags=0;
3925 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3926 return NULL;
3927 CHECK_ENV_NOT_CLOSED(self);
3929 MYDB_BEGIN_ALLOW_THREADS;
3930 #if (DBVER >= 40)
3931 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3932 #else
3933 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3934 #endif
3935 MYDB_END_ALLOW_THREADS;
3936 RETURN_IF_ERR();
3937 RETURN_NONE();
3941 static PyObject*
3942 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3944 int err, max;
3946 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3947 return NULL;
3948 CHECK_ENV_NOT_CLOSED(self);
3950 MYDB_BEGIN_ALLOW_THREADS;
3951 err = self->db_env->set_tx_max(self->db_env, max);
3952 MYDB_END_ALLOW_THREADS;
3953 RETURN_IF_ERR();
3954 RETURN_NONE();
3958 static PyObject*
3959 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3961 int err, atype, flags=0;
3962 int aborted = 0;
3964 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3965 return NULL;
3966 CHECK_ENV_NOT_CLOSED(self);
3968 MYDB_BEGIN_ALLOW_THREADS;
3969 #if (DBVER >= 40)
3970 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3971 #else
3972 err = lock_detect(self->db_env, flags, atype, &aborted);
3973 #endif
3974 MYDB_END_ALLOW_THREADS;
3975 RETURN_IF_ERR();
3976 return PyInt_FromLong(aborted);
3980 static PyObject*
3981 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3983 int flags=0;
3984 int locker, lock_mode;
3985 DBT obj;
3986 PyObject* objobj;
3988 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3989 return NULL;
3992 if (!make_dbt(objobj, &obj))
3993 return NULL;
3995 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3999 static PyObject*
4000 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4002 int err;
4003 u_int32_t theID;
4005 if (!PyArg_ParseTuple(args, ":lock_id"))
4006 return NULL;
4008 CHECK_ENV_NOT_CLOSED(self);
4009 MYDB_BEGIN_ALLOW_THREADS;
4010 #if (DBVER >= 40)
4011 err = self->db_env->lock_id(self->db_env, &theID);
4012 #else
4013 err = lock_id(self->db_env, &theID);
4014 #endif
4015 MYDB_END_ALLOW_THREADS;
4016 RETURN_IF_ERR();
4018 return PyInt_FromLong((long)theID);
4022 static PyObject*
4023 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4025 int err;
4026 DBLockObject* dblockobj;
4028 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4029 return NULL;
4031 CHECK_ENV_NOT_CLOSED(self);
4032 MYDB_BEGIN_ALLOW_THREADS;
4033 #if (DBVER >= 40)
4034 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4035 #else
4036 err = lock_put(self->db_env, &dblockobj->lock);
4037 #endif
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4044 static PyObject*
4045 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4047 int err;
4048 DB_LOCK_STAT* sp;
4049 PyObject* d = NULL;
4050 u_int32_t flags = 0;
4052 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4053 return NULL;
4054 CHECK_ENV_NOT_CLOSED(self);
4056 MYDB_BEGIN_ALLOW_THREADS;
4057 #if (DBVER >= 40)
4058 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4059 #else
4060 #if (DBVER >= 33)
4061 err = lock_stat(self->db_env, &sp);
4062 #else
4063 err = lock_stat(self->db_env, &sp, NULL);
4064 #endif
4065 #endif
4066 MYDB_END_ALLOW_THREADS;
4067 RETURN_IF_ERR();
4069 /* Turn the stat structure into a dictionary */
4070 d = PyDict_New();
4071 if (d == NULL) {
4072 free(sp);
4073 return NULL;
4076 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4078 #if (DBVER < 41)
4079 MAKE_ENTRY(lastid);
4080 #endif
4081 MAKE_ENTRY(nmodes);
4082 #if (DBVER >= 32)
4083 MAKE_ENTRY(maxlocks);
4084 MAKE_ENTRY(maxlockers);
4085 MAKE_ENTRY(maxobjects);
4086 MAKE_ENTRY(nlocks);
4087 MAKE_ENTRY(maxnlocks);
4088 #endif
4089 MAKE_ENTRY(nlockers);
4090 MAKE_ENTRY(maxnlockers);
4091 #if (DBVER >= 32)
4092 MAKE_ENTRY(nobjects);
4093 MAKE_ENTRY(maxnobjects);
4094 #endif
4095 MAKE_ENTRY(nrequests);
4096 MAKE_ENTRY(nreleases);
4097 MAKE_ENTRY(nnowaits);
4098 MAKE_ENTRY(nconflicts);
4099 MAKE_ENTRY(ndeadlocks);
4100 MAKE_ENTRY(regsize);
4101 MAKE_ENTRY(region_wait);
4102 MAKE_ENTRY(region_nowait);
4104 #undef MAKE_ENTRY
4105 free(sp);
4106 return d;
4110 static PyObject*
4111 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4113 int flags=0;
4114 int err;
4115 char **log_list_start, **log_list;
4116 PyObject* list;
4117 PyObject* item = NULL;
4119 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4120 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 #if (DBVER >= 40)
4125 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4126 #elif (DBVER == 33)
4127 err = log_archive(self->db_env, &log_list, flags);
4128 #else
4129 err = log_archive(self->db_env, &log_list, flags, NULL);
4130 #endif
4131 MYDB_END_ALLOW_THREADS;
4132 RETURN_IF_ERR();
4134 list = PyList_New(0);
4135 if (list == NULL) {
4136 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
4137 return NULL;
4140 if (log_list) {
4141 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4142 item = PyString_FromString (*log_list);
4143 if (item == NULL) {
4144 Py_DECREF(list);
4145 PyErr_SetString(PyExc_MemoryError,
4146 "List item creation failed");
4147 list = NULL;
4148 break;
4150 PyList_Append(list, item);
4151 Py_DECREF(item);
4153 free(log_list_start);
4155 return list;
4159 static PyObject*
4160 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4162 int err;
4163 DB_TXN_STAT* sp;
4164 PyObject* d = NULL;
4165 u_int32_t flags=0;
4167 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4168 return NULL;
4169 CHECK_ENV_NOT_CLOSED(self);
4171 MYDB_BEGIN_ALLOW_THREADS;
4172 #if (DBVER >= 40)
4173 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4174 #elif (DBVER == 33)
4175 err = txn_stat(self->db_env, &sp);
4176 #else
4177 err = txn_stat(self->db_env, &sp, NULL);
4178 #endif
4179 MYDB_END_ALLOW_THREADS;
4180 RETURN_IF_ERR();
4182 /* Turn the stat structure into a dictionary */
4183 d = PyDict_New();
4184 if (d == NULL) {
4185 free(sp);
4186 return NULL;
4189 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4191 MAKE_ENTRY(time_ckp);
4192 MAKE_ENTRY(last_txnid);
4193 MAKE_ENTRY(maxtxns);
4194 MAKE_ENTRY(nactive);
4195 MAKE_ENTRY(maxnactive);
4196 MAKE_ENTRY(nbegins);
4197 MAKE_ENTRY(naborts);
4198 MAKE_ENTRY(ncommits);
4199 MAKE_ENTRY(regsize);
4200 MAKE_ENTRY(region_wait);
4201 MAKE_ENTRY(region_nowait);
4203 #undef MAKE_ENTRY
4204 free(sp);
4205 return d;
4209 static PyObject*
4210 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4212 int flags=0;
4213 int oldValue=0;
4215 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4216 return NULL;
4217 CHECK_ENV_NOT_CLOSED(self);
4219 if (self->moduleFlags.getReturnsNone)
4220 ++oldValue;
4221 if (self->moduleFlags.cursorSetReturnsNone)
4222 ++oldValue;
4223 self->moduleFlags.getReturnsNone = (flags >= 1);
4224 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4225 return PyInt_FromLong(oldValue);
4229 /* --------------------------------------------------------------------- */
4230 /* DBTxn methods */
4233 static PyObject*
4234 DBTxn_commit(DBTxnObject* self, PyObject* args)
4236 int flags=0, err;
4237 DB_TXN *txn;
4239 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4240 return NULL;
4242 if (!self->txn) {
4243 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4244 "DBTxn must not be used after txn_commit or txn_abort"));
4245 return NULL;
4247 txn = self->txn;
4248 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4249 MYDB_BEGIN_ALLOW_THREADS;
4250 #if (DBVER >= 40)
4251 err = txn->commit(txn, flags);
4252 #else
4253 err = txn_commit(txn, flags);
4254 #endif
4255 MYDB_END_ALLOW_THREADS;
4256 RETURN_IF_ERR();
4257 RETURN_NONE();
4260 static PyObject*
4261 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4263 #if (DBVER >= 33)
4264 int err;
4265 char* gid=NULL;
4266 int gid_size=0;
4268 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4269 return NULL;
4271 if (gid_size != DB_XIDDATASIZE) {
4272 PyErr_SetString(PyExc_TypeError,
4273 "gid must be DB_XIDDATASIZE bytes long");
4274 return NULL;
4277 if (!self->txn) {
4278 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4279 "DBTxn must not be used after txn_commit or txn_abort"));
4280 return NULL;
4282 MYDB_BEGIN_ALLOW_THREADS;
4283 #if (DBVER >= 40)
4284 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4285 #else
4286 err = txn_prepare(self->txn, (u_int8_t*)gid);
4287 #endif
4288 MYDB_END_ALLOW_THREADS;
4289 RETURN_IF_ERR();
4290 RETURN_NONE();
4291 #else
4292 int err;
4294 if (!PyArg_ParseTuple(args, ":prepare"))
4295 return NULL;
4297 if (!self->txn) {
4298 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4299 "DBTxn must not be used after txn_commit or txn_abort"));
4300 return NULL;
4302 MYDB_BEGIN_ALLOW_THREADS;
4303 err = txn_prepare(self->txn);
4304 MYDB_END_ALLOW_THREADS;
4305 RETURN_IF_ERR();
4306 RETURN_NONE();
4307 #endif
4311 static PyObject*
4312 DBTxn_abort(DBTxnObject* self, PyObject* args)
4314 int err;
4315 DB_TXN *txn;
4317 if (!PyArg_ParseTuple(args, ":abort"))
4318 return NULL;
4320 if (!self->txn) {
4321 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4322 "DBTxn must not be used after txn_commit or txn_abort"));
4323 return NULL;
4325 txn = self->txn;
4326 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4327 MYDB_BEGIN_ALLOW_THREADS;
4328 #if (DBVER >= 40)
4329 err = txn->abort(txn);
4330 #else
4331 err = txn_abort(txn);
4332 #endif
4333 MYDB_END_ALLOW_THREADS;
4334 RETURN_IF_ERR();
4335 RETURN_NONE();
4339 static PyObject*
4340 DBTxn_id(DBTxnObject* self, PyObject* args)
4342 int id;
4344 if (!PyArg_ParseTuple(args, ":id"))
4345 return NULL;
4347 if (!self->txn) {
4348 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4349 "DBTxn must not be used after txn_commit or txn_abort"));
4350 return NULL;
4352 MYDB_BEGIN_ALLOW_THREADS;
4353 #if (DBVER >= 40)
4354 id = self->txn->id(self->txn);
4355 #else
4356 id = txn_id(self->txn);
4357 #endif
4358 MYDB_END_ALLOW_THREADS;
4359 return PyInt_FromLong(id);
4362 /* --------------------------------------------------------------------- */
4363 /* Method definition tables and type objects */
4365 static PyMethodDef DB_methods[] = {
4366 {"append", (PyCFunction)DB_append, METH_VARARGS},
4367 #if (DBVER >= 33)
4368 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4369 #endif
4370 {"close", (PyCFunction)DB_close, METH_VARARGS},
4371 #if (DBVER >= 32)
4372 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4373 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4374 #endif
4375 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4376 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4377 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4378 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4379 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
4380 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4381 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4382 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4383 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4384 {"join", (PyCFunction)DB_join, METH_VARARGS},
4385 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4386 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4387 {"items", (PyCFunction)DB_items, METH_VARARGS},
4388 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4389 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4390 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4391 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4392 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4393 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4394 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
4395 #if (DBVER >= 41)
4396 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4397 #endif
4398 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4399 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4400 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4401 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4402 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4403 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4404 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4405 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4406 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4407 #if (DBVER >= 32)
4408 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4409 #endif
4410 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4411 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4412 #if (DBVER >= 33)
4413 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4414 #endif
4415 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4416 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4417 {"values", (PyCFunction)DB_values, METH_VARARGS},
4418 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4419 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4420 {NULL, NULL} /* sentinel */
4424 static PyMappingMethods DB_mapping = {
4425 (inquiry)DB_length, /*mp_length*/
4426 (binaryfunc)DB_subscript, /*mp_subscript*/
4427 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4431 static PyMethodDef DBCursor_methods[] = {
4432 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4433 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4434 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4435 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4436 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4437 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4438 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4439 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
4440 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4441 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4442 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4443 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4444 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4445 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4446 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4447 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
4448 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
4449 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
4450 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4451 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4452 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4453 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4454 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4455 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4456 {NULL, NULL} /* sentinel */
4460 static PyMethodDef DBEnv_methods[] = {
4461 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4462 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4463 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
4464 #if (DBVER >= 41)
4465 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4466 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4467 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4468 #endif
4469 #if (DBVER >= 40)
4470 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4471 #endif
4472 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
4473 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4474 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4475 #if (DBVER >= 32)
4476 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4477 #endif
4478 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4479 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4480 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4481 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4482 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4483 #if (DBVER >= 32)
4484 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4485 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4486 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4487 #endif
4488 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4489 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4490 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4491 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4492 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4493 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4494 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4495 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4496 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4497 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4498 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4499 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4500 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4501 {NULL, NULL} /* sentinel */
4505 static PyMethodDef DBTxn_methods[] = {
4506 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4507 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4508 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4509 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4510 {NULL, NULL} /* sentinel */
4514 static PyObject*
4515 DB_getattr(DBObject* self, char *name)
4517 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4521 static PyObject*
4522 DBEnv_getattr(DBEnvObject* self, char *name)
4524 if (!strcmp(name, "db_home")) {
4525 CHECK_ENV_NOT_CLOSED(self);
4526 if (self->db_env->db_home == NULL) {
4527 RETURN_NONE();
4529 return PyString_FromString(self->db_env->db_home);
4532 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4536 static PyObject*
4537 DBCursor_getattr(DBCursorObject* self, char *name)
4539 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4542 static PyObject*
4543 DBTxn_getattr(DBTxnObject* self, char *name)
4545 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4548 static PyObject*
4549 DBLock_getattr(DBLockObject* self, char *name)
4551 return NULL;
4554 statichere PyTypeObject DB_Type = {
4555 PyObject_HEAD_INIT(NULL)
4556 0, /*ob_size*/
4557 "DB", /*tp_name*/
4558 sizeof(DBObject), /*tp_basicsize*/
4559 0, /*tp_itemsize*/
4560 /* methods */
4561 (destructor)DB_dealloc, /*tp_dealloc*/
4562 0, /*tp_print*/
4563 (getattrfunc)DB_getattr, /*tp_getattr*/
4564 0, /*tp_setattr*/
4565 0, /*tp_compare*/
4566 0, /*tp_repr*/
4567 0, /*tp_as_number*/
4568 0, /*tp_as_sequence*/
4569 &DB_mapping,/*tp_as_mapping*/
4570 0, /*tp_hash*/
4571 #ifdef HAVE_WEAKREF
4572 0, /* tp_call */
4573 0, /* tp_str */
4574 0, /* tp_getattro */
4575 0, /* tp_setattro */
4576 0, /* tp_as_buffer */
4577 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4578 0, /* tp_doc */
4579 0, /* tp_traverse */
4580 0, /* tp_clear */
4581 0, /* tp_richcompare */
4582 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
4583 #endif
4587 statichere PyTypeObject DBCursor_Type = {
4588 PyObject_HEAD_INIT(NULL)
4589 0, /*ob_size*/
4590 "DBCursor", /*tp_name*/
4591 sizeof(DBCursorObject), /*tp_basicsize*/
4592 0, /*tp_itemsize*/
4593 /* methods */
4594 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4595 0, /*tp_print*/
4596 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4597 0, /*tp_setattr*/
4598 0, /*tp_compare*/
4599 0, /*tp_repr*/
4600 0, /*tp_as_number*/
4601 0, /*tp_as_sequence*/
4602 0, /*tp_as_mapping*/
4603 0, /*tp_hash*/
4604 #ifdef HAVE_WEAKREF
4605 0, /* tp_call */
4606 0, /* tp_str */
4607 0, /* tp_getattro */
4608 0, /* tp_setattro */
4609 0, /* tp_as_buffer */
4610 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4611 0, /* tp_doc */
4612 0, /* tp_traverse */
4613 0, /* tp_clear */
4614 0, /* tp_richcompare */
4615 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
4616 #endif
4620 statichere PyTypeObject DBEnv_Type = {
4621 PyObject_HEAD_INIT(NULL)
4622 0, /*ob_size*/
4623 "DBEnv", /*tp_name*/
4624 sizeof(DBEnvObject), /*tp_basicsize*/
4625 0, /*tp_itemsize*/
4626 /* methods */
4627 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4628 0, /*tp_print*/
4629 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4630 0, /*tp_setattr*/
4631 0, /*tp_compare*/
4632 0, /*tp_repr*/
4633 0, /*tp_as_number*/
4634 0, /*tp_as_sequence*/
4635 0, /*tp_as_mapping*/
4636 0, /*tp_hash*/
4637 #ifdef HAVE_WEAKREF
4638 0, /* tp_call */
4639 0, /* tp_str */
4640 0, /* tp_getattro */
4641 0, /* tp_setattro */
4642 0, /* tp_as_buffer */
4643 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4644 0, /* tp_doc */
4645 0, /* tp_traverse */
4646 0, /* tp_clear */
4647 0, /* tp_richcompare */
4648 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
4649 #endif
4652 statichere PyTypeObject DBTxn_Type = {
4653 PyObject_HEAD_INIT(NULL)
4654 0, /*ob_size*/
4655 "DBTxn", /*tp_name*/
4656 sizeof(DBTxnObject), /*tp_basicsize*/
4657 0, /*tp_itemsize*/
4658 /* methods */
4659 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4660 0, /*tp_print*/
4661 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4662 0, /*tp_setattr*/
4663 0, /*tp_compare*/
4664 0, /*tp_repr*/
4665 0, /*tp_as_number*/
4666 0, /*tp_as_sequence*/
4667 0, /*tp_as_mapping*/
4668 0, /*tp_hash*/
4669 #ifdef HAVE_WEAKREF
4670 0, /* tp_call */
4671 0, /* tp_str */
4672 0, /* tp_getattro */
4673 0, /* tp_setattro */
4674 0, /* tp_as_buffer */
4675 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4676 0, /* tp_doc */
4677 0, /* tp_traverse */
4678 0, /* tp_clear */
4679 0, /* tp_richcompare */
4680 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
4681 #endif
4685 statichere PyTypeObject DBLock_Type = {
4686 PyObject_HEAD_INIT(NULL)
4687 0, /*ob_size*/
4688 "DBLock", /*tp_name*/
4689 sizeof(DBLockObject), /*tp_basicsize*/
4690 0, /*tp_itemsize*/
4691 /* methods */
4692 (destructor)DBLock_dealloc, /*tp_dealloc*/
4693 0, /*tp_print*/
4694 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4695 0, /*tp_setattr*/
4696 0, /*tp_compare*/
4697 0, /*tp_repr*/
4698 0, /*tp_as_number*/
4699 0, /*tp_as_sequence*/
4700 0, /*tp_as_mapping*/
4701 0, /*tp_hash*/
4702 #ifdef HAVE_WEAKREF
4703 0, /* tp_call */
4704 0, /* tp_str */
4705 0, /* tp_getattro */
4706 0, /* tp_setattro */
4707 0, /* tp_as_buffer */
4708 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
4709 0, /* tp_doc */
4710 0, /* tp_traverse */
4711 0, /* tp_clear */
4712 0, /* tp_richcompare */
4713 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
4714 #endif
4718 /* --------------------------------------------------------------------- */
4719 /* Module-level functions */
4721 static PyObject*
4722 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4724 PyObject* dbenvobj = NULL;
4725 int flags = 0;
4726 char* kwnames[] = { "dbEnv", "flags", NULL};
4728 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4729 &dbenvobj, &flags))
4730 return NULL;
4731 if (dbenvobj == Py_None)
4732 dbenvobj = NULL;
4733 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4734 makeTypeError("DBEnv", dbenvobj);
4735 return NULL;
4738 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4742 static PyObject*
4743 DBEnv_construct(PyObject* self, PyObject* args)
4745 int flags = 0;
4746 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4747 return (PyObject* )newDBEnvObject(flags);
4751 static char bsddb_version_doc[] =
4752 "Returns a tuple of major, minor, and patch release numbers of the\n\
4753 underlying DB library.";
4755 static PyObject*
4756 bsddb_version(PyObject* self, PyObject* args)
4758 int major, minor, patch;
4760 if (!PyArg_ParseTuple(args, ":version"))
4761 return NULL;
4762 db_version(&major, &minor, &patch);
4763 return Py_BuildValue("(iii)", major, minor, patch);
4767 /* List of functions defined in the module */
4769 static PyMethodDef bsddb_methods[] = {
4770 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4771 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4772 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4773 {NULL, NULL} /* sentinel */
4777 /* --------------------------------------------------------------------- */
4778 /* Module initialization */
4781 /* Convenience routine to export an integer value.
4782 * Errors are silently ignored, for better or for worse...
4784 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4786 #define MODULE_NAME_MAX_LEN 11
4787 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
4789 DL_EXPORT(void) init_bsddb(void)
4791 PyObject* m;
4792 PyObject* d;
4793 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4794 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4795 PyObject* cvsid_s = PyString_FromString( rcs_id );
4797 /* Initialize the type of the new type objects here; doing it here
4798 is required for portability to Windows without requiring C++. */
4799 DB_Type.ob_type = &PyType_Type;
4800 DBCursor_Type.ob_type = &PyType_Type;
4801 DBEnv_Type.ob_type = &PyType_Type;
4802 DBTxn_Type.ob_type = &PyType_Type;
4803 DBLock_Type.ob_type = &PyType_Type;
4806 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
4807 /* Save the current interpreter, so callbacks can do the right thing. */
4808 _db_interpreterState = PyThreadState_GET()->interp;
4809 #endif
4811 /* Create the module and add the functions */
4812 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
4814 /* Add some symbolic constants to the module */
4815 d = PyModule_GetDict(m);
4816 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4817 PyDict_SetItemString(d, "cvsid", cvsid_s);
4818 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4819 Py_DECREF(pybsddb_version_s);
4820 pybsddb_version_s = NULL;
4821 Py_DECREF(cvsid_s);
4822 cvsid_s = NULL;
4823 Py_DECREF(db_version_s);
4824 db_version_s = NULL;
4826 ADD_INT(d, DB_VERSION_MAJOR);
4827 ADD_INT(d, DB_VERSION_MINOR);
4828 ADD_INT(d, DB_VERSION_PATCH);
4830 ADD_INT(d, DB_MAX_PAGES);
4831 ADD_INT(d, DB_MAX_RECORDS);
4833 #if (DBVER >= 42)
4834 ADD_INT(d, DB_RPCCLIENT);
4835 #else
4836 ADD_INT(d, DB_CLIENT);
4837 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4838 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4839 #endif
4840 ADD_INT(d, DB_XA_CREATE);
4842 ADD_INT(d, DB_CREATE);
4843 ADD_INT(d, DB_NOMMAP);
4844 ADD_INT(d, DB_THREAD);
4846 ADD_INT(d, DB_FORCE);
4847 ADD_INT(d, DB_INIT_CDB);
4848 ADD_INT(d, DB_INIT_LOCK);
4849 ADD_INT(d, DB_INIT_LOG);
4850 ADD_INT(d, DB_INIT_MPOOL);
4851 ADD_INT(d, DB_INIT_TXN);
4852 #if (DBVER >= 32)
4853 ADD_INT(d, DB_JOINENV);
4854 #endif
4856 ADD_INT(d, DB_RECOVER);
4857 ADD_INT(d, DB_RECOVER_FATAL);
4858 ADD_INT(d, DB_TXN_NOSYNC);
4859 ADD_INT(d, DB_USE_ENVIRON);
4860 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4862 ADD_INT(d, DB_LOCKDOWN);
4863 ADD_INT(d, DB_PRIVATE);
4864 ADD_INT(d, DB_SYSTEM_MEM);
4866 ADD_INT(d, DB_TXN_SYNC);
4867 ADD_INT(d, DB_TXN_NOWAIT);
4869 ADD_INT(d, DB_EXCL);
4870 ADD_INT(d, DB_FCNTL_LOCKING);
4871 ADD_INT(d, DB_ODDFILESIZE);
4872 ADD_INT(d, DB_RDWRMASTER);
4873 ADD_INT(d, DB_RDONLY);
4874 ADD_INT(d, DB_TRUNCATE);
4875 #if (DBVER >= 32)
4876 ADD_INT(d, DB_EXTENT);
4877 ADD_INT(d, DB_CDB_ALLDB);
4878 ADD_INT(d, DB_VERIFY);
4879 #endif
4880 ADD_INT(d, DB_UPGRADE);
4882 ADD_INT(d, DB_AGGRESSIVE);
4883 ADD_INT(d, DB_NOORDERCHK);
4884 ADD_INT(d, DB_ORDERCHKONLY);
4885 ADD_INT(d, DB_PR_PAGE);
4886 #if ! (DBVER >= 33)
4887 ADD_INT(d, DB_VRFY_FLAGMASK);
4888 ADD_INT(d, DB_PR_HEADERS);
4889 #endif
4890 ADD_INT(d, DB_PR_RECOVERYTEST);
4891 ADD_INT(d, DB_SALVAGE);
4893 ADD_INT(d, DB_LOCK_NORUN);
4894 ADD_INT(d, DB_LOCK_DEFAULT);
4895 ADD_INT(d, DB_LOCK_OLDEST);
4896 ADD_INT(d, DB_LOCK_RANDOM);
4897 ADD_INT(d, DB_LOCK_YOUNGEST);
4898 #if (DBVER >= 33)
4899 ADD_INT(d, DB_LOCK_MAXLOCKS);
4900 ADD_INT(d, DB_LOCK_MINLOCKS);
4901 ADD_INT(d, DB_LOCK_MINWRITE);
4902 #endif
4905 #if (DBVER >= 33)
4906 /* docs say to use zero instead */
4907 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
4908 #else
4909 ADD_INT(d, DB_LOCK_CONFLICT);
4910 #endif
4912 ADD_INT(d, DB_LOCK_DUMP);
4913 ADD_INT(d, DB_LOCK_GET);
4914 ADD_INT(d, DB_LOCK_INHERIT);
4915 ADD_INT(d, DB_LOCK_PUT);
4916 ADD_INT(d, DB_LOCK_PUT_ALL);
4917 ADD_INT(d, DB_LOCK_PUT_OBJ);
4919 ADD_INT(d, DB_LOCK_NG);
4920 ADD_INT(d, DB_LOCK_READ);
4921 ADD_INT(d, DB_LOCK_WRITE);
4922 ADD_INT(d, DB_LOCK_NOWAIT);
4923 #if (DBVER >= 32)
4924 ADD_INT(d, DB_LOCK_WAIT);
4925 #endif
4926 ADD_INT(d, DB_LOCK_IWRITE);
4927 ADD_INT(d, DB_LOCK_IREAD);
4928 ADD_INT(d, DB_LOCK_IWR);
4929 #if (DBVER >= 33)
4930 ADD_INT(d, DB_LOCK_DIRTY);
4931 ADD_INT(d, DB_LOCK_WWRITE);
4932 #endif
4934 ADD_INT(d, DB_LOCK_RECORD);
4935 ADD_INT(d, DB_LOCK_UPGRADE);
4936 #if (DBVER >= 32)
4937 ADD_INT(d, DB_LOCK_SWITCH);
4938 #endif
4939 #if (DBVER >= 33)
4940 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4941 #endif
4943 ADD_INT(d, DB_LOCK_NOWAIT);
4944 ADD_INT(d, DB_LOCK_RECORD);
4945 ADD_INT(d, DB_LOCK_UPGRADE);
4947 #if (DBVER >= 33)
4948 ADD_INT(d, DB_LSTAT_ABORTED);
4949 ADD_INT(d, DB_LSTAT_ERR);
4950 ADD_INT(d, DB_LSTAT_FREE);
4951 ADD_INT(d, DB_LSTAT_HELD);
4952 #if (DBVER == 33)
4953 ADD_INT(d, DB_LSTAT_NOGRANT);
4954 #endif
4955 ADD_INT(d, DB_LSTAT_PENDING);
4956 ADD_INT(d, DB_LSTAT_WAITING);
4957 #endif
4959 ADD_INT(d, DB_ARCH_ABS);
4960 ADD_INT(d, DB_ARCH_DATA);
4961 ADD_INT(d, DB_ARCH_LOG);
4963 ADD_INT(d, DB_BTREE);
4964 ADD_INT(d, DB_HASH);
4965 ADD_INT(d, DB_RECNO);
4966 ADD_INT(d, DB_QUEUE);
4967 ADD_INT(d, DB_UNKNOWN);
4969 ADD_INT(d, DB_DUP);
4970 ADD_INT(d, DB_DUPSORT);
4971 ADD_INT(d, DB_RECNUM);
4972 ADD_INT(d, DB_RENUMBER);
4973 ADD_INT(d, DB_REVSPLITOFF);
4974 ADD_INT(d, DB_SNAPSHOT);
4976 ADD_INT(d, DB_JOIN_NOSORT);
4978 ADD_INT(d, DB_AFTER);
4979 ADD_INT(d, DB_APPEND);
4980 ADD_INT(d, DB_BEFORE);
4981 ADD_INT(d, DB_CACHED_COUNTS);
4982 #if (DBVER >= 41)
4983 _addIntToDict(d, "DB_CHECKPOINT", 0);
4984 #else
4985 ADD_INT(d, DB_CHECKPOINT);
4986 ADD_INT(d, DB_CURLSN);
4987 #endif
4988 #if ((DBVER >= 33) && (DBVER <= 41))
4989 ADD_INT(d, DB_COMMIT);
4990 #endif
4991 ADD_INT(d, DB_CONSUME);
4992 #if (DBVER >= 32)
4993 ADD_INT(d, DB_CONSUME_WAIT);
4994 #endif
4995 ADD_INT(d, DB_CURRENT);
4996 #if (DBVER >= 33)
4997 ADD_INT(d, DB_FAST_STAT);
4998 #endif
4999 ADD_INT(d, DB_FIRST);
5000 ADD_INT(d, DB_FLUSH);
5001 ADD_INT(d, DB_GET_BOTH);
5002 ADD_INT(d, DB_GET_RECNO);
5003 ADD_INT(d, DB_JOIN_ITEM);
5004 ADD_INT(d, DB_KEYFIRST);
5005 ADD_INT(d, DB_KEYLAST);
5006 ADD_INT(d, DB_LAST);
5007 ADD_INT(d, DB_NEXT);
5008 ADD_INT(d, DB_NEXT_DUP);
5009 ADD_INT(d, DB_NEXT_NODUP);
5010 ADD_INT(d, DB_NODUPDATA);
5011 ADD_INT(d, DB_NOOVERWRITE);
5012 ADD_INT(d, DB_NOSYNC);
5013 ADD_INT(d, DB_POSITION);
5014 ADD_INT(d, DB_PREV);
5015 ADD_INT(d, DB_PREV_NODUP);
5016 ADD_INT(d, DB_RECORDCOUNT);
5017 ADD_INT(d, DB_SET);
5018 ADD_INT(d, DB_SET_RANGE);
5019 ADD_INT(d, DB_SET_RECNO);
5020 ADD_INT(d, DB_WRITECURSOR);
5022 ADD_INT(d, DB_OPFLAGS_MASK);
5023 ADD_INT(d, DB_RMW);
5024 #if (DBVER >= 33)
5025 ADD_INT(d, DB_DIRTY_READ);
5026 ADD_INT(d, DB_MULTIPLE);
5027 ADD_INT(d, DB_MULTIPLE_KEY);
5028 #endif
5030 #if (DBVER >= 33)
5031 ADD_INT(d, DB_DONOTINDEX);
5032 #endif
5034 #if (DBVER >= 41)
5035 _addIntToDict(d, "DB_INCOMPLETE", 0);
5036 #else
5037 ADD_INT(d, DB_INCOMPLETE);
5038 #endif
5039 ADD_INT(d, DB_KEYEMPTY);
5040 ADD_INT(d, DB_KEYEXIST);
5041 ADD_INT(d, DB_LOCK_DEADLOCK);
5042 ADD_INT(d, DB_LOCK_NOTGRANTED);
5043 ADD_INT(d, DB_NOSERVER);
5044 ADD_INT(d, DB_NOSERVER_HOME);
5045 ADD_INT(d, DB_NOSERVER_ID);
5046 ADD_INT(d, DB_NOTFOUND);
5047 ADD_INT(d, DB_OLD_VERSION);
5048 ADD_INT(d, DB_RUNRECOVERY);
5049 ADD_INT(d, DB_VERIFY_BAD);
5050 #if (DBVER >= 33)
5051 ADD_INT(d, DB_PAGE_NOTFOUND);
5052 ADD_INT(d, DB_SECONDARY_BAD);
5053 #endif
5054 #if (DBVER >= 40)
5055 ADD_INT(d, DB_STAT_CLEAR);
5056 ADD_INT(d, DB_REGION_INIT);
5057 ADD_INT(d, DB_NOLOCKING);
5058 ADD_INT(d, DB_YIELDCPU);
5059 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5060 ADD_INT(d, DB_NOPANIC);
5061 #endif
5063 #if (DBVER >= 42)
5064 ADD_INT(d, DB_TIME_NOTGRANTED);
5065 ADD_INT(d, DB_TXN_NOT_DURABLE);
5066 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5067 ADD_INT(d, DB_LOG_AUTOREMOVE);
5068 ADD_INT(d, DB_DIRECT_LOG);
5069 ADD_INT(d, DB_DIRECT_DB);
5070 ADD_INT(d, DB_INIT_REP);
5071 ADD_INT(d, DB_ENCRYPT);
5072 ADD_INT(d, DB_CHKSUM);
5073 #endif
5075 #if (DBVER >= 41)
5076 ADD_INT(d, DB_ENCRYPT_AES);
5077 ADD_INT(d, DB_AUTO_COMMIT);
5078 #else
5079 /* allow berkeleydb 4.1 aware apps to run on older versions */
5080 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5081 #endif
5083 ADD_INT(d, EINVAL);
5084 ADD_INT(d, EACCES);
5085 ADD_INT(d, ENOSPC);
5086 ADD_INT(d, ENOMEM);
5087 ADD_INT(d, EAGAIN);
5088 ADD_INT(d, EBUSY);
5089 ADD_INT(d, EEXIST);
5090 ADD_INT(d, ENOENT);
5091 ADD_INT(d, EPERM);
5093 #if (DBVER >= 40)
5094 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5095 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5096 #endif
5098 /* The base exception class is DBError */
5099 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
5100 PyDict_SetItemString(d, "DBError", DBError);
5102 /* Some magic to make DBNotFoundError derive from both DBError and
5103 KeyError, since the API only supports using one base class. */
5104 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5105 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
5106 Py_file_input, d, d);
5107 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5108 PyDict_DelItemString(d, "KeyError");
5111 /* All the rest of the exceptions derive only from DBError */
5112 #define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
5113 PyDict_SetItemString(d, #name, name)
5115 #if !INCOMPLETE_IS_WARNING
5116 MAKE_EX(DBIncompleteError);
5117 #endif
5118 MAKE_EX(DBCursorClosedError);
5119 MAKE_EX(DBKeyEmptyError);
5120 MAKE_EX(DBKeyExistError);
5121 MAKE_EX(DBLockDeadlockError);
5122 MAKE_EX(DBLockNotGrantedError);
5123 MAKE_EX(DBOldVersionError);
5124 MAKE_EX(DBRunRecoveryError);
5125 MAKE_EX(DBVerifyBadError);
5126 MAKE_EX(DBNoServerError);
5127 MAKE_EX(DBNoServerHomeError);
5128 MAKE_EX(DBNoServerIDError);
5129 #if (DBVER >= 33)
5130 MAKE_EX(DBPageNotFoundError);
5131 MAKE_EX(DBSecondaryBadError);
5132 #endif
5134 MAKE_EX(DBInvalidArgError);
5135 MAKE_EX(DBAccessError);
5136 MAKE_EX(DBNoSpaceError);
5137 MAKE_EX(DBNoMemoryError);
5138 MAKE_EX(DBAgainError);
5139 MAKE_EX(DBBusyError);
5140 MAKE_EX(DBFileExistsError);
5141 MAKE_EX(DBNoSuchFileError);
5142 MAKE_EX(DBPermissionsError);
5144 #undef MAKE_EX
5146 /* Check for errors */
5147 if (PyErr_Occurred()) {
5148 PyErr_Print();
5149 Py_FatalError("can't initialize module _bsddb");
5153 /* allow this module to be named _pybsddb so that it can be installed
5154 * and imported on top of python >= 2.3 that includes its own older
5155 * copy of the library named _bsddb without importing the old version. */
5156 DL_EXPORT(void) init_pybsddb(void)
5158 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5159 init_bsddb();