This commit was manufactured by cvs2svn to create tag 'r23a1-fork'.
[python/dscho.git] / Modules / _bsddb.c
blob9bb339cab1c5f47c34744b4d39c216406fd68e00
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.1.
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.
56 * This module contains 5 types:
58 * DB (Database)
59 * DBCursor (Database Cursor)
60 * DBEnv (database environment)
61 * DBTxn (An explicit database transaction)
62 * DBLock (A lock handle)
66 /* --------------------------------------------------------------------- */
69 * Portions of this module, associated unit tests and build scripts are the
70 * result of a contract with The Written Word (http://thewrittenword.com/)
71 * Many thanks go out to them for causing me to raise the bar on quality and
72 * functionality, resulting in a better bsddb3 package for all of us to use.
74 * --Robin
77 /* --------------------------------------------------------------------- */
79 #include <Python.h>
80 #include <db.h>
82 /* --------------------------------------------------------------------- */
83 /* Various macro definitions */
85 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
86 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
88 #define PY_BSDDB_VERSION "4.1.1"
89 static char *rcs_id = "$Id$";
92 #ifdef WITH_THREAD
94 /* These are for when calling Python --> C */
95 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
96 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
98 /* and these are for calling C --> Python */
99 static PyInterpreterState* _db_interpreterState = NULL;
100 #define MYDB_BEGIN_BLOCK_THREADS { \
101 PyThreadState* prevState; \
102 PyThreadState* newState; \
103 PyEval_AcquireLock(); \
104 newState = PyThreadState_New(_db_interpreterState); \
105 prevState = PyThreadState_Swap(newState);
107 #define MYDB_END_BLOCK_THREADS \
108 newState = PyThreadState_Swap(prevState); \
109 PyThreadState_Clear(newState); \
110 PyEval_ReleaseLock(); \
111 PyThreadState_Delete(newState); \
114 #else
116 #define MYDB_BEGIN_ALLOW_THREADS
117 #define MYDB_END_ALLOW_THREADS
118 #define MYDB_BEGIN_BLOCK_THREADS
119 #define MYDB_END_BLOCK_THREADS
121 #endif
124 /* What is the default behaviour when DB->get or DBCursor->get returns a
125 DB_NOTFOUND error? Return None or raise an exception? */
126 #define GET_RETURNS_NONE_DEFAULT 1
129 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
130 #define INCOMPLETE_IS_WARNING 1
132 /* --------------------------------------------------------------------- */
133 /* Exceptions */
135 static PyObject* DBError; /* Base class, all others derive from this */
136 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */
137 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
138 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
139 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
140 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
141 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
142 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
143 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
144 static PyObject* DBNoServerError; /* DB_NOSERVER */
145 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
146 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
147 #if (DBVER >= 33)
148 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
149 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
150 #endif
152 #if !INCOMPLETE_IS_WARNING
153 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
154 #endif
156 static PyObject* DBInvalidArgError; /* EINVAL */
157 static PyObject* DBAccessError; /* EACCES */
158 static PyObject* DBNoSpaceError; /* ENOSPC */
159 static PyObject* DBNoMemoryError; /* ENOMEM */
160 static PyObject* DBAgainError; /* EAGAIN */
161 static PyObject* DBBusyError; /* EBUSY */
162 static PyObject* DBFileExistsError; /* EEXIST */
163 static PyObject* DBNoSuchFileError; /* ENOENT */
164 static PyObject* DBPermissionsError; /* EPERM */
168 /* --------------------------------------------------------------------- */
169 /* Structure definitions */
171 typedef struct {
172 PyObject_HEAD
173 DB_ENV* db_env;
174 u_int32_t flags; /* saved flags from open() */
175 int closed;
176 int getReturnsNone;
177 } DBEnvObject;
180 typedef struct {
181 PyObject_HEAD
182 DB* db;
183 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
184 u_int32_t flags; /* saved flags from open() */
185 u_int32_t setflags; /* saved flags from set_flags() */
186 int haveStat;
187 int getReturnsNone;
188 #if (DBVER >= 33)
189 PyObject* associateCallback;
190 int primaryDBType;
191 #endif
192 } DBObject;
195 typedef struct {
196 PyObject_HEAD
197 DBC* dbc;
198 DBObject* mydb;
199 } DBCursorObject;
202 typedef struct {
203 PyObject_HEAD
204 DB_TXN* txn;
205 } DBTxnObject;
208 typedef struct {
209 PyObject_HEAD
210 DB_LOCK lock;
211 } DBLockObject;
215 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
217 #define DBObject_Check(v) ((v)->ob_type == &DB_Type)
218 #define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
219 #define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
220 #define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
221 #define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
224 /* --------------------------------------------------------------------- */
225 /* Utility macros and functions */
227 #define RETURN_IF_ERR() \
228 if (makeDBError(err)) { \
229 return NULL; \
232 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
234 #define CHECK_DB_NOT_CLOSED(dbobj) \
235 if (dbobj->db == NULL) { \
236 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
237 "DB object has been closed")); \
238 return NULL; \
241 #define CHECK_ENV_NOT_CLOSED(env) \
242 if (env->db_env == NULL) { \
243 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
244 "DBEnv object has been closed"));\
245 return NULL; \
248 #define CHECK_CURSOR_NOT_CLOSED(curs) \
249 if (curs->dbc == NULL) { \
250 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
251 "DBCursor object has been closed"));\
252 return NULL; \
257 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
258 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
260 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
262 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
263 dbt.data != NULL) { free(dbt.data); }
266 static int makeDBError(int err);
269 /* Return the access method type of the DBObject */
270 static int _DB_get_type(DBObject* self)
272 #if (DBVER >= 33)
273 DBTYPE type;
274 int err;
275 err = self->db->get_type(self->db, &type);
276 if (makeDBError(err)) {
277 return -1;
279 return type;
280 #else
281 return self->db->get_type(self->db);
282 #endif
286 /* Create a DBT structure (containing key and data values) from Python
287 strings. Returns 1 on success, 0 on an error. */
288 static int make_dbt(PyObject* obj, DBT* dbt)
290 CLEAR_DBT(*dbt);
291 if (obj == Py_None) {
292 /* no need to do anything, the structure has already been zeroed */
294 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
295 PyErr_SetString(PyExc_TypeError,
296 "Key and Data values must be of type string or None.");
297 return 0;
299 return 1;
303 /* Recno and Queue DBs can have integer keys. This function figures out
304 what's been given, verifies that it's allowed, and then makes the DBT.
306 Caller should call FREE_DBT(key) when done. */
307 static int
308 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
310 db_recno_t recno;
311 int type;
313 CLEAR_DBT(*key);
314 if (keyobj == Py_None) { /* TODO: is None really okay for keys? */
315 /* no need to do anything, the structure has already been zeroed */
318 else if (PyString_Check(keyobj)) {
319 /* verify access method type */
320 type = _DB_get_type(self);
321 if (type == -1)
322 return 0;
323 if (type == DB_RECNO || type == DB_QUEUE) {
324 PyErr_SetString(
325 PyExc_TypeError,
326 "String keys not allowed for Recno and Queue DB's");
327 return 0;
330 key->data = PyString_AS_STRING(keyobj);
331 key->size = PyString_GET_SIZE(keyobj);
334 else if (PyInt_Check(keyobj)) {
335 /* verify access method type */
336 type = _DB_get_type(self);
337 if (type == -1)
338 return 0;
339 if (type == DB_BTREE && pflags != NULL) {
340 /* if BTREE then an Integer key is allowed with the
341 * DB_SET_RECNO flag */
342 *pflags |= DB_SET_RECNO;
344 else if (type != DB_RECNO && type != DB_QUEUE) {
345 PyErr_SetString(
346 PyExc_TypeError,
347 "Integer keys only allowed for Recno and Queue DB's");
348 return 0;
351 /* Make a key out of the requested recno, use allocated space so DB
352 * will be able to realloc room for the real key if needed. */
353 recno = PyInt_AS_LONG(keyobj);
354 key->data = malloc(sizeof(db_recno_t));
355 if (key->data == NULL) {
356 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
357 return 0;
359 key->ulen = key->size = sizeof(db_recno_t);
360 memcpy(key->data, &recno, sizeof(db_recno_t));
361 key->flags = DB_DBT_REALLOC;
363 else {
364 PyErr_Format(PyExc_TypeError,
365 "String or Integer object expected for key, %s found",
366 keyobj->ob_type->tp_name);
367 return 0;
370 return 1;
374 /* Add partial record access to an existing DBT data struct.
375 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
376 and the data storage/retrieval will be done using dlen and doff. */
377 static int add_partial_dbt(DBT* d, int dlen, int doff) {
378 /* if neither were set we do nothing (-1 is the default value) */
379 if ((dlen == -1) && (doff == -1)) {
380 return 1;
383 if ((dlen < 0) || (doff < 0)) {
384 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
385 return 0;
388 d->flags = d->flags | DB_DBT_PARTIAL;
389 d->dlen = (unsigned int) dlen;
390 d->doff = (unsigned int) doff;
391 return 1;
395 /* Callback used to save away more information about errors from the DB
396 * library. */
397 static char _db_errmsg[1024];
398 static void _db_errorCallback(const char* prefix, char* msg)
400 strcpy(_db_errmsg, msg);
404 /* make a nice exception object to raise for errors. */
405 static int makeDBError(int err)
407 char errTxt[2048]; /* really big, just in case... */
408 PyObject *errObj = NULL;
409 PyObject *errTuple = NULL;
410 int exceptionRaised = 0;
412 switch (err) {
413 case 0: /* successful, no error */ break;
415 #if (DBVER < 41)
416 case DB_INCOMPLETE:
417 #if INCOMPLETE_IS_WARNING
418 strcpy(errTxt, db_strerror(err));
419 if (_db_errmsg[0]) {
420 strcat(errTxt, " -- ");
421 strcat(errTxt, _db_errmsg);
422 _db_errmsg[0] = 0;
424 /* if Python 2.1 or better use warning framework */
425 #if PYTHON_API_VERSION >= 1010
426 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
427 #else
428 fprintf(stderr, errTxt);
429 fprintf(stderr, "\n");
430 #endif
432 #else /* do an exception instead */
433 errObj = DBIncompleteError;
434 #endif
435 break;
436 #endif /* DBVER < 41 */
438 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
439 case DB_KEYEXIST: errObj = DBKeyExistError; break;
440 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
441 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
442 case DB_NOTFOUND: errObj = DBNotFoundError; break;
443 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
444 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
445 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
446 case DB_NOSERVER: errObj = DBNoServerError; break;
447 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
448 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
449 #if (DBVER >= 33)
450 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
451 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
452 #endif
454 case EINVAL: errObj = DBInvalidArgError; break;
455 case EACCES: errObj = DBAccessError; break;
456 case ENOSPC: errObj = DBNoSpaceError; break;
457 case ENOMEM: errObj = DBNoMemoryError; break;
458 case EAGAIN: errObj = DBAgainError; break;
459 case EBUSY : errObj = DBBusyError; break;
460 case EEXIST: errObj = DBFileExistsError; break;
461 case ENOENT: errObj = DBNoSuchFileError; break;
462 case EPERM : errObj = DBPermissionsError; break;
464 default: errObj = DBError; break;
467 if (errObj != NULL) {
468 strcpy(errTxt, db_strerror(err));
469 if (_db_errmsg[0]) {
470 strcat(errTxt, " -- ");
471 strcat(errTxt, _db_errmsg);
472 _db_errmsg[0] = 0;
475 errTuple = Py_BuildValue("(is)", err, errTxt);
476 PyErr_SetObject(errObj, errTuple);
477 Py_DECREF(errTuple);
480 return ((errObj != NULL) || exceptionRaised);
485 /* set a type exception */
486 static void makeTypeError(char* expected, PyObject* found)
488 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
489 expected, found->ob_type->tp_name);
493 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
494 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
496 if (txnobj == Py_None || txnobj == NULL) {
497 *txn = NULL;
498 return 1;
500 if (DBTxnObject_Check(txnobj)) {
501 *txn = ((DBTxnObject*)txnobj)->txn;
502 return 1;
504 else
505 makeTypeError("DBTxn", txnobj);
506 return 0;
510 /* Delete a key from a database
511 Returns 0 on success, -1 on an error. */
512 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
514 int err;
516 MYDB_BEGIN_ALLOW_THREADS;
517 err = self->db->del(self->db, txn, key, 0);
518 MYDB_END_ALLOW_THREADS;
519 if (makeDBError(err)) {
520 return -1;
522 self->haveStat = 0;
523 return 0;
527 /* Store a key into a database
528 Returns 0 on success, -1 on an error. */
529 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
531 int err;
533 MYDB_BEGIN_ALLOW_THREADS;
534 err = self->db->put(self->db, txn, key, data, flags);
535 MYDB_END_ALLOW_THREADS;
536 if (makeDBError(err)) {
537 return -1;
539 self->haveStat = 0;
540 return 0;
543 /* Get a key/data pair from a cursor */
544 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
545 PyObject *args, PyObject *kwargs, char *format)
547 int err;
548 PyObject* retval = NULL;
549 DBT key, data;
550 int dlen = -1;
551 int doff = -1;
552 int flags = 0;
553 char* kwnames[] = { "flags", "dlen", "doff", NULL };
555 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
556 &flags, &dlen, &doff))
557 return NULL;
559 CHECK_CURSOR_NOT_CLOSED(self);
561 flags |= extra_flags;
562 CLEAR_DBT(key);
563 CLEAR_DBT(data);
564 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
565 /* Tell BerkeleyDB to malloc the return value (thread safe) */
566 data.flags = DB_DBT_MALLOC;
567 key.flags = DB_DBT_MALLOC;
569 if (!add_partial_dbt(&data, dlen, doff))
570 return NULL;
572 MYDB_BEGIN_ALLOW_THREADS;
573 err = self->dbc->c_get(self->dbc, &key, &data, flags);
574 MYDB_END_ALLOW_THREADS;
576 if ((err == DB_NOTFOUND) && self->mydb->getReturnsNone) {
577 Py_INCREF(Py_None);
578 retval = Py_None;
580 else if (makeDBError(err)) {
581 retval = NULL;
583 else { /* otherwise, success! */
585 /* if Recno or Queue, return the key as an Int */
586 switch (_DB_get_type(self->mydb)) {
587 case -1:
588 retval = NULL;
589 break;
591 case DB_RECNO:
592 case DB_QUEUE:
593 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
594 data.data, data.size);
595 break;
596 case DB_HASH:
597 case DB_BTREE:
598 default:
599 retval = Py_BuildValue("s#s#", key.data, key.size,
600 data.data, data.size);
601 break;
604 if (!err) {
605 FREE_DBT(key);
606 FREE_DBT(data);
608 return retval;
612 /* add an integer to a dictionary using the given name as a key */
613 static void _addIntToDict(PyObject* dict, char *name, int value)
615 PyObject* v = PyInt_FromLong((long) value);
616 if (!v || PyDict_SetItemString(dict, name, v))
617 PyErr_Clear();
619 Py_XDECREF(v);
625 /* --------------------------------------------------------------------- */
626 /* Allocators and deallocators */
628 static DBObject*
629 newDBObject(DBEnvObject* arg, int flags)
631 DBObject* self;
632 DB_ENV* db_env = NULL;
633 int err;
635 #if PYTHON_API_VERSION <= 1007
636 /* 1.5 compatibility */
637 self = PyObject_NEW(DBObject, &DB_Type);
638 #else
639 self = PyObject_New(DBObject, &DB_Type);
640 #endif
642 if (self == NULL)
643 return NULL;
645 self->haveStat = 0;
646 self->flags = 0;
647 self->setflags = 0;
648 self->myenvobj = NULL;
649 #if (DBVER >= 33)
650 self->associateCallback = NULL;
651 self->primaryDBType = 0;
652 #endif
654 /* keep a reference to our python DBEnv object */
655 if (arg) {
656 Py_INCREF(arg);
657 self->myenvobj = arg;
658 db_env = arg->db_env;
661 if (self->myenvobj)
662 self->getReturnsNone = self->myenvobj->getReturnsNone;
663 else
664 self->getReturnsNone = GET_RETURNS_NONE_DEFAULT;
666 MYDB_BEGIN_ALLOW_THREADS;
667 err = db_create(&self->db, db_env, flags);
668 self->db->set_errcall(self->db, _db_errorCallback);
669 #if (DBVER >= 33)
670 self->db->app_private = (void*)self;
671 #endif
672 MYDB_END_ALLOW_THREADS;
673 if (makeDBError(err)) {
674 if (self->myenvobj) {
675 Py_DECREF(self->myenvobj);
676 self->myenvobj = NULL;
678 self = NULL;
680 return self;
684 static void
685 DB_dealloc(DBObject* self)
687 if (self->db != NULL) {
688 /* avoid closing a DB when its DBEnv has been closed out from under
689 * it */
690 if (!self->myenvobj ||
691 (self->myenvobj && self->myenvobj->db_env))
693 MYDB_BEGIN_ALLOW_THREADS;
694 self->db->close(self->db, 0);
695 MYDB_END_ALLOW_THREADS;
696 /* if Python 2.1 or better use warning framework */
697 #if PYTHON_API_VERSION >= 1010
698 } else {
699 PyErr_Warn(PyExc_RuntimeWarning,
700 "DB could not be closed in destructor: DBEnv already closed");
701 #endif
703 self->db = NULL;
705 if (self->myenvobj) {
706 Py_DECREF(self->myenvobj);
707 self->myenvobj = NULL;
709 #if (DBVER >= 33)
710 if (self->associateCallback != NULL) {
711 Py_DECREF(self->associateCallback);
712 self->associateCallback = NULL;
714 #endif
715 #if PYTHON_API_VERSION <= 1007
716 PyMem_DEL(self);
717 #else
718 PyObject_Del(self);
719 #endif
723 static DBCursorObject*
724 newDBCursorObject(DBC* dbc, DBObject* db)
726 DBCursorObject* self;
727 #if PYTHON_API_VERSION <= 1007
728 self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
729 #else
730 self = PyObject_New(DBCursorObject, &DBCursor_Type);
731 #endif
732 if (self == NULL)
733 return NULL;
735 self->dbc = dbc;
736 self->mydb = db;
737 Py_INCREF(self->mydb);
738 return self;
742 static void
743 DBCursor_dealloc(DBCursorObject* self)
745 int err;
746 if (self->dbc != NULL) {
747 MYDB_BEGIN_ALLOW_THREADS;
748 err = self->dbc->c_close(self->dbc);
749 self->dbc = NULL;
750 MYDB_END_ALLOW_THREADS;
752 Py_XDECREF( self->mydb );
753 #if PYTHON_API_VERSION <= 1007
754 PyMem_DEL(self);
755 #else
756 PyObject_Del(self);
757 #endif
761 static DBEnvObject*
762 newDBEnvObject(int flags)
764 int err;
765 DBEnvObject* self;
766 #if PYTHON_API_VERSION <= 1007
767 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
768 #else
769 self = PyObject_New(DBEnvObject, &DBEnv_Type);
770 #endif
772 if (self == NULL)
773 return NULL;
775 self->closed = 1;
776 self->flags = flags;
777 self->getReturnsNone = GET_RETURNS_NONE_DEFAULT;
779 MYDB_BEGIN_ALLOW_THREADS;
780 err = db_env_create(&self->db_env, flags);
781 MYDB_END_ALLOW_THREADS;
782 if (makeDBError(err)) {
783 self = NULL;
785 else {
786 self->db_env->set_errcall(self->db_env, _db_errorCallback);
788 return self;
792 static void
793 DBEnv_dealloc(DBEnvObject* self)
795 if (!self->closed) {
796 MYDB_BEGIN_ALLOW_THREADS;
797 self->db_env->close(self->db_env, 0);
798 MYDB_END_ALLOW_THREADS;
800 #if PYTHON_API_VERSION <= 1007
801 PyMem_DEL(self);
802 #else
803 PyObject_Del(self);
804 #endif
808 static DBTxnObject*
809 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
811 int err;
812 DBTxnObject* self;
814 #if PYTHON_API_VERSION <= 1007
815 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
816 #else
817 self = PyObject_New(DBTxnObject, &DBTxn_Type);
818 #endif
819 if (self == NULL)
820 return NULL;
822 MYDB_BEGIN_ALLOW_THREADS;
823 #if (DBVER >= 40)
824 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
825 #else
826 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
827 #endif
828 MYDB_END_ALLOW_THREADS;
829 if (makeDBError(err)) {
830 self = NULL;
832 return self;
836 static void
837 DBTxn_dealloc(DBTxnObject* self)
839 /* XXX nothing to do for transaction objects?!? */
841 /* TODO: if it hasn't been commited, should we abort it? */
843 #if PYTHON_API_VERSION <= 1007
844 PyMem_DEL(self);
845 #else
846 PyObject_Del(self);
847 #endif
851 static DBLockObject*
852 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
853 db_lockmode_t lock_mode, int flags)
855 int err;
856 DBLockObject* self;
858 #if PYTHON_API_VERSION <= 1007
859 self = PyObject_NEW(DBLockObject, &DBLock_Type);
860 #else
861 self = PyObject_New(DBLockObject, &DBLock_Type);
862 #endif
863 if (self == NULL)
864 return NULL;
866 MYDB_BEGIN_ALLOW_THREADS;
867 #if (DBVER >= 40)
868 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
869 &self->lock);
870 #else
871 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
872 #endif
873 MYDB_END_ALLOW_THREADS;
874 if (makeDBError(err)) {
875 self = NULL;
878 return self;
882 static void
883 DBLock_dealloc(DBLockObject* self)
885 /* TODO: if it hasn't been released, should we do it? */
887 #if PYTHON_API_VERSION <= 1007
888 PyMem_DEL(self);
889 #else
890 PyObject_Del(self);
891 #endif
895 /* --------------------------------------------------------------------- */
896 /* DB methods */
898 static PyObject*
899 DB_append(DBObject* self, PyObject* args)
901 PyObject* txnobj = NULL;
902 PyObject* dataobj;
903 db_recno_t recno;
904 DBT key, data;
905 DB_TXN *txn = NULL;
907 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
908 return NULL;
910 CHECK_DB_NOT_CLOSED(self);
912 /* make a dummy key out of a recno */
913 recno = 0;
914 CLEAR_DBT(key);
915 key.data = &recno;
916 key.size = sizeof(recno);
917 key.ulen = key.size;
918 key.flags = DB_DBT_USERMEM;
920 if (!make_dbt(dataobj, &data)) return NULL;
921 if (!checkTxnObj(txnobj, &txn)) return NULL;
923 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
924 return NULL;
926 return PyInt_FromLong(recno);
930 #if (DBVER >= 33)
932 static int
933 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
934 DBT* secKey)
936 int retval = DB_DONOTINDEX;
937 DBObject* secondaryDB = (DBObject*)db->app_private;
938 PyObject* callback = secondaryDB->associateCallback;
939 int type = secondaryDB->primaryDBType;
940 PyObject* key;
941 PyObject* data;
942 PyObject* args;
943 PyObject* result;
946 if (callback != NULL) {
947 MYDB_BEGIN_BLOCK_THREADS;
949 if (type == DB_RECNO || type == DB_QUEUE) {
950 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
952 else {
953 key = PyString_FromStringAndSize(priKey->data, priKey->size);
955 data = PyString_FromStringAndSize(priData->data, priData->size);
956 args = PyTuple_New(2);
957 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
958 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
960 result = PyEval_CallObject(callback, args);
962 if (result == NULL) {
963 PyErr_Print();
965 else if (result == Py_None) {
966 retval = DB_DONOTINDEX;
968 else if (PyInt_Check(result)) {
969 retval = PyInt_AsLong(result);
971 else if (PyString_Check(result)) {
972 char* data;
973 int size;
975 CLEAR_DBT(*secKey);
976 #if PYTHON_API_VERSION <= 1007
977 /* 1.5 compatibility */
978 size = PyString_Size(result);
979 data = PyString_AsString(result);
980 #else
981 PyString_AsStringAndSize(result, &data, &size);
982 #endif
983 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
984 secKey->data = malloc(size); /* TODO, check this */
985 if (secKey->data) {
986 memcpy(secKey->data, data, size);
987 secKey->size = size;
988 retval = 0;
990 else {
991 PyErr_SetString(PyExc_MemoryError,
992 "malloc failed in _db_associateCallback");
993 PyErr_Print();
996 else {
997 PyErr_SetString(
998 PyExc_TypeError,
999 "DB associate callback should return DB_DONOTINDEX or string.");
1000 PyErr_Print();
1003 Py_DECREF(args);
1004 if (result) {
1005 Py_DECREF(result);
1008 MYDB_END_BLOCK_THREADS;
1010 return retval;
1014 static PyObject*
1015 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1017 int err, flags=0;
1018 DBObject* secondaryDB;
1019 PyObject* callback;
1020 #if (DBVER >= 41)
1021 PyObject *txnobj = NULL;
1022 DB_TXN *txn = NULL;
1023 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1024 #else
1025 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1026 #endif
1028 #if (DBVER >= 41)
1029 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1030 &secondaryDB, &callback, &flags,
1031 &txnobj)) {
1032 #else
1033 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1034 &secondaryDB, &callback, &flags)) {
1035 #endif
1036 return NULL;
1039 #if (DBVER >= 41)
1040 if (!checkTxnObj(txnobj, &txn)) return NULL;
1041 #endif
1043 CHECK_DB_NOT_CLOSED(self);
1044 if (!DBObject_Check(secondaryDB)) {
1045 makeTypeError("DB", (PyObject*)secondaryDB);
1046 return NULL;
1048 if (callback == Py_None) {
1049 callback = NULL;
1051 else if (!PyCallable_Check(callback)) {
1052 makeTypeError("Callable", callback);
1053 return NULL;
1056 /* Save a reference to the callback in the secondary DB. */
1057 if (self->associateCallback != NULL) {
1058 Py_DECREF(self->associateCallback);
1060 Py_INCREF(callback);
1061 secondaryDB->associateCallback = callback;
1062 secondaryDB->primaryDBType = _DB_get_type(self);
1064 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1065 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1066 * The global interepreter lock is not initialized until the first
1067 * thread is created using thread.start_new_thread() or fork() is
1068 * called. that would cause the ALLOW_THREADS here to segfault due
1069 * to a null pointer reference if no threads or child processes
1070 * have been created. This works around that and is a no-op if
1071 * threads have already been initialized.
1072 * (see pybsddb-users mailing list post on 2002-08-07)
1074 PyEval_InitThreads();
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 #if (DBVER >= 41)
1077 err = self->db->associate(self->db,
1078 txn,
1079 secondaryDB->db,
1080 _db_associateCallback,
1081 flags);
1082 #else
1083 err = self->db->associate(self->db,
1084 secondaryDB->db,
1085 _db_associateCallback,
1086 flags);
1087 #endif
1088 MYDB_END_ALLOW_THREADS;
1090 if (err) {
1091 Py_DECREF(self->associateCallback);
1092 self->associateCallback = NULL;
1093 secondaryDB->primaryDBType = 0;
1096 RETURN_IF_ERR();
1097 RETURN_NONE();
1101 #endif
1104 static PyObject*
1105 DB_close(DBObject* self, PyObject* args)
1107 int err, flags=0;
1108 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1109 return NULL;
1110 if (self->db != NULL) {
1111 if (self->myenvobj)
1112 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1113 MYDB_BEGIN_ALLOW_THREADS;
1114 err = self->db->close(self->db, flags);
1115 MYDB_END_ALLOW_THREADS;
1116 self->db = NULL;
1117 RETURN_IF_ERR();
1119 RETURN_NONE();
1123 #if (DBVER >= 32)
1124 static PyObject*
1125 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1127 int err, flags=0, type;
1128 PyObject* txnobj = NULL;
1129 PyObject* retval = NULL;
1130 DBT key, data;
1131 DB_TXN *txn = NULL;
1132 char* kwnames[] = { "txn", "flags", NULL };
1134 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1135 &txnobj, &flags))
1136 return NULL;
1138 CHECK_DB_NOT_CLOSED(self);
1139 type = _DB_get_type(self);
1140 if (type == -1)
1141 return NULL;
1142 if (type != DB_QUEUE) {
1143 PyErr_SetString(PyExc_TypeError,
1144 "Consume methods only allowed for Queue DB's");
1145 return NULL;
1147 if (!checkTxnObj(txnobj, &txn))
1148 return NULL;
1150 CLEAR_DBT(key);
1151 CLEAR_DBT(data);
1152 if (CHECK_DBFLAG(self, DB_THREAD)) {
1153 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1154 data.flags = DB_DBT_MALLOC;
1155 key.flags = DB_DBT_MALLOC;
1158 MYDB_BEGIN_ALLOW_THREADS;
1159 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1160 MYDB_END_ALLOW_THREADS;
1162 if ((err == DB_NOTFOUND) && self->getReturnsNone) {
1163 err = 0;
1164 Py_INCREF(Py_None);
1165 retval = Py_None;
1167 else if (!err) {
1168 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1169 data.size);
1170 FREE_DBT(key);
1171 FREE_DBT(data);
1174 RETURN_IF_ERR();
1175 return retval;
1178 static PyObject*
1179 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1181 return _DB_consume(self, args, kwargs, DB_CONSUME);
1184 static PyObject*
1185 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1186 int consume_flag)
1188 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1190 #endif
1194 static PyObject*
1195 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1197 int err, flags=0;
1198 DBC* dbc;
1199 PyObject* txnobj = NULL;
1200 DB_TXN *txn = NULL;
1201 char* kwnames[] = { "txn", "flags", NULL };
1203 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1204 &txnobj, &flags))
1205 return NULL;
1206 CHECK_DB_NOT_CLOSED(self);
1207 if (!checkTxnObj(txnobj, &txn))
1208 return NULL;
1210 MYDB_BEGIN_ALLOW_THREADS;
1211 err = self->db->cursor(self->db, txn, &dbc, flags);
1212 MYDB_END_ALLOW_THREADS;
1213 RETURN_IF_ERR();
1214 return (PyObject*) newDBCursorObject(dbc, self);
1218 static PyObject*
1219 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1221 PyObject* txnobj = NULL;
1222 int flags = 0;
1223 PyObject* keyobj;
1224 DBT key;
1225 DB_TXN *txn = NULL;
1226 char* kwnames[] = { "key", "txn", "flags", NULL };
1228 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1229 &keyobj, &txnobj, &flags))
1230 return NULL;
1231 CHECK_DB_NOT_CLOSED(self);
1232 if (!make_key_dbt(self, keyobj, &key, NULL))
1233 return NULL;
1234 if (!checkTxnObj(txnobj, &txn))
1235 return NULL;
1237 if (-1 == _DB_delete(self, txn, &key, 0))
1238 return NULL;
1240 FREE_DBT(key);
1241 RETURN_NONE();
1245 static PyObject*
1246 DB_fd(DBObject* self, PyObject* args)
1248 int err, the_fd;
1250 if (!PyArg_ParseTuple(args,":fd"))
1251 return NULL;
1252 CHECK_DB_NOT_CLOSED(self);
1254 MYDB_BEGIN_ALLOW_THREADS;
1255 err = self->db->fd(self->db, &the_fd);
1256 MYDB_END_ALLOW_THREADS;
1257 RETURN_IF_ERR();
1258 return PyInt_FromLong(the_fd);
1262 static PyObject*
1263 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1265 int err, flags=0;
1266 PyObject* txnobj = NULL;
1267 PyObject* keyobj;
1268 PyObject* dfltobj = NULL;
1269 PyObject* retval = NULL;
1270 int dlen = -1;
1271 int doff = -1;
1272 DBT key, data;
1273 DB_TXN *txn = NULL;
1274 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1276 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1277 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1278 &doff))
1279 return NULL;
1281 CHECK_DB_NOT_CLOSED(self);
1282 if (!make_key_dbt(self, keyobj, &key, &flags))
1283 return NULL;
1284 if (!checkTxnObj(txnobj, &txn))
1285 return NULL;
1287 CLEAR_DBT(data);
1288 if (CHECK_DBFLAG(self, DB_THREAD)) {
1289 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1290 data.flags = DB_DBT_MALLOC;
1292 if (!add_partial_dbt(&data, dlen, doff))
1293 return NULL;
1295 MYDB_BEGIN_ALLOW_THREADS;
1296 err = self->db->get(self->db, txn, &key, &data, flags);
1297 MYDB_END_ALLOW_THREADS;
1299 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1300 err = 0;
1301 Py_INCREF(dfltobj);
1302 retval = dfltobj;
1304 else if ((err == DB_NOTFOUND) && self->getReturnsNone) {
1305 err = 0;
1306 Py_INCREF(Py_None);
1307 retval = Py_None;
1309 else if (!err) {
1310 if (flags & DB_SET_RECNO) /* return both key and data */
1311 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1312 data.size);
1313 else /* return just the data */
1314 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1315 FREE_DBT(key);
1316 FREE_DBT(data);
1319 RETURN_IF_ERR();
1320 return retval;
1324 /* Return size of entry */
1325 static PyObject*
1326 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1328 int err, flags=0;
1329 PyObject* txnobj = NULL;
1330 PyObject* keyobj;
1331 PyObject* retval = NULL;
1332 DBT key, data;
1333 DB_TXN *txn = NULL;
1334 char* kwnames[] = { "key", "txn", NULL };
1336 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1337 &keyobj, &txnobj))
1338 return NULL;
1339 CHECK_DB_NOT_CLOSED(self);
1340 if (!make_key_dbt(self, keyobj, &key, &flags))
1341 return NULL;
1342 if (!checkTxnObj(txnobj, &txn))
1343 return NULL;
1344 CLEAR_DBT(data);
1346 /* We don't allocate any memory, forcing a ENOMEM error and thus
1347 getting the record size. */
1348 data.flags = DB_DBT_USERMEM;
1349 data.ulen = 0;
1350 MYDB_BEGIN_ALLOW_THREADS;
1351 err = self->db->get(self->db, txn, &key, &data, flags);
1352 MYDB_END_ALLOW_THREADS;
1353 if (err == ENOMEM) {
1354 retval = PyInt_FromLong((long)data.size);
1355 err = 0;
1358 FREE_DBT(key);
1359 FREE_DBT(data);
1360 RETURN_IF_ERR();
1361 return retval;
1365 static PyObject*
1366 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1368 int err, flags=0;
1369 PyObject* txnobj = NULL;
1370 PyObject* keyobj;
1371 PyObject* dataobj;
1372 PyObject* retval = NULL;
1373 DBT key, data;
1374 DB_TXN *txn = NULL;
1375 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1378 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1379 &keyobj, &dataobj, &txnobj, &flags))
1380 return NULL;
1382 CHECK_DB_NOT_CLOSED(self);
1383 if (!make_key_dbt(self, keyobj, &key, NULL))
1384 return NULL;
1385 if (!make_dbt(dataobj, &data))
1386 return NULL;
1387 if (!checkTxnObj(txnobj, &txn))
1388 return NULL;
1390 flags |= DB_GET_BOTH;
1392 if (CHECK_DBFLAG(self, DB_THREAD)) {
1393 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1394 data.flags = DB_DBT_MALLOC;
1395 /* TODO: Is this flag needed? We're passing a data object that should
1396 match what's in the DB, so there should be no need to malloc.
1397 We run the risk of freeing something twice! Check this. */
1400 MYDB_BEGIN_ALLOW_THREADS;
1401 err = self->db->get(self->db, txn, &key, &data, flags);
1402 MYDB_END_ALLOW_THREADS;
1404 if ((err == DB_NOTFOUND) && self->getReturnsNone) {
1405 err = 0;
1406 Py_INCREF(Py_None);
1407 retval = Py_None;
1409 else if (!err) {
1410 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1411 FREE_DBT(data); /* Only if retrieval was successful */
1414 FREE_DBT(key);
1415 RETURN_IF_ERR();
1416 return retval;
1420 static PyObject*
1421 DB_get_byteswapped(DBObject* self, PyObject* args)
1423 #if (DBVER >= 33)
1424 int err = 0;
1425 #endif
1426 int retval = -1;
1428 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1429 return NULL;
1430 CHECK_DB_NOT_CLOSED(self);
1432 #if (DBVER >= 33)
1433 MYDB_BEGIN_ALLOW_THREADS;
1434 err = self->db->get_byteswapped(self->db, &retval);
1435 MYDB_END_ALLOW_THREADS;
1436 RETURN_IF_ERR();
1437 #else
1438 MYDB_BEGIN_ALLOW_THREADS;
1439 retval = self->db->get_byteswapped(self->db);
1440 MYDB_END_ALLOW_THREADS;
1441 #endif
1442 return PyInt_FromLong(retval);
1446 static PyObject*
1447 DB_get_type(DBObject* self, PyObject* args)
1449 int type;
1451 if (!PyArg_ParseTuple(args,":get_type"))
1452 return NULL;
1453 CHECK_DB_NOT_CLOSED(self);
1455 MYDB_BEGIN_ALLOW_THREADS;
1456 type = _DB_get_type(self);
1457 MYDB_END_ALLOW_THREADS;
1458 if (type == -1)
1459 return NULL;
1460 return PyInt_FromLong(type);
1464 static PyObject*
1465 DB_join(DBObject* self, PyObject* args)
1467 int err, flags=0;
1468 int length, x;
1469 PyObject* cursorsObj;
1470 DBC** cursors;
1471 DBC* dbc;
1474 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1475 return NULL;
1477 CHECK_DB_NOT_CLOSED(self);
1479 if (!PySequence_Check(cursorsObj)) {
1480 PyErr_SetString(PyExc_TypeError,
1481 "Sequence of DBCursor objects expected");
1482 return NULL;
1485 length = PyObject_Length(cursorsObj);
1486 cursors = malloc((length+1) * sizeof(DBC*));
1487 cursors[length] = NULL;
1488 for (x=0; x<length; x++) {
1489 PyObject* item = PySequence_GetItem(cursorsObj, x);
1490 if (!DBCursorObject_Check(item)) {
1491 PyErr_SetString(PyExc_TypeError,
1492 "Sequence of DBCursor objects expected");
1493 free(cursors);
1494 return NULL;
1496 cursors[x] = ((DBCursorObject*)item)->dbc;
1499 MYDB_BEGIN_ALLOW_THREADS;
1500 err = self->db->join(self->db, cursors, &dbc, flags);
1501 MYDB_END_ALLOW_THREADS;
1502 free(cursors);
1503 RETURN_IF_ERR();
1505 return (PyObject*) newDBCursorObject(dbc, self);
1509 static PyObject*
1510 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1512 int err, flags=0;
1513 PyObject* txnobj = NULL;
1514 PyObject* keyobj;
1515 DBT key;
1516 DB_TXN *txn = NULL;
1517 DB_KEY_RANGE range;
1518 char* kwnames[] = { "key", "txn", "flags", NULL };
1520 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1521 &keyobj, &txnobj, &flags))
1522 return NULL;
1523 CHECK_DB_NOT_CLOSED(self);
1524 if (!make_dbt(keyobj, &key))
1525 /* BTree only, don't need to allow for an int key */
1526 return NULL;
1527 if (!checkTxnObj(txnobj, &txn))
1528 return NULL;
1530 MYDB_BEGIN_ALLOW_THREADS;
1531 err = self->db->key_range(self->db, txn, &key, &range, flags);
1532 MYDB_END_ALLOW_THREADS;
1534 RETURN_IF_ERR();
1535 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1539 static PyObject*
1540 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1542 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1543 char* filename = NULL;
1544 char* dbname = NULL;
1545 #if (DBVER >= 41)
1546 PyObject *txnobj = NULL;
1547 DB_TXN *txn = NULL;
1548 /* with dbname */
1549 char* kwnames[] = {
1550 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1551 /* without dbname */
1552 char* kwnames_basic[] = {
1553 "filename", "dbtype", "flags", "mode", "txn", NULL};
1554 #else
1555 /* with dbname */
1556 char* kwnames[] = {
1557 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1558 /* without dbname */
1559 char* kwnames_basic[] = {
1560 "filename", "dbtype", "flags", "mode", NULL};
1561 #endif
1563 #if (DBVER >= 41)
1564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1565 &filename, &dbname, &type, &flags, &mode,
1566 &txnobj))
1567 #else
1568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1569 &filename, &dbname, &type, &flags,
1570 &mode))
1571 #endif
1573 PyErr_Clear();
1574 type = DB_UNKNOWN; flags = 0; mode = 0660;
1575 filename = NULL; dbname = NULL;
1576 #if (DBVER >= 41)
1577 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1578 kwnames_basic,
1579 &filename, &type, &flags, &mode,
1580 &txnobj))
1581 return NULL;
1582 #else
1583 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1584 kwnames_basic,
1585 &filename, &type, &flags, &mode))
1586 return NULL;
1587 #endif
1590 #if (DBVER >= 41)
1591 if (!checkTxnObj(txnobj, &txn)) return NULL;
1592 #endif
1594 if (NULL == self->db) {
1595 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1596 "Cannot call open() twice for DB object"));
1597 return NULL;
1600 #if 0 && (DBVER >= 41)
1601 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1602 && (self->myenvobj->flags & DB_INIT_TXN))
1604 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1605 * explicitly passed) but we are in a transaction ready environment:
1606 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1607 * to work on BerkeleyDB 4.1 without needing to modify their
1608 * DBEnv or DB open calls.
1609 * TODO make this behaviour of the library configurable.
1611 flags |= DB_AUTO_COMMIT;
1613 #endif
1615 MYDB_BEGIN_ALLOW_THREADS;
1616 #if (DBVER >= 41)
1617 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1618 #else
1619 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1620 #endif
1621 MYDB_END_ALLOW_THREADS;
1622 if (makeDBError(err)) {
1623 self->db = NULL;
1624 return NULL;
1627 self->flags = flags;
1628 RETURN_NONE();
1632 static PyObject*
1633 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1635 int flags=0;
1636 PyObject* txnobj = NULL;
1637 int dlen = -1;
1638 int doff = -1;
1639 PyObject* keyobj, *dataobj, *retval;
1640 DBT key, data;
1641 DB_TXN *txn = NULL;
1642 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1644 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1645 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1646 return NULL;
1648 CHECK_DB_NOT_CLOSED(self);
1649 if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
1650 if (!make_dbt(dataobj, &data)) return NULL;
1651 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
1652 if (!checkTxnObj(txnobj, &txn)) return NULL;
1654 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1655 FREE_DBT(key);
1656 return NULL;
1659 if (flags & DB_APPEND)
1660 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1661 else {
1662 retval = Py_None;
1663 Py_INCREF(retval);
1665 FREE_DBT(key);
1666 return retval;
1671 static PyObject*
1672 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1674 char* filename;
1675 char* database = NULL;
1676 int err, flags=0;
1677 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1680 &filename, &database, &flags))
1681 return NULL;
1682 CHECK_DB_NOT_CLOSED(self);
1684 MYDB_BEGIN_ALLOW_THREADS;
1685 err = self->db->remove(self->db, filename, database, flags);
1686 MYDB_END_ALLOW_THREADS;
1687 RETURN_IF_ERR();
1688 RETURN_NONE();
1693 static PyObject*
1694 DB_rename(DBObject* self, PyObject* args)
1696 char* filename;
1697 char* database;
1698 char* newname;
1699 int err, flags=0;
1701 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1702 &flags))
1703 return NULL;
1704 CHECK_DB_NOT_CLOSED(self);
1706 MYDB_BEGIN_ALLOW_THREADS;
1707 err = self->db->rename(self->db, filename, database, newname, flags);
1708 MYDB_END_ALLOW_THREADS;
1709 RETURN_IF_ERR();
1710 RETURN_NONE();
1714 static PyObject*
1715 DB_set_bt_minkey(DBObject* self, PyObject* args)
1717 int err, minkey;
1719 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1720 return NULL;
1721 CHECK_DB_NOT_CLOSED(self);
1723 MYDB_BEGIN_ALLOW_THREADS;
1724 err = self->db->set_bt_minkey(self->db, minkey);
1725 MYDB_END_ALLOW_THREADS;
1726 RETURN_IF_ERR();
1727 RETURN_NONE();
1731 static PyObject*
1732 DB_set_cachesize(DBObject* self, PyObject* args)
1734 int err;
1735 int gbytes = 0, bytes = 0, ncache = 0;
1737 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1738 &gbytes,&bytes,&ncache))
1739 return NULL;
1740 CHECK_DB_NOT_CLOSED(self);
1742 MYDB_BEGIN_ALLOW_THREADS;
1743 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1744 MYDB_END_ALLOW_THREADS;
1745 RETURN_IF_ERR();
1746 RETURN_NONE();
1750 static PyObject*
1751 DB_set_flags(DBObject* self, PyObject* args)
1753 int err, flags;
1755 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1759 MYDB_BEGIN_ALLOW_THREADS;
1760 err = self->db->set_flags(self->db, flags);
1761 MYDB_END_ALLOW_THREADS;
1762 RETURN_IF_ERR();
1764 self->setflags |= flags;
1765 RETURN_NONE();
1769 static PyObject*
1770 DB_set_h_ffactor(DBObject* self, PyObject* args)
1772 int err, ffactor;
1774 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1775 return NULL;
1776 CHECK_DB_NOT_CLOSED(self);
1778 MYDB_BEGIN_ALLOW_THREADS;
1779 err = self->db->set_h_ffactor(self->db, ffactor);
1780 MYDB_END_ALLOW_THREADS;
1781 RETURN_IF_ERR();
1782 RETURN_NONE();
1786 static PyObject*
1787 DB_set_h_nelem(DBObject* self, PyObject* args)
1789 int err, nelem;
1791 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1792 return NULL;
1793 CHECK_DB_NOT_CLOSED(self);
1795 MYDB_BEGIN_ALLOW_THREADS;
1796 err = self->db->set_h_nelem(self->db, nelem);
1797 MYDB_END_ALLOW_THREADS;
1798 RETURN_IF_ERR();
1799 RETURN_NONE();
1803 static PyObject*
1804 DB_set_lorder(DBObject* self, PyObject* args)
1806 int err, lorder;
1808 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1809 return NULL;
1810 CHECK_DB_NOT_CLOSED(self);
1812 MYDB_BEGIN_ALLOW_THREADS;
1813 err = self->db->set_lorder(self->db, lorder);
1814 MYDB_END_ALLOW_THREADS;
1815 RETURN_IF_ERR();
1816 RETURN_NONE();
1820 static PyObject*
1821 DB_set_pagesize(DBObject* self, PyObject* args)
1823 int err, pagesize;
1825 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1826 return NULL;
1827 CHECK_DB_NOT_CLOSED(self);
1829 MYDB_BEGIN_ALLOW_THREADS;
1830 err = self->db->set_pagesize(self->db, pagesize);
1831 MYDB_END_ALLOW_THREADS;
1832 RETURN_IF_ERR();
1833 RETURN_NONE();
1837 static PyObject*
1838 DB_set_re_delim(DBObject* self, PyObject* args)
1840 int err;
1841 char delim;
1843 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1844 PyErr_Clear();
1845 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1846 return NULL;
1849 CHECK_DB_NOT_CLOSED(self);
1851 MYDB_BEGIN_ALLOW_THREADS;
1852 err = self->db->set_re_delim(self->db, delim);
1853 MYDB_END_ALLOW_THREADS;
1854 RETURN_IF_ERR();
1855 RETURN_NONE();
1858 static PyObject*
1859 DB_set_re_len(DBObject* self, PyObject* args)
1861 int err, len;
1863 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1864 return NULL;
1865 CHECK_DB_NOT_CLOSED(self);
1867 MYDB_BEGIN_ALLOW_THREADS;
1868 err = self->db->set_re_len(self->db, len);
1869 MYDB_END_ALLOW_THREADS;
1870 RETURN_IF_ERR();
1871 RETURN_NONE();
1875 static PyObject*
1876 DB_set_re_pad(DBObject* self, PyObject* args)
1878 int err;
1879 char pad;
1881 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1882 PyErr_Clear();
1883 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1884 return NULL;
1886 CHECK_DB_NOT_CLOSED(self);
1888 MYDB_BEGIN_ALLOW_THREADS;
1889 err = self->db->set_re_pad(self->db, pad);
1890 MYDB_END_ALLOW_THREADS;
1891 RETURN_IF_ERR();
1892 RETURN_NONE();
1896 static PyObject*
1897 DB_set_re_source(DBObject* self, PyObject* args)
1899 int err;
1900 char *re_source;
1902 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1903 return NULL;
1904 CHECK_DB_NOT_CLOSED(self);
1906 MYDB_BEGIN_ALLOW_THREADS;
1907 err = self->db->set_re_source(self->db, re_source);
1908 MYDB_END_ALLOW_THREADS;
1909 RETURN_IF_ERR();
1910 RETURN_NONE();
1914 #if (DBVER >= 32)
1915 static PyObject*
1916 DB_set_q_extentsize(DBObject* self, PyObject* args)
1918 int err;
1919 int extentsize;
1921 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
1922 return NULL;
1923 CHECK_DB_NOT_CLOSED(self);
1925 MYDB_BEGIN_ALLOW_THREADS;
1926 err = self->db->set_q_extentsize(self->db, extentsize);
1927 MYDB_END_ALLOW_THREADS;
1928 RETURN_IF_ERR();
1929 RETURN_NONE();
1931 #endif
1933 static PyObject*
1934 DB_stat(DBObject* self, PyObject* args)
1936 int err, flags = 0, type;
1937 void* sp;
1938 PyObject* d;
1941 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
1942 return NULL;
1943 CHECK_DB_NOT_CLOSED(self);
1945 MYDB_BEGIN_ALLOW_THREADS;
1946 #if (DBVER >= 33)
1947 err = self->db->stat(self->db, &sp, flags);
1948 #else
1949 err = self->db->stat(self->db, &sp, NULL, flags);
1950 #endif
1951 MYDB_END_ALLOW_THREADS;
1952 RETURN_IF_ERR();
1954 self->haveStat = 1;
1956 /* Turn the stat structure into a dictionary */
1957 type = _DB_get_type(self);
1958 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
1959 free(sp);
1960 return NULL;
1963 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
1964 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
1965 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
1967 switch (type) {
1968 case DB_HASH:
1969 MAKE_HASH_ENTRY(magic);
1970 MAKE_HASH_ENTRY(version);
1971 MAKE_HASH_ENTRY(nkeys);
1972 MAKE_HASH_ENTRY(ndata);
1973 MAKE_HASH_ENTRY(pagesize);
1974 #if (DBVER < 41)
1975 MAKE_HASH_ENTRY(nelem);
1976 #endif
1977 MAKE_HASH_ENTRY(ffactor);
1978 MAKE_HASH_ENTRY(buckets);
1979 MAKE_HASH_ENTRY(free);
1980 MAKE_HASH_ENTRY(bfree);
1981 MAKE_HASH_ENTRY(bigpages);
1982 MAKE_HASH_ENTRY(big_bfree);
1983 MAKE_HASH_ENTRY(overflows);
1984 MAKE_HASH_ENTRY(ovfl_free);
1985 MAKE_HASH_ENTRY(dup);
1986 MAKE_HASH_ENTRY(dup_free);
1987 break;
1989 case DB_BTREE:
1990 case DB_RECNO:
1991 MAKE_BT_ENTRY(magic);
1992 MAKE_BT_ENTRY(version);
1993 MAKE_BT_ENTRY(nkeys);
1994 MAKE_BT_ENTRY(ndata);
1995 MAKE_BT_ENTRY(pagesize);
1996 MAKE_BT_ENTRY(minkey);
1997 MAKE_BT_ENTRY(re_len);
1998 MAKE_BT_ENTRY(re_pad);
1999 MAKE_BT_ENTRY(levels);
2000 MAKE_BT_ENTRY(int_pg);
2001 MAKE_BT_ENTRY(leaf_pg);
2002 MAKE_BT_ENTRY(dup_pg);
2003 MAKE_BT_ENTRY(over_pg);
2004 MAKE_BT_ENTRY(free);
2005 MAKE_BT_ENTRY(int_pgfree);
2006 MAKE_BT_ENTRY(leaf_pgfree);
2007 MAKE_BT_ENTRY(dup_pgfree);
2008 MAKE_BT_ENTRY(over_pgfree);
2009 break;
2011 case DB_QUEUE:
2012 MAKE_QUEUE_ENTRY(magic);
2013 MAKE_QUEUE_ENTRY(version);
2014 MAKE_QUEUE_ENTRY(nkeys);
2015 MAKE_QUEUE_ENTRY(ndata);
2016 MAKE_QUEUE_ENTRY(pagesize);
2017 MAKE_QUEUE_ENTRY(pages);
2018 MAKE_QUEUE_ENTRY(re_len);
2019 MAKE_QUEUE_ENTRY(re_pad);
2020 MAKE_QUEUE_ENTRY(pgfree);
2021 #if (DBVER == 31)
2022 MAKE_QUEUE_ENTRY(start);
2023 #endif
2024 MAKE_QUEUE_ENTRY(first_recno);
2025 MAKE_QUEUE_ENTRY(cur_recno);
2026 break;
2028 default:
2029 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2030 Py_DECREF(d);
2031 d = NULL;
2034 #undef MAKE_HASH_ENTRY
2035 #undef MAKE_BT_ENTRY
2036 #undef MAKE_QUEUE_ENTRY
2038 free(sp);
2039 return d;
2042 static PyObject*
2043 DB_sync(DBObject* self, PyObject* args)
2045 int err;
2046 int flags = 0;
2048 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2049 return NULL;
2050 CHECK_DB_NOT_CLOSED(self);
2052 MYDB_BEGIN_ALLOW_THREADS;
2053 err = self->db->sync(self->db, flags);
2054 MYDB_END_ALLOW_THREADS;
2055 RETURN_IF_ERR();
2056 RETURN_NONE();
2060 #if (DBVER >= 33)
2061 static PyObject*
2062 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2064 int err, flags=0;
2065 u_int32_t count=0;
2066 PyObject* txnobj = NULL;
2067 DB_TXN *txn = NULL;
2068 char* kwnames[] = { "txn", "flags", NULL };
2070 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2071 &txnobj, &flags))
2072 return NULL;
2073 CHECK_DB_NOT_CLOSED(self);
2074 if (!checkTxnObj(txnobj, &txn))
2075 return NULL;
2077 MYDB_BEGIN_ALLOW_THREADS;
2078 err = self->db->truncate(self->db, txn, &count, flags);
2079 MYDB_END_ALLOW_THREADS;
2080 RETURN_IF_ERR();
2081 return PyInt_FromLong(count);
2083 #endif
2086 static PyObject*
2087 DB_upgrade(DBObject* self, PyObject* args)
2089 int err, flags=0;
2090 char *filename;
2092 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2093 return NULL;
2094 CHECK_DB_NOT_CLOSED(self);
2096 MYDB_BEGIN_ALLOW_THREADS;
2097 err = self->db->upgrade(self->db, filename, flags);
2098 MYDB_END_ALLOW_THREADS;
2099 RETURN_IF_ERR();
2100 RETURN_NONE();
2104 static PyObject*
2105 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2107 int err, flags=0;
2108 char* fileName;
2109 char* dbName=NULL;
2110 char* outFileName=NULL;
2111 FILE* outFile=NULL;
2112 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2114 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2115 &fileName, &dbName, &outFileName, &flags))
2116 return NULL;
2118 CHECK_DB_NOT_CLOSED(self);
2119 if (outFileName)
2120 outFile = fopen(outFileName, "w");
2122 MYDB_BEGIN_ALLOW_THREADS;
2123 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2124 MYDB_END_ALLOW_THREADS;
2125 if (outFileName)
2126 fclose(outFile);
2127 RETURN_IF_ERR();
2128 RETURN_NONE();
2132 static PyObject*
2133 DB_set_get_returns_none(DBObject* self, PyObject* args)
2135 int flags=0;
2136 int oldValue;
2138 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2139 return NULL;
2140 CHECK_DB_NOT_CLOSED(self);
2142 oldValue = self->getReturnsNone;
2143 self->getReturnsNone = flags;
2144 return PyInt_FromLong(oldValue);
2147 #if (DBVER >= 41)
2148 static PyObject*
2149 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2151 int err;
2152 u_int32_t flags=0;
2153 char *passwd = NULL;
2154 char* kwnames[] = { "passwd", "flags", NULL };
2156 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2157 &passwd, &flags)) {
2158 return NULL;
2161 MYDB_BEGIN_ALLOW_THREADS;
2162 err = self->db->set_encrypt(self->db, passwd, flags);
2163 MYDB_END_ALLOW_THREADS;
2165 RETURN_IF_ERR();
2166 RETURN_NONE();
2168 #endif /* DBVER >= 41 */
2171 /*-------------------------------------------------------------- */
2172 /* Mapping and Dictionary-like access routines */
2174 int DB_length(DBObject* self)
2176 int err;
2177 long size = 0;
2178 int flags = 0;
2179 void* sp;
2181 if (self->db == NULL) {
2182 PyErr_SetObject(DBError,
2183 Py_BuildValue("(is)", 0, "DB object has been closed"));
2184 return -1;
2187 if (self->haveStat) { /* Has the stat function been called recently? If
2188 so, we can use the cached value. */
2189 flags = DB_CACHED_COUNTS;
2192 MYDB_BEGIN_ALLOW_THREADS;
2193 #if (DBVER >= 33)
2194 err = self->db->stat(self->db, &sp, flags);
2195 #else
2196 err = self->db->stat(self->db, &sp, NULL, flags);
2197 #endif
2198 MYDB_END_ALLOW_THREADS;
2200 if (err)
2201 return -1;
2203 self->haveStat = 1;
2205 /* All the stat structures have matching fields upto the ndata field,
2206 so we can use any of them for the type cast */
2207 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2208 free(sp);
2209 return size;
2213 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2215 int err;
2216 PyObject* retval;
2217 DBT key;
2218 DBT data;
2220 CHECK_DB_NOT_CLOSED(self);
2221 if (!make_key_dbt(self, keyobj, &key, NULL))
2222 return NULL;
2224 CLEAR_DBT(data);
2225 if (CHECK_DBFLAG(self, DB_THREAD)) {
2226 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2227 data.flags = DB_DBT_MALLOC;
2229 MYDB_BEGIN_ALLOW_THREADS;
2230 err = self->db->get(self->db, NULL, &key, &data, 0);
2231 MYDB_END_ALLOW_THREADS;
2232 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2233 PyErr_SetObject(PyExc_KeyError, keyobj);
2234 retval = NULL;
2236 else if (makeDBError(err)) {
2237 retval = NULL;
2239 else {
2240 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2241 FREE_DBT(data);
2244 FREE_DBT(key);
2245 return retval;
2249 static int
2250 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2252 DBT key, data;
2253 int retval;
2254 int flags = 0;
2256 if (self->db == NULL) {
2257 PyErr_SetObject(DBError,
2258 Py_BuildValue("(is)", 0, "DB object has been closed"));
2259 return -1;
2262 if (!make_key_dbt(self, keyobj, &key, NULL))
2263 return -1;
2265 if (dataobj != NULL) {
2266 if (!make_dbt(dataobj, &data))
2267 retval = -1;
2268 else {
2269 if (self->setflags & (DB_DUP|DB_DUPSORT))
2270 /* dictionaries shouldn't have duplicate keys */
2271 flags = DB_NOOVERWRITE;
2272 retval = _DB_put(self, NULL, &key, &data, flags);
2274 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2275 /* try deleting any old record that matches and then PUT it
2276 * again... */
2277 _DB_delete(self, NULL, &key, 0);
2278 PyErr_Clear();
2279 retval = _DB_put(self, NULL, &key, &data, flags);
2283 else {
2284 /* dataobj == NULL, so delete the key */
2285 retval = _DB_delete(self, NULL, &key, 0);
2287 FREE_DBT(key);
2288 return retval;
2292 static PyObject*
2293 DB_has_key(DBObject* self, PyObject* args)
2295 int err;
2296 PyObject* keyobj;
2297 DBT key, data;
2298 PyObject* txnobj = NULL;
2299 DB_TXN *txn = NULL;
2301 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2302 return NULL;
2303 CHECK_DB_NOT_CLOSED(self);
2304 if (!make_key_dbt(self, keyobj, &key, NULL))
2305 return NULL;
2306 if (!checkTxnObj(txnobj, &txn))
2307 return NULL;
2309 /* This causes ENOMEM to be returned when the db has the key because
2310 it has a record but can't allocate a buffer for the data. This saves
2311 having to deal with data we won't be using.
2313 CLEAR_DBT(data);
2314 data.flags = DB_DBT_USERMEM;
2316 MYDB_BEGIN_ALLOW_THREADS;
2317 err = self->db->get(self->db, NULL, &key, &data, 0);
2318 MYDB_END_ALLOW_THREADS;
2319 FREE_DBT(key);
2320 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2324 #define _KEYS_LIST 1
2325 #define _VALUES_LIST 2
2326 #define _ITEMS_LIST 3
2328 static PyObject*
2329 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2331 int err, dbtype;
2332 DBT key;
2333 DBT data;
2334 DBC *cursor;
2335 PyObject* list;
2336 PyObject* item = NULL;
2338 CHECK_DB_NOT_CLOSED(self);
2339 CLEAR_DBT(key);
2340 CLEAR_DBT(data);
2342 dbtype = _DB_get_type(self);
2343 if (dbtype == -1)
2344 return NULL;
2346 list = PyList_New(0);
2347 if (list == NULL) {
2348 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2349 return NULL;
2352 /* get a cursor */
2353 MYDB_BEGIN_ALLOW_THREADS;
2354 err = self->db->cursor(self->db, NULL, &cursor, 0);
2355 MYDB_END_ALLOW_THREADS;
2356 RETURN_IF_ERR();
2358 if (CHECK_DBFLAG(self, DB_THREAD)) {
2359 key.flags = DB_DBT_REALLOC;
2360 data.flags = DB_DBT_REALLOC;
2363 while (1) { /* use the cursor to traverse the DB, collecting items */
2364 MYDB_BEGIN_ALLOW_THREADS;
2365 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2366 MYDB_END_ALLOW_THREADS;
2368 if (err) {
2369 /* for any error, break out of the loop */
2370 break;
2373 switch (type) {
2374 case _KEYS_LIST:
2375 switch(dbtype) {
2376 case DB_BTREE:
2377 case DB_HASH:
2378 default:
2379 item = PyString_FromStringAndSize((char*)key.data, key.size);
2380 break;
2381 case DB_RECNO:
2382 case DB_QUEUE:
2383 item = PyInt_FromLong(*((db_recno_t*)key.data));
2384 break;
2386 break;
2388 case _VALUES_LIST:
2389 item = PyString_FromStringAndSize((char*)data.data, data.size);
2390 break;
2392 case _ITEMS_LIST:
2393 switch(dbtype) {
2394 case DB_BTREE:
2395 case DB_HASH:
2396 default:
2397 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2398 data.size);
2399 break;
2400 case DB_RECNO:
2401 case DB_QUEUE:
2402 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2403 data.data, data.size);
2404 break;
2406 break;
2408 if (item == NULL) {
2409 Py_DECREF(list);
2410 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2411 list = NULL;
2412 goto done;
2414 PyList_Append(list, item);
2415 Py_DECREF(item);
2418 /* DB_NOTFOUND is okay, it just means we got to the end */
2419 if (err != DB_NOTFOUND && makeDBError(err)) {
2420 Py_DECREF(list);
2421 list = NULL;
2424 done:
2425 FREE_DBT(key);
2426 FREE_DBT(data);
2427 MYDB_BEGIN_ALLOW_THREADS;
2428 cursor->c_close(cursor);
2429 MYDB_END_ALLOW_THREADS;
2430 return list;
2434 static PyObject*
2435 DB_keys(DBObject* self, PyObject* args)
2437 PyObject* txnobj = NULL;
2438 DB_TXN *txn = NULL;
2440 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2441 return NULL;
2442 if (!checkTxnObj(txnobj, &txn))
2443 return NULL;
2444 return _DB_make_list(self, txn, _KEYS_LIST);
2448 static PyObject*
2449 DB_items(DBObject* self, PyObject* args)
2451 PyObject* txnobj = NULL;
2452 DB_TXN *txn = NULL;
2454 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2455 return NULL;
2456 if (!checkTxnObj(txnobj, &txn))
2457 return NULL;
2458 return _DB_make_list(self, txn, _ITEMS_LIST);
2462 static PyObject*
2463 DB_values(DBObject* self, PyObject* args)
2465 PyObject* txnobj = NULL;
2466 DB_TXN *txn = NULL;
2468 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2469 return NULL;
2470 if (!checkTxnObj(txnobj, &txn))
2471 return NULL;
2472 return _DB_make_list(self, txn, _VALUES_LIST);
2475 /* --------------------------------------------------------------------- */
2476 /* DBCursor methods */
2479 static PyObject*
2480 DBC_close(DBCursorObject* self, PyObject* args)
2482 int err = 0;
2484 if (!PyArg_ParseTuple(args, ":close"))
2485 return NULL;
2487 if (self->dbc != NULL) {
2488 MYDB_BEGIN_ALLOW_THREADS;
2489 err = self->dbc->c_close(self->dbc);
2490 self->dbc = NULL;
2491 MYDB_END_ALLOW_THREADS;
2493 RETURN_IF_ERR();
2494 RETURN_NONE();
2498 static PyObject*
2499 DBC_count(DBCursorObject* self, PyObject* args)
2501 int err = 0;
2502 db_recno_t count;
2503 int flags = 0;
2505 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2506 return NULL;
2508 CHECK_CURSOR_NOT_CLOSED(self);
2510 MYDB_BEGIN_ALLOW_THREADS;
2511 err = self->dbc->c_count(self->dbc, &count, flags);
2512 MYDB_END_ALLOW_THREADS;
2513 RETURN_IF_ERR();
2515 return PyInt_FromLong(count);
2519 static PyObject*
2520 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2522 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2526 static PyObject*
2527 DBC_delete(DBCursorObject* self, PyObject* args)
2529 int err, flags=0;
2531 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2532 return NULL;
2534 CHECK_CURSOR_NOT_CLOSED(self);
2536 MYDB_BEGIN_ALLOW_THREADS;
2537 err = self->dbc->c_del(self->dbc, flags);
2538 MYDB_END_ALLOW_THREADS;
2539 RETURN_IF_ERR();
2541 self->mydb->haveStat = 0;
2542 RETURN_NONE();
2546 static PyObject*
2547 DBC_dup(DBCursorObject* self, PyObject* args)
2549 int err, flags =0;
2550 DBC* dbc = NULL;
2552 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2553 return NULL;
2555 CHECK_CURSOR_NOT_CLOSED(self);
2557 MYDB_BEGIN_ALLOW_THREADS;
2558 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2559 MYDB_END_ALLOW_THREADS;
2560 RETURN_IF_ERR();
2562 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2565 static PyObject*
2566 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2568 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2572 static PyObject*
2573 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2575 int err, flags=0;
2576 PyObject* keyobj = NULL;
2577 PyObject* dataobj = NULL;
2578 PyObject* retval = NULL;
2579 int dlen = -1;
2580 int doff = -1;
2581 DBT key, data;
2582 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2584 CLEAR_DBT(key);
2585 CLEAR_DBT(data);
2586 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
2587 &flags, &dlen, &doff))
2589 PyErr_Clear();
2590 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2591 &kwnames[1],
2592 &keyobj, &flags, &dlen, &doff))
2594 PyErr_Clear();
2595 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2596 kwnames, &keyobj, &dataobj,
2597 &flags, &dlen, &doff))
2599 return NULL;
2604 CHECK_CURSOR_NOT_CLOSED(self);
2606 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2607 return NULL;
2608 if (dataobj && !make_dbt(dataobj, &data))
2609 return NULL;
2610 if (!add_partial_dbt(&data, dlen, doff))
2611 return NULL;
2613 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2614 data.flags = DB_DBT_MALLOC;
2615 key.flags = DB_DBT_MALLOC;
2618 MYDB_BEGIN_ALLOW_THREADS;
2619 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2620 MYDB_END_ALLOW_THREADS;
2623 if ((err == DB_NOTFOUND) && self->mydb->getReturnsNone) {
2624 Py_INCREF(Py_None);
2625 retval = Py_None;
2627 else if (makeDBError(err)) {
2628 retval = NULL;
2630 else {
2631 switch (_DB_get_type(self->mydb)) {
2632 case -1:
2633 retval = NULL;
2634 break;
2635 case DB_BTREE:
2636 case DB_HASH:
2637 default:
2638 retval = Py_BuildValue("s#s#", key.data, key.size,
2639 data.data, data.size);
2640 break;
2641 case DB_RECNO:
2642 case DB_QUEUE:
2643 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2644 data.data, data.size);
2645 break;
2647 FREE_DBT(key);
2648 FREE_DBT(data);
2650 return retval;
2654 static PyObject*
2655 DBC_get_recno(DBCursorObject* self, PyObject* args)
2657 int err;
2658 db_recno_t recno;
2659 DBT key;
2660 DBT data;
2662 if (!PyArg_ParseTuple(args, ":get_recno"))
2663 return NULL;
2665 CHECK_CURSOR_NOT_CLOSED(self);
2667 CLEAR_DBT(key);
2668 CLEAR_DBT(data);
2669 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2670 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2671 data.flags = DB_DBT_MALLOC;
2672 key.flags = DB_DBT_MALLOC;
2675 MYDB_BEGIN_ALLOW_THREADS;
2676 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2677 MYDB_END_ALLOW_THREADS;
2678 RETURN_IF_ERR();
2680 recno = *((db_recno_t*)data.data);
2681 FREE_DBT(key);
2682 FREE_DBT(data);
2683 return PyInt_FromLong(recno);
2687 static PyObject*
2688 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2690 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2694 static PyObject*
2695 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2697 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2701 static PyObject*
2702 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2704 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2708 static PyObject*
2709 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2711 int err, flags = 0;
2712 PyObject* keyobj, *dataobj;
2713 DBT key, data;
2714 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2715 int dlen = -1;
2716 int doff = -1;
2718 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2719 &keyobj, &dataobj, &flags, &dlen, &doff))
2720 return NULL;
2722 CHECK_CURSOR_NOT_CLOSED(self);
2724 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2725 return NULL;
2726 if (!make_dbt(dataobj, &data))
2727 return NULL;
2728 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2730 MYDB_BEGIN_ALLOW_THREADS;
2731 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2732 MYDB_END_ALLOW_THREADS;
2733 FREE_DBT(key);
2734 RETURN_IF_ERR();
2735 self->mydb->haveStat = 0;
2736 RETURN_NONE();
2740 static PyObject*
2741 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2743 int err, flags = 0;
2744 DBT key, data;
2745 PyObject* retval, *keyobj;
2746 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2747 int dlen = -1;
2748 int doff = -1;
2750 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2751 &keyobj, &flags, &dlen, &doff))
2752 return NULL;
2754 CHECK_CURSOR_NOT_CLOSED(self);
2756 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2757 return NULL;
2759 CLEAR_DBT(data);
2760 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2761 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2762 data.flags = DB_DBT_MALLOC;
2764 if (!add_partial_dbt(&data, dlen, doff))
2765 return NULL;
2767 MYDB_BEGIN_ALLOW_THREADS;
2768 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2769 MYDB_END_ALLOW_THREADS;
2770 if (makeDBError(err)) {
2771 retval = NULL;
2773 else {
2774 switch (_DB_get_type(self->mydb)) {
2775 case -1:
2776 retval = NULL;
2777 break;
2778 case DB_BTREE:
2779 case DB_HASH:
2780 default:
2781 retval = Py_BuildValue("s#s#", key.data, key.size,
2782 data.data, data.size);
2783 break;
2784 case DB_RECNO:
2785 case DB_QUEUE:
2786 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2787 data.data, data.size);
2788 break;
2790 FREE_DBT(key);
2791 FREE_DBT(data);
2794 return retval;
2798 static PyObject*
2799 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2801 int err, flags = 0;
2802 DBT key, data;
2803 PyObject* retval, *keyobj;
2804 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2805 int dlen = -1;
2806 int doff = -1;
2808 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2809 &keyobj, &flags, &dlen, &doff))
2810 return NULL;
2812 CHECK_CURSOR_NOT_CLOSED(self);
2814 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2815 return NULL;
2817 CLEAR_DBT(data);
2818 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2819 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2820 data.flags = DB_DBT_MALLOC;
2821 key.flags = DB_DBT_MALLOC;
2823 if (!add_partial_dbt(&data, dlen, doff))
2824 return NULL;
2825 MYDB_BEGIN_ALLOW_THREADS;
2826 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2827 MYDB_END_ALLOW_THREADS;
2828 if (makeDBError(err)) {
2829 retval = NULL;
2831 else {
2832 switch (_DB_get_type(self->mydb)) {
2833 case -1:
2834 retval = NULL;
2835 break;
2836 case DB_BTREE:
2837 case DB_HASH:
2838 default:
2839 retval = Py_BuildValue("s#s#", key.data, key.size,
2840 data.data, data.size);
2841 break;
2842 case DB_RECNO:
2843 case DB_QUEUE:
2844 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2845 data.data, data.size);
2846 break;
2848 FREE_DBT(key);
2849 FREE_DBT(data);
2852 return retval;
2856 static PyObject*
2857 DBC_get_both(DBCursorObject* self, PyObject* args)
2859 int err, flags=0;
2860 DBT key, data;
2861 PyObject* retval, *keyobj, *dataobj;
2863 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2864 return NULL;
2866 CHECK_CURSOR_NOT_CLOSED(self);
2868 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2869 return NULL;
2870 if (!make_dbt(dataobj, &data))
2871 return NULL;
2873 MYDB_BEGIN_ALLOW_THREADS;
2874 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2875 MYDB_END_ALLOW_THREADS;
2876 if (makeDBError(err)) {
2877 retval = NULL;
2879 else {
2880 switch (_DB_get_type(self->mydb)) {
2881 case -1:
2882 retval = NULL;
2883 break;
2884 case DB_BTREE:
2885 case DB_HASH:
2886 default:
2887 retval = Py_BuildValue("s#s#", key.data, key.size,
2888 data.data, data.size);
2889 break;
2890 case DB_RECNO:
2891 case DB_QUEUE:
2892 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2893 data.data, data.size);
2894 break;
2898 FREE_DBT(key);
2899 return retval;
2903 static PyObject*
2904 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2906 int err, irecno, flags=0;
2907 db_recno_t recno;
2908 DBT key, data;
2909 PyObject* retval;
2910 int dlen = -1;
2911 int doff = -1;
2912 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
2914 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
2915 &irecno, &flags, &dlen, &doff))
2916 return NULL;
2918 CHECK_CURSOR_NOT_CLOSED(self);
2920 CLEAR_DBT(key);
2921 recno = (db_recno_t) irecno;
2922 /* use allocated space so DB will be able to realloc room for the real
2923 * key */
2924 key.data = malloc(sizeof(db_recno_t));
2925 if (key.data == NULL) {
2926 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
2927 return NULL;
2929 key.size = sizeof(db_recno_t);
2930 key.ulen = key.size;
2931 memcpy(key.data, &recno, sizeof(db_recno_t));
2932 key.flags = DB_DBT_REALLOC;
2934 CLEAR_DBT(data);
2935 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2936 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2937 data.flags = DB_DBT_MALLOC;
2939 if (!add_partial_dbt(&data, dlen, doff))
2940 return NULL;
2942 MYDB_BEGIN_ALLOW_THREADS;
2943 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
2944 MYDB_END_ALLOW_THREADS;
2945 if (makeDBError(err)) {
2946 retval = NULL;
2948 else { /* Can only be used for BTrees, so no need to return int key */
2949 retval = Py_BuildValue("s#s#", key.data, key.size,
2950 data.data, data.size);
2951 FREE_DBT(key);
2952 FREE_DBT(data);
2955 return retval;
2959 static PyObject*
2960 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2962 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
2966 static PyObject*
2967 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2969 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
2973 static PyObject*
2974 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2976 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
2980 static PyObject*
2981 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2983 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
2987 static PyObject*
2988 DBC_join_item(DBCursorObject* self, PyObject* args)
2990 int err;
2991 DBT key, data;
2992 PyObject* retval;
2994 if (!PyArg_ParseTuple(args, ":join_item"))
2995 return NULL;
2997 CHECK_CURSOR_NOT_CLOSED(self);
2999 CLEAR_DBT(key);
3000 CLEAR_DBT(data);
3001 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3002 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3003 key.flags = DB_DBT_MALLOC;
3006 MYDB_BEGIN_ALLOW_THREADS;
3007 err = self->dbc->c_get(self->dbc, &key, &data, DB_JOIN_ITEM);
3008 MYDB_END_ALLOW_THREADS;
3009 if (makeDBError(err)) {
3010 retval = NULL;
3012 else {
3013 retval = Py_BuildValue("s#s#", key.data, key.size);
3014 FREE_DBT(key);
3017 return retval;
3022 /* --------------------------------------------------------------------- */
3023 /* DBEnv methods */
3026 static PyObject*
3027 DBEnv_close(DBEnvObject* self, PyObject* args)
3029 int err, flags = 0;
3031 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3032 return NULL;
3033 if (!self->closed) { /* Don't close more than once */
3034 MYDB_BEGIN_ALLOW_THREADS;
3035 err = self->db_env->close(self->db_env, flags);
3036 MYDB_END_ALLOW_THREADS;
3037 /* after calling DBEnv->close, regardless of error, this DBEnv
3038 * may not be accessed again (BerkeleyDB docs). */
3039 self->closed = 1;
3040 self->db_env = NULL;
3041 RETURN_IF_ERR();
3043 RETURN_NONE();
3047 static PyObject*
3048 DBEnv_open(DBEnvObject* self, PyObject* args)
3050 int err, flags=0, mode=0660;
3051 char *db_home;
3053 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3054 return NULL;
3056 CHECK_ENV_NOT_CLOSED(self);
3058 MYDB_BEGIN_ALLOW_THREADS;
3059 err = self->db_env->open(self->db_env, db_home, flags, mode);
3060 MYDB_END_ALLOW_THREADS;
3061 RETURN_IF_ERR();
3062 self->closed = 0;
3063 self->flags = flags;
3064 RETURN_NONE();
3068 static PyObject*
3069 DBEnv_remove(DBEnvObject* self, PyObject* args)
3071 int err, flags=0;
3072 char *db_home;
3074 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3075 return NULL;
3076 CHECK_ENV_NOT_CLOSED(self);
3077 MYDB_BEGIN_ALLOW_THREADS;
3078 err = self->db_env->remove(self->db_env, db_home, flags);
3079 MYDB_END_ALLOW_THREADS;
3080 RETURN_IF_ERR();
3081 RETURN_NONE();
3084 #if (DBVER >= 41)
3085 static PyObject*
3086 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3088 int err;
3089 u_int32_t flags=0;
3090 char *file = NULL;
3091 char *database = NULL;
3092 PyObject *txnobj = NULL;
3093 DB_TXN *txn = NULL;
3094 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3096 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3097 &file, &database, &txnobj, &flags)) {
3098 return NULL;
3100 if (!checkTxnObj(txnobj, &txn)) {
3101 return NULL;
3103 CHECK_ENV_NOT_CLOSED(self);
3104 MYDB_BEGIN_ALLOW_THREADS;
3105 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3106 MYDB_END_ALLOW_THREADS;
3107 RETURN_IF_ERR();
3108 RETURN_NONE();
3111 static PyObject*
3112 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3114 int err;
3115 u_int32_t flags=0;
3116 char *file = NULL;
3117 char *database = NULL;
3118 char *newname = NULL;
3119 PyObject *txnobj = NULL;
3120 DB_TXN *txn = NULL;
3121 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3123 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3124 &file, &database, &newname, &txnobj, &flags)) {
3125 return NULL;
3127 if (!checkTxnObj(txnobj, &txn)) {
3128 return NULL;
3130 CHECK_ENV_NOT_CLOSED(self);
3131 MYDB_BEGIN_ALLOW_THREADS;
3132 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3133 flags);
3134 MYDB_END_ALLOW_THREADS;
3135 RETURN_IF_ERR();
3136 RETURN_NONE();
3139 static PyObject*
3140 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3142 int err;
3143 u_int32_t flags=0;
3144 char *passwd = NULL;
3145 char* kwnames[] = { "passwd", "flags", NULL };
3147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3148 &passwd, &flags)) {
3149 return NULL;
3152 MYDB_BEGIN_ALLOW_THREADS;
3153 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3154 MYDB_END_ALLOW_THREADS;
3156 RETURN_IF_ERR();
3157 RETURN_NONE();
3159 #endif /* DBVER >= 41 */
3161 static PyObject*
3162 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3164 int err, gbytes=0, bytes=0, ncache=0;
3166 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3167 &gbytes, &bytes, &ncache))
3168 return NULL;
3169 CHECK_ENV_NOT_CLOSED(self);
3171 MYDB_BEGIN_ALLOW_THREADS;
3172 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3173 MYDB_END_ALLOW_THREADS;
3174 RETURN_IF_ERR();
3175 RETURN_NONE();
3179 #if (DBVER >= 32)
3180 static PyObject*
3181 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3183 int err, flags=0, onoff=0;
3185 if (!PyArg_ParseTuple(args, "ii:set_flags",
3186 &flags, &onoff))
3187 return NULL;
3188 CHECK_ENV_NOT_CLOSED(self);
3190 MYDB_BEGIN_ALLOW_THREADS;
3191 err = self->db_env->set_flags(self->db_env, flags, onoff);
3192 MYDB_END_ALLOW_THREADS;
3193 RETURN_IF_ERR();
3194 RETURN_NONE();
3196 #endif
3199 static PyObject*
3200 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3202 int err;
3203 char *dir;
3205 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3206 return NULL;
3207 CHECK_ENV_NOT_CLOSED(self);
3209 MYDB_BEGIN_ALLOW_THREADS;
3210 err = self->db_env->set_data_dir(self->db_env, dir);
3211 MYDB_END_ALLOW_THREADS;
3212 RETURN_IF_ERR();
3213 RETURN_NONE();
3217 static PyObject*
3218 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3220 int err, lg_bsize;
3222 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3223 return NULL;
3224 CHECK_ENV_NOT_CLOSED(self);
3226 MYDB_BEGIN_ALLOW_THREADS;
3227 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3228 MYDB_END_ALLOW_THREADS;
3229 RETURN_IF_ERR();
3230 RETURN_NONE();
3234 static PyObject*
3235 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3237 int err;
3238 char *dir;
3240 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3241 return NULL;
3242 CHECK_ENV_NOT_CLOSED(self);
3244 MYDB_BEGIN_ALLOW_THREADS;
3245 err = self->db_env->set_lg_dir(self->db_env, dir);
3246 MYDB_END_ALLOW_THREADS;
3247 RETURN_IF_ERR();
3248 RETURN_NONE();
3251 static PyObject*
3252 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3254 int err, lg_max;
3256 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3257 return NULL;
3258 CHECK_ENV_NOT_CLOSED(self);
3260 MYDB_BEGIN_ALLOW_THREADS;
3261 err = self->db_env->set_lg_max(self->db_env, lg_max);
3262 MYDB_END_ALLOW_THREADS;
3263 RETURN_IF_ERR();
3264 RETURN_NONE();
3268 static PyObject*
3269 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3271 int err, lk_detect;
3273 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3274 return NULL;
3275 CHECK_ENV_NOT_CLOSED(self);
3277 MYDB_BEGIN_ALLOW_THREADS;
3278 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3279 MYDB_END_ALLOW_THREADS;
3280 RETURN_IF_ERR();
3281 RETURN_NONE();
3285 static PyObject*
3286 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3288 int err, max;
3290 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3291 return NULL;
3292 CHECK_ENV_NOT_CLOSED(self);
3294 MYDB_BEGIN_ALLOW_THREADS;
3295 err = self->db_env->set_lk_max(self->db_env, max);
3296 MYDB_END_ALLOW_THREADS;
3297 RETURN_IF_ERR();
3298 RETURN_NONE();
3302 #if (DBVER >= 32)
3304 static PyObject*
3305 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3307 int err, max;
3309 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3310 return NULL;
3311 CHECK_ENV_NOT_CLOSED(self);
3313 MYDB_BEGIN_ALLOW_THREADS;
3314 err = self->db_env->set_lk_max_locks(self->db_env, max);
3315 MYDB_END_ALLOW_THREADS;
3316 RETURN_IF_ERR();
3317 RETURN_NONE();
3321 static PyObject*
3322 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3324 int err, max;
3326 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3327 return NULL;
3328 CHECK_ENV_NOT_CLOSED(self);
3330 MYDB_BEGIN_ALLOW_THREADS;
3331 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3332 MYDB_END_ALLOW_THREADS;
3333 RETURN_IF_ERR();
3334 RETURN_NONE();
3338 static PyObject*
3339 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3341 int err, max;
3343 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3344 return NULL;
3345 CHECK_ENV_NOT_CLOSED(self);
3347 MYDB_BEGIN_ALLOW_THREADS;
3348 err = self->db_env->set_lk_max_objects(self->db_env, max);
3349 MYDB_END_ALLOW_THREADS;
3350 RETURN_IF_ERR();
3351 RETURN_NONE();
3354 #endif
3357 static PyObject*
3358 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3360 int err, mp_mmapsize;
3362 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3363 return NULL;
3364 CHECK_ENV_NOT_CLOSED(self);
3366 MYDB_BEGIN_ALLOW_THREADS;
3367 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3368 MYDB_END_ALLOW_THREADS;
3369 RETURN_IF_ERR();
3370 RETURN_NONE();
3374 static PyObject*
3375 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3377 int err;
3378 char *dir;
3380 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3381 return NULL;
3382 CHECK_ENV_NOT_CLOSED(self);
3384 MYDB_BEGIN_ALLOW_THREADS;
3385 err = self->db_env->set_tmp_dir(self->db_env, dir);
3386 MYDB_END_ALLOW_THREADS;
3387 RETURN_IF_ERR();
3388 RETURN_NONE();
3392 static PyObject*
3393 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3395 int flags = 0;
3396 PyObject* txnobj = NULL;
3397 DB_TXN *txn = NULL;
3398 char* kwnames[] = { "parent", "flags", NULL };
3400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3401 &txnobj, &flags))
3402 return NULL;
3404 if (!checkTxnObj(txnobj, &txn))
3405 return NULL;
3406 CHECK_ENV_NOT_CLOSED(self);
3408 return (PyObject*)newDBTxnObject(self, txn, flags);
3412 static PyObject*
3413 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3415 int err, kbyte=0, min=0, flags=0;
3417 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3418 return NULL;
3419 CHECK_ENV_NOT_CLOSED(self);
3421 MYDB_BEGIN_ALLOW_THREADS;
3422 #if (DBVER >= 40)
3423 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3424 #else
3425 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3426 #endif
3427 MYDB_END_ALLOW_THREADS;
3428 RETURN_IF_ERR();
3429 RETURN_NONE();
3433 static PyObject*
3434 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3436 int err, max;
3438 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3439 return NULL;
3440 CHECK_ENV_NOT_CLOSED(self);
3442 MYDB_BEGIN_ALLOW_THREADS;
3443 err = self->db_env->set_tx_max(self->db_env, max);
3444 MYDB_END_ALLOW_THREADS;
3445 RETURN_IF_ERR();
3446 RETURN_NONE();
3450 static PyObject*
3451 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3453 int err, atype, flags=0;
3454 int aborted = 0;
3456 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3457 return NULL;
3458 CHECK_ENV_NOT_CLOSED(self);
3460 MYDB_BEGIN_ALLOW_THREADS;
3461 #if (DBVER >= 40)
3462 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3463 #else
3464 err = lock_detect(self->db_env, flags, atype, &aborted);
3465 #endif
3466 MYDB_END_ALLOW_THREADS;
3467 RETURN_IF_ERR();
3468 return PyInt_FromLong(aborted);
3472 static PyObject*
3473 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3475 int flags=0;
3476 int locker, lock_mode;
3477 DBT obj;
3478 PyObject* objobj;
3480 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3481 return NULL;
3484 if (!make_dbt(objobj, &obj))
3485 return NULL;
3487 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3491 static PyObject*
3492 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3494 int err;
3495 u_int32_t theID;
3497 if (!PyArg_ParseTuple(args, ":lock_id"))
3498 return NULL;
3500 CHECK_ENV_NOT_CLOSED(self);
3501 MYDB_BEGIN_ALLOW_THREADS;
3502 #if (DBVER >= 40)
3503 err = self->db_env->lock_id(self->db_env, &theID);
3504 #else
3505 err = lock_id(self->db_env, &theID);
3506 #endif
3507 MYDB_END_ALLOW_THREADS;
3508 RETURN_IF_ERR();
3510 return PyInt_FromLong((long)theID);
3514 static PyObject*
3515 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3517 int err;
3518 DBLockObject* dblockobj;
3520 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3521 return NULL;
3523 CHECK_ENV_NOT_CLOSED(self);
3524 MYDB_BEGIN_ALLOW_THREADS;
3525 #if (DBVER >= 40)
3526 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3527 #else
3528 err = lock_put(self->db_env, &dblockobj->lock);
3529 #endif
3530 MYDB_END_ALLOW_THREADS;
3531 RETURN_IF_ERR();
3532 RETURN_NONE();
3536 static PyObject*
3537 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3539 int err;
3540 DB_LOCK_STAT* sp;
3541 PyObject* d = NULL;
3542 u_int32_t flags = 0;
3544 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3545 return NULL;
3546 CHECK_ENV_NOT_CLOSED(self);
3548 MYDB_BEGIN_ALLOW_THREADS;
3549 #if (DBVER >= 40)
3550 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3551 #else
3552 #if (DBVER >= 33)
3553 err = lock_stat(self->db_env, &sp);
3554 #else
3555 err = lock_stat(self->db_env, &sp, NULL);
3556 #endif
3557 #endif
3558 MYDB_END_ALLOW_THREADS;
3559 RETURN_IF_ERR();
3561 /* Turn the stat structure into a dictionary */
3562 d = PyDict_New();
3563 if (d == NULL) {
3564 free(sp);
3565 return NULL;
3568 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3570 #if (DBVER < 41)
3571 MAKE_ENTRY(lastid);
3572 #endif
3573 MAKE_ENTRY(nmodes);
3574 #if (DBVER >= 32)
3575 MAKE_ENTRY(maxlocks);
3576 MAKE_ENTRY(maxlockers);
3577 MAKE_ENTRY(maxobjects);
3578 MAKE_ENTRY(nlocks);
3579 MAKE_ENTRY(maxnlocks);
3580 #endif
3581 MAKE_ENTRY(nlockers);
3582 MAKE_ENTRY(maxnlockers);
3583 #if (DBVER >= 32)
3584 MAKE_ENTRY(nobjects);
3585 MAKE_ENTRY(maxnobjects);
3586 #endif
3587 MAKE_ENTRY(nrequests);
3588 MAKE_ENTRY(nreleases);
3589 MAKE_ENTRY(nnowaits);
3590 MAKE_ENTRY(nconflicts);
3591 MAKE_ENTRY(ndeadlocks);
3592 MAKE_ENTRY(regsize);
3593 MAKE_ENTRY(region_wait);
3594 MAKE_ENTRY(region_nowait);
3596 #undef MAKE_ENTRY
3597 free(sp);
3598 return d;
3602 static PyObject*
3603 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3605 int flags=0;
3606 int err;
3607 char **log_list_start, **log_list;
3608 PyObject* list;
3609 PyObject* item = NULL;
3611 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3612 return NULL;
3614 CHECK_ENV_NOT_CLOSED(self);
3615 MYDB_BEGIN_ALLOW_THREADS;
3616 #if (DBVER >= 40)
3617 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3618 #elif (DBVER == 33)
3619 err = log_archive(self->db_env, &log_list, flags);
3620 #else
3621 err = log_archive(self->db_env, &log_list, flags, NULL);
3622 #endif
3623 MYDB_END_ALLOW_THREADS;
3624 RETURN_IF_ERR();
3626 list = PyList_New(0);
3627 if (list == NULL) {
3628 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3629 return NULL;
3632 if (log_list) {
3633 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3634 item = PyString_FromString (*log_list);
3635 if (item == NULL) {
3636 Py_DECREF(list);
3637 PyErr_SetString(PyExc_MemoryError,
3638 "List item creation failed");
3639 list = NULL;
3640 break;
3642 PyList_Append(list, item);
3643 Py_DECREF(item);
3645 free(log_list_start);
3647 return list;
3651 static PyObject*
3652 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3654 int err;
3655 DB_TXN_STAT* sp;
3656 PyObject* d = NULL;
3657 u_int32_t flags=0;
3659 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3660 return NULL;
3661 CHECK_ENV_NOT_CLOSED(self);
3663 MYDB_BEGIN_ALLOW_THREADS;
3664 #if (DBVER >= 40)
3665 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3666 #elif (DBVER == 33)
3667 err = txn_stat(self->db_env, &sp);
3668 #else
3669 err = txn_stat(self->db_env, &sp, NULL);
3670 #endif
3671 MYDB_END_ALLOW_THREADS;
3672 RETURN_IF_ERR();
3674 /* Turn the stat structure into a dictionary */
3675 d = PyDict_New();
3676 if (d == NULL) {
3677 free(sp);
3678 return NULL;
3681 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3683 MAKE_ENTRY(time_ckp);
3684 MAKE_ENTRY(last_txnid);
3685 MAKE_ENTRY(maxtxns);
3686 MAKE_ENTRY(nactive);
3687 MAKE_ENTRY(maxnactive);
3688 MAKE_ENTRY(nbegins);
3689 MAKE_ENTRY(naborts);
3690 MAKE_ENTRY(ncommits);
3691 MAKE_ENTRY(regsize);
3692 MAKE_ENTRY(region_wait);
3693 MAKE_ENTRY(region_nowait);
3695 #undef MAKE_ENTRY
3696 free(sp);
3697 return d;
3701 static PyObject*
3702 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3704 int flags=0;
3705 int oldValue;
3707 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3708 return NULL;
3709 CHECK_ENV_NOT_CLOSED(self);
3711 oldValue = self->getReturnsNone;
3712 self->getReturnsNone = flags;
3713 return PyInt_FromLong(oldValue);
3717 /* --------------------------------------------------------------------- */
3718 /* DBTxn methods */
3721 static PyObject*
3722 DBTxn_commit(DBTxnObject* self, PyObject* args)
3724 int flags=0, err;
3726 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3727 return NULL;
3729 MYDB_BEGIN_ALLOW_THREADS;
3730 #if (DBVER >= 40)
3731 err = self->txn->commit(self->txn, flags);
3732 #else
3733 err = txn_commit(self->txn, flags);
3734 #endif
3735 MYDB_END_ALLOW_THREADS;
3736 RETURN_IF_ERR();
3737 RETURN_NONE();
3740 static PyObject*
3741 DBTxn_prepare(DBTxnObject* self, PyObject* args)
3743 #if (DBVER >= 33)
3744 int err;
3745 char* gid=NULL;
3746 int gid_size=0;
3748 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3749 return NULL;
3751 if (gid_size != DB_XIDDATASIZE) {
3752 PyErr_SetString(PyExc_TypeError,
3753 "gid must be DB_XIDDATASIZE bytes long");
3754 return NULL;
3757 MYDB_BEGIN_ALLOW_THREADS;
3758 #if (DBVER >= 40)
3759 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3760 #else
3761 err = txn_prepare(self->txn, (u_int8_t*)gid);
3762 #endif
3763 MYDB_END_ALLOW_THREADS;
3764 RETURN_IF_ERR();
3765 RETURN_NONE();
3766 #else
3767 int err;
3769 if (!PyArg_ParseTuple(args, ":prepare"))
3770 return NULL;
3772 MYDB_BEGIN_ALLOW_THREADS;
3773 err = txn_prepare(self->txn);
3774 MYDB_END_ALLOW_THREADS;
3775 RETURN_IF_ERR();
3776 RETURN_NONE();
3777 #endif
3781 static PyObject*
3782 DBTxn_abort(DBTxnObject* self, PyObject* args)
3784 int err;
3786 if (!PyArg_ParseTuple(args, ":abort"))
3787 return NULL;
3789 MYDB_BEGIN_ALLOW_THREADS;
3790 #if (DBVER >= 40)
3791 err = self->txn->abort(self->txn);
3792 #else
3793 err = txn_abort(self->txn);
3794 #endif
3795 MYDB_END_ALLOW_THREADS;
3796 RETURN_IF_ERR();
3797 RETURN_NONE();
3801 static PyObject*
3802 DBTxn_id(DBTxnObject* self, PyObject* args)
3804 int id;
3806 if (!PyArg_ParseTuple(args, ":id"))
3807 return NULL;
3809 MYDB_BEGIN_ALLOW_THREADS;
3810 #if (DBVER >= 40)
3811 id = self->txn->id(self->txn);
3812 #else
3813 id = txn_id(self->txn);
3814 #endif
3815 MYDB_END_ALLOW_THREADS;
3816 return PyInt_FromLong(id);
3819 /* --------------------------------------------------------------------- */
3820 /* Method definition tables and type objects */
3822 static PyMethodDef DB_methods[] = {
3823 {"append", (PyCFunction)DB_append, METH_VARARGS},
3824 #if (DBVER >= 33)
3825 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
3826 #endif
3827 {"close", (PyCFunction)DB_close, METH_VARARGS},
3828 #if (DBVER >= 32)
3829 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
3830 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
3831 #endif
3832 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
3833 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
3834 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
3835 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
3836 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
3837 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
3838 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
3839 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
3840 {"join", (PyCFunction)DB_join, METH_VARARGS},
3841 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
3842 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
3843 {"items", (PyCFunction)DB_items, METH_VARARGS},
3844 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
3845 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
3846 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
3847 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
3848 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
3849 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
3850 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
3851 #if (DBVER >= 41)
3852 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
3853 #endif
3854 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
3855 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
3856 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
3857 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
3858 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
3859 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
3860 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
3861 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
3862 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
3863 #if (DBVER >= 32)
3864 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
3865 #endif
3866 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
3867 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
3868 #if (DBVER >= 33)
3869 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
3870 #endif
3871 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
3872 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
3873 {"values", (PyCFunction)DB_values, METH_VARARGS},
3874 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
3875 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
3876 {NULL, NULL} /* sentinel */
3880 static PyMappingMethods DB_mapping = {
3881 (inquiry)DB_length, /*mp_length*/
3882 (binaryfunc)DB_subscript, /*mp_subscript*/
3883 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
3887 static PyMethodDef DBCursor_methods[] = {
3888 {"close", (PyCFunction)DBC_close, METH_VARARGS},
3889 {"count", (PyCFunction)DBC_count, METH_VARARGS},
3890 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
3891 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
3892 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
3893 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
3894 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
3895 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
3896 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
3897 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
3898 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
3899 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
3900 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
3901 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
3902 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
3903 {"set_both", (PyCFunction)DBC_get_both, METH_VARARGS},
3904 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
3905 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
3906 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
3907 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
3908 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
3909 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
3910 {NULL, NULL} /* sentinel */
3914 static PyMethodDef DBEnv_methods[] = {
3915 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
3916 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
3917 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
3918 #if (DBVER >= 41)
3919 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
3920 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
3921 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
3922 #endif
3923 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
3924 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
3925 #if (DBVER >= 32)
3926 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
3927 #endif
3928 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
3929 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
3930 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
3931 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
3932 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
3933 #if (DBVER >= 32)
3934 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
3935 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
3936 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
3937 #endif
3938 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
3939 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
3940 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
3941 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
3942 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
3943 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
3944 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
3945 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
3946 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
3947 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
3948 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
3949 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
3950 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
3951 {NULL, NULL} /* sentinel */
3955 static PyMethodDef DBTxn_methods[] = {
3956 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
3957 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
3958 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
3959 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
3960 {NULL, NULL} /* sentinel */
3964 static PyObject*
3965 DB_getattr(DBObject* self, char *name)
3967 return Py_FindMethod(DB_methods, (PyObject* )self, name);
3971 static PyObject*
3972 DBEnv_getattr(DBEnvObject* self, char *name)
3974 if (!strcmp(name, "db_home")) {
3975 CHECK_ENV_NOT_CLOSED(self);
3976 if (self->db_env->db_home == NULL) {
3977 RETURN_NONE();
3979 return PyString_FromString(self->db_env->db_home);
3982 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
3986 static PyObject*
3987 DBCursor_getattr(DBCursorObject* self, char *name)
3989 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
3992 static PyObject*
3993 DBTxn_getattr(DBTxnObject* self, char *name)
3995 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
3998 static PyObject*
3999 DBLock_getattr(DBLockObject* self, char *name)
4001 return NULL;
4004 statichere PyTypeObject DB_Type = {
4005 PyObject_HEAD_INIT(NULL)
4006 0, /*ob_size*/
4007 "DB", /*tp_name*/
4008 sizeof(DBObject), /*tp_basicsize*/
4009 0, /*tp_itemsize*/
4010 /* methods */
4011 (destructor)DB_dealloc, /*tp_dealloc*/
4012 0, /*tp_print*/
4013 (getattrfunc)DB_getattr, /*tp_getattr*/
4014 0, /*tp_setattr*/
4015 0, /*tp_compare*/
4016 0, /*tp_repr*/
4017 0, /*tp_as_number*/
4018 0, /*tp_as_sequence*/
4019 &DB_mapping,/*tp_as_mapping*/
4020 0, /*tp_hash*/
4024 statichere PyTypeObject DBCursor_Type = {
4025 PyObject_HEAD_INIT(NULL)
4026 0, /*ob_size*/
4027 "DBCursor", /*tp_name*/
4028 sizeof(DBCursorObject), /*tp_basicsize*/
4029 0, /*tp_itemsize*/
4030 /* methods */
4031 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4032 0, /*tp_print*/
4033 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4034 0, /*tp_setattr*/
4035 0, /*tp_compare*/
4036 0, /*tp_repr*/
4037 0, /*tp_as_number*/
4038 0, /*tp_as_sequence*/
4039 0, /*tp_as_mapping*/
4040 0, /*tp_hash*/
4044 statichere PyTypeObject DBEnv_Type = {
4045 PyObject_HEAD_INIT(NULL)
4046 0, /*ob_size*/
4047 "DBEnv", /*tp_name*/
4048 sizeof(DBEnvObject), /*tp_basicsize*/
4049 0, /*tp_itemsize*/
4050 /* methods */
4051 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4052 0, /*tp_print*/
4053 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4054 0, /*tp_setattr*/
4055 0, /*tp_compare*/
4056 0, /*tp_repr*/
4057 0, /*tp_as_number*/
4058 0, /*tp_as_sequence*/
4059 0, /*tp_as_mapping*/
4060 0, /*tp_hash*/
4063 statichere PyTypeObject DBTxn_Type = {
4064 PyObject_HEAD_INIT(NULL)
4065 0, /*ob_size*/
4066 "DBTxn", /*tp_name*/
4067 sizeof(DBTxnObject), /*tp_basicsize*/
4068 0, /*tp_itemsize*/
4069 /* methods */
4070 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4071 0, /*tp_print*/
4072 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4073 0, /*tp_setattr*/
4074 0, /*tp_compare*/
4075 0, /*tp_repr*/
4076 0, /*tp_as_number*/
4077 0, /*tp_as_sequence*/
4078 0, /*tp_as_mapping*/
4079 0, /*tp_hash*/
4083 statichere PyTypeObject DBLock_Type = {
4084 PyObject_HEAD_INIT(NULL)
4085 0, /*ob_size*/
4086 "DBLock", /*tp_name*/
4087 sizeof(DBLockObject), /*tp_basicsize*/
4088 0, /*tp_itemsize*/
4089 /* methods */
4090 (destructor)DBLock_dealloc, /*tp_dealloc*/
4091 0, /*tp_print*/
4092 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4093 0, /*tp_setattr*/
4094 0, /*tp_compare*/
4095 0, /*tp_repr*/
4096 0, /*tp_as_number*/
4097 0, /*tp_as_sequence*/
4098 0, /*tp_as_mapping*/
4099 0, /*tp_hash*/
4103 /* --------------------------------------------------------------------- */
4104 /* Module-level functions */
4106 static PyObject*
4107 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4109 PyObject* dbenvobj = NULL;
4110 int flags = 0;
4111 char* kwnames[] = { "dbEnv", "flags", NULL};
4113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4114 &dbenvobj, &flags))
4115 return NULL;
4116 if (dbenvobj == Py_None)
4117 dbenvobj = NULL;
4118 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4119 makeTypeError("DBEnv", dbenvobj);
4120 return NULL;
4123 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4127 static PyObject*
4128 DBEnv_construct(PyObject* self, PyObject* args)
4130 int flags = 0;
4131 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4132 return (PyObject* )newDBEnvObject(flags);
4136 static char bsddb_version_doc[] =
4137 "Returns a tuple of major, minor, and patch release numbers of the\n\
4138 underlying DB library.";
4140 static PyObject*
4141 bsddb_version(PyObject* self, PyObject* args)
4143 int major, minor, patch;
4145 if (!PyArg_ParseTuple(args, ":version"))
4146 return NULL;
4147 db_version(&major, &minor, &patch);
4148 return Py_BuildValue("(iii)", major, minor, patch);
4152 /* List of functions defined in the module */
4154 static PyMethodDef bsddb_methods[] = {
4155 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4156 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4157 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4158 {NULL, NULL} /* sentinel */
4162 /* --------------------------------------------------------------------- */
4163 /* Module initialization */
4166 /* Convenience routine to export an integer value.
4167 * Errors are silently ignored, for better or for worse...
4169 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4173 DL_EXPORT(void) init_bsddb(void)
4175 PyObject* m;
4176 PyObject* d;
4177 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4178 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4179 PyObject* cvsid_s = PyString_FromString( rcs_id );
4181 /* Initialize the type of the new type objects here; doing it here
4182 is required for portability to Windows without requiring C++. */
4183 DB_Type.ob_type = &PyType_Type;
4184 DBCursor_Type.ob_type = &PyType_Type;
4185 DBEnv_Type.ob_type = &PyType_Type;
4186 DBTxn_Type.ob_type = &PyType_Type;
4187 DBLock_Type.ob_type = &PyType_Type;
4190 #ifdef WITH_THREAD
4191 /* Save the current interpreter, so callbacks can do the right thing. */
4192 _db_interpreterState = PyThreadState_Get()->interp;
4193 #endif
4195 /* Create the module and add the functions */
4196 m = Py_InitModule("_bsddb", bsddb_methods);
4198 /* Add some symbolic constants to the module */
4199 d = PyModule_GetDict(m);
4200 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4201 PyDict_SetItemString(d, "cvsid", cvsid_s);
4202 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4203 Py_DECREF(pybsddb_version_s);
4204 pybsddb_version_s = NULL;
4205 Py_DECREF(cvsid_s);
4206 cvsid_s = NULL;
4207 Py_DECREF(db_version_s);
4208 db_version_s = NULL;
4210 ADD_INT(d, DB_VERSION_MAJOR);
4211 ADD_INT(d, DB_VERSION_MINOR);
4212 ADD_INT(d, DB_VERSION_PATCH);
4214 ADD_INT(d, DB_MAX_PAGES);
4215 ADD_INT(d, DB_MAX_RECORDS);
4217 ADD_INT(d, DB_CLIENT);
4218 ADD_INT(d, DB_XA_CREATE);
4220 ADD_INT(d, DB_CREATE);
4221 ADD_INT(d, DB_NOMMAP);
4222 ADD_INT(d, DB_THREAD);
4224 ADD_INT(d, DB_FORCE);
4225 ADD_INT(d, DB_INIT_CDB);
4226 ADD_INT(d, DB_INIT_LOCK);
4227 ADD_INT(d, DB_INIT_LOG);
4228 ADD_INT(d, DB_INIT_MPOOL);
4229 ADD_INT(d, DB_INIT_TXN);
4230 #if (DBVER >= 32)
4231 ADD_INT(d, DB_JOINENV);
4232 #endif
4234 ADD_INT(d, DB_RECOVER);
4235 ADD_INT(d, DB_RECOVER_FATAL);
4236 ADD_INT(d, DB_TXN_NOSYNC);
4237 ADD_INT(d, DB_USE_ENVIRON);
4238 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4240 ADD_INT(d, DB_LOCKDOWN);
4241 ADD_INT(d, DB_PRIVATE);
4242 ADD_INT(d, DB_SYSTEM_MEM);
4244 ADD_INT(d, DB_TXN_SYNC);
4245 ADD_INT(d, DB_TXN_NOWAIT);
4247 ADD_INT(d, DB_EXCL);
4248 ADD_INT(d, DB_FCNTL_LOCKING);
4249 ADD_INT(d, DB_ODDFILESIZE);
4250 ADD_INT(d, DB_RDWRMASTER);
4251 ADD_INT(d, DB_RDONLY);
4252 ADD_INT(d, DB_TRUNCATE);
4253 #if (DBVER >= 32)
4254 ADD_INT(d, DB_EXTENT);
4255 ADD_INT(d, DB_CDB_ALLDB);
4256 ADD_INT(d, DB_VERIFY);
4257 #endif
4258 ADD_INT(d, DB_UPGRADE);
4260 ADD_INT(d, DB_AGGRESSIVE);
4261 ADD_INT(d, DB_NOORDERCHK);
4262 ADD_INT(d, DB_ORDERCHKONLY);
4263 ADD_INT(d, DB_PR_PAGE);
4264 #if ! (DBVER >= 33)
4265 ADD_INT(d, DB_VRFY_FLAGMASK);
4266 ADD_INT(d, DB_PR_HEADERS);
4267 #endif
4268 ADD_INT(d, DB_PR_RECOVERYTEST);
4269 ADD_INT(d, DB_SALVAGE);
4271 ADD_INT(d, DB_LOCK_NORUN);
4272 ADD_INT(d, DB_LOCK_DEFAULT);
4273 ADD_INT(d, DB_LOCK_OLDEST);
4274 ADD_INT(d, DB_LOCK_RANDOM);
4275 ADD_INT(d, DB_LOCK_YOUNGEST);
4276 #if (DBVER >= 33)
4277 ADD_INT(d, DB_LOCK_MAXLOCKS);
4278 ADD_INT(d, DB_LOCK_MINLOCKS);
4279 ADD_INT(d, DB_LOCK_MINWRITE);
4280 #endif
4283 #if (DBVER >= 33)
4284 /* docs say to use zero instead */
4285 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
4286 #else
4287 ADD_INT(d, DB_LOCK_CONFLICT);
4288 #endif
4290 ADD_INT(d, DB_LOCK_DUMP);
4291 ADD_INT(d, DB_LOCK_GET);
4292 ADD_INT(d, DB_LOCK_INHERIT);
4293 ADD_INT(d, DB_LOCK_PUT);
4294 ADD_INT(d, DB_LOCK_PUT_ALL);
4295 ADD_INT(d, DB_LOCK_PUT_OBJ);
4297 ADD_INT(d, DB_LOCK_NG);
4298 ADD_INT(d, DB_LOCK_READ);
4299 ADD_INT(d, DB_LOCK_WRITE);
4300 ADD_INT(d, DB_LOCK_NOWAIT);
4301 #if (DBVER >= 32)
4302 ADD_INT(d, DB_LOCK_WAIT);
4303 #endif
4304 ADD_INT(d, DB_LOCK_IWRITE);
4305 ADD_INT(d, DB_LOCK_IREAD);
4306 ADD_INT(d, DB_LOCK_IWR);
4307 #if (DBVER >= 33)
4308 ADD_INT(d, DB_LOCK_DIRTY);
4309 ADD_INT(d, DB_LOCK_WWRITE);
4310 #endif
4312 ADD_INT(d, DB_LOCK_RECORD);
4313 ADD_INT(d, DB_LOCK_UPGRADE);
4314 #if (DBVER >= 32)
4315 ADD_INT(d, DB_LOCK_SWITCH);
4316 #endif
4317 #if (DBVER >= 33)
4318 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4319 #endif
4321 ADD_INT(d, DB_LOCK_NOWAIT);
4322 ADD_INT(d, DB_LOCK_RECORD);
4323 ADD_INT(d, DB_LOCK_UPGRADE);
4325 #if (DBVER >= 33)
4326 ADD_INT(d, DB_LSTAT_ABORTED);
4327 ADD_INT(d, DB_LSTAT_ERR);
4328 ADD_INT(d, DB_LSTAT_FREE);
4329 ADD_INT(d, DB_LSTAT_HELD);
4330 #if (DBVER == 33)
4331 ADD_INT(d, DB_LSTAT_NOGRANT);
4332 #endif
4333 ADD_INT(d, DB_LSTAT_PENDING);
4334 ADD_INT(d, DB_LSTAT_WAITING);
4335 #endif
4337 ADD_INT(d, DB_ARCH_ABS);
4338 ADD_INT(d, DB_ARCH_DATA);
4339 ADD_INT(d, DB_ARCH_LOG);
4341 ADD_INT(d, DB_BTREE);
4342 ADD_INT(d, DB_HASH);
4343 ADD_INT(d, DB_RECNO);
4344 ADD_INT(d, DB_QUEUE);
4345 ADD_INT(d, DB_UNKNOWN);
4347 ADD_INT(d, DB_DUP);
4348 ADD_INT(d, DB_DUPSORT);
4349 ADD_INT(d, DB_RECNUM);
4350 ADD_INT(d, DB_RENUMBER);
4351 ADD_INT(d, DB_REVSPLITOFF);
4352 ADD_INT(d, DB_SNAPSHOT);
4354 ADD_INT(d, DB_JOIN_NOSORT);
4356 ADD_INT(d, DB_AFTER);
4357 ADD_INT(d, DB_APPEND);
4358 ADD_INT(d, DB_BEFORE);
4359 ADD_INT(d, DB_CACHED_COUNTS);
4360 #if (DBVER >= 41)
4361 _addIntToDict(d, "DB_CHECKPOINT", 0);
4362 #else
4363 ADD_INT(d, DB_CHECKPOINT);
4364 ADD_INT(d, DB_CURLSN);
4365 #endif
4366 #if (DBVER >= 33)
4367 ADD_INT(d, DB_COMMIT);
4368 #endif
4369 ADD_INT(d, DB_CONSUME);
4370 #if (DBVER >= 32)
4371 ADD_INT(d, DB_CONSUME_WAIT);
4372 #endif
4373 ADD_INT(d, DB_CURRENT);
4374 #if (DBVER >= 33)
4375 ADD_INT(d, DB_FAST_STAT);
4376 #endif
4377 ADD_INT(d, DB_FIRST);
4378 ADD_INT(d, DB_FLUSH);
4379 ADD_INT(d, DB_GET_BOTH);
4380 ADD_INT(d, DB_GET_RECNO);
4381 ADD_INT(d, DB_JOIN_ITEM);
4382 ADD_INT(d, DB_KEYFIRST);
4383 ADD_INT(d, DB_KEYLAST);
4384 ADD_INT(d, DB_LAST);
4385 ADD_INT(d, DB_NEXT);
4386 ADD_INT(d, DB_NEXT_DUP);
4387 ADD_INT(d, DB_NEXT_NODUP);
4388 ADD_INT(d, DB_NODUPDATA);
4389 ADD_INT(d, DB_NOOVERWRITE);
4390 ADD_INT(d, DB_NOSYNC);
4391 ADD_INT(d, DB_POSITION);
4392 ADD_INT(d, DB_PREV);
4393 ADD_INT(d, DB_PREV_NODUP);
4394 ADD_INT(d, DB_RECORDCOUNT);
4395 ADD_INT(d, DB_SET);
4396 ADD_INT(d, DB_SET_RANGE);
4397 ADD_INT(d, DB_SET_RECNO);
4398 ADD_INT(d, DB_WRITECURSOR);
4400 ADD_INT(d, DB_OPFLAGS_MASK);
4401 ADD_INT(d, DB_RMW);
4402 #if (DBVER >= 33)
4403 ADD_INT(d, DB_DIRTY_READ);
4404 ADD_INT(d, DB_MULTIPLE);
4405 ADD_INT(d, DB_MULTIPLE_KEY);
4406 #endif
4408 #if (DBVER >= 33)
4409 ADD_INT(d, DB_DONOTINDEX);
4410 #endif
4412 #if (DBVER >= 41)
4413 _addIntToDict(d, "DB_INCOMPLETE", 0);
4414 #else
4415 ADD_INT(d, DB_INCOMPLETE);
4416 #endif
4417 ADD_INT(d, DB_KEYEMPTY);
4418 ADD_INT(d, DB_KEYEXIST);
4419 ADD_INT(d, DB_LOCK_DEADLOCK);
4420 ADD_INT(d, DB_LOCK_NOTGRANTED);
4421 ADD_INT(d, DB_NOSERVER);
4422 ADD_INT(d, DB_NOSERVER_HOME);
4423 ADD_INT(d, DB_NOSERVER_ID);
4424 ADD_INT(d, DB_NOTFOUND);
4425 ADD_INT(d, DB_OLD_VERSION);
4426 ADD_INT(d, DB_RUNRECOVERY);
4427 ADD_INT(d, DB_VERIFY_BAD);
4428 #if (DBVER >= 33)
4429 ADD_INT(d, DB_PAGE_NOTFOUND);
4430 ADD_INT(d, DB_SECONDARY_BAD);
4431 #endif
4432 #if (DBVER >= 40)
4433 ADD_INT(d, DB_STAT_CLEAR);
4434 ADD_INT(d, DB_REGION_INIT);
4435 ADD_INT(d, DB_NOLOCKING);
4436 ADD_INT(d, DB_YIELDCPU);
4437 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4438 ADD_INT(d, DB_NOPANIC);
4439 #endif
4441 #if (DBVER >= 41)
4442 ADD_INT(d, DB_ENCRYPT_AES);
4443 ADD_INT(d, DB_AUTO_COMMIT);
4444 #else
4445 /* allow berkeleydb 4.1 aware apps to run on older versions */
4446 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4447 #endif
4449 ADD_INT(d, EINVAL);
4450 ADD_INT(d, EACCES);
4451 ADD_INT(d, ENOSPC);
4452 ADD_INT(d, ENOMEM);
4453 ADD_INT(d, EAGAIN);
4454 ADD_INT(d, EBUSY);
4455 ADD_INT(d, EEXIST);
4456 ADD_INT(d, ENOENT);
4457 ADD_INT(d, EPERM);
4461 /* The base exception class is DBError */
4462 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
4463 PyDict_SetItemString(d, "DBError", DBError);
4465 /* Some magic to make DBNotFoundError derive from both DBError and
4466 KeyError, since the API only supports using one base class. */
4467 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4468 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4469 Py_file_input, d, d);
4470 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4471 PyDict_DelItemString(d, "KeyError");
4474 /* All the rest of the exceptions derive only from DBError */
4475 #define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
4476 PyDict_SetItemString(d, #name, name)
4478 #if !INCOMPLETE_IS_WARNING
4479 MAKE_EX(DBIncompleteError);
4480 #endif
4481 MAKE_EX(DBKeyEmptyError);
4482 MAKE_EX(DBKeyExistError);
4483 MAKE_EX(DBLockDeadlockError);
4484 MAKE_EX(DBLockNotGrantedError);
4485 MAKE_EX(DBOldVersionError);
4486 MAKE_EX(DBRunRecoveryError);
4487 MAKE_EX(DBVerifyBadError);
4488 MAKE_EX(DBNoServerError);
4489 MAKE_EX(DBNoServerHomeError);
4490 MAKE_EX(DBNoServerIDError);
4491 #if (DBVER >= 33)
4492 MAKE_EX(DBPageNotFoundError);
4493 MAKE_EX(DBSecondaryBadError);
4494 #endif
4496 MAKE_EX(DBInvalidArgError);
4497 MAKE_EX(DBAccessError);
4498 MAKE_EX(DBNoSpaceError);
4499 MAKE_EX(DBNoMemoryError);
4500 MAKE_EX(DBAgainError);
4501 MAKE_EX(DBBusyError);
4502 MAKE_EX(DBFileExistsError);
4503 MAKE_EX(DBNoSuchFileError);
4504 MAKE_EX(DBPermissionsError);
4506 #undef MAKE_EX
4508 /* Check for errors */
4509 if (PyErr_Occurred()) {
4510 PyErr_Print();
4511 Py_FatalError("can't initialize module _bsddb");