Speed-up isinstance() for one easy case.
[python.git] / Modules / _bsddb.c
blob7d05b24ed1d32268cbc59c010cf3830e73e37de2
1 /*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33 ------------------------------------------------------------------------*/
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
38 * written to replace a SWIG-generated file. It has since been updated
39 * to compile with BerkeleyDB versions 3.2 through 4.2.
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
44 * 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@krypto.org> is once again the maintainer.
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
54 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
57 * http://pybsddb.sf.net
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
62 * http://www.python.org/peps/pep-0291.html
64 * This module contains 6 types:
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 * DBSequence (Sequence)
75 /* --------------------------------------------------------------------- */
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
83 * --Robin
86 /* --------------------------------------------------------------------- */
88 #include <stddef.h> /* for offsetof() */
89 #include <Python.h>
91 #define COMPILING_BSDDB_C
92 #include "bsddb.h"
93 #undef COMPILING_BSDDB_C
95 static char *rcs_id = "$Id$";
97 /* --------------------------------------------------------------------- */
98 /* Various macro definitions */
100 #if (PY_VERSION_HEX < 0x02050000)
101 typedef int Py_ssize_t;
102 #endif
104 #ifdef WITH_THREAD
106 /* These are for when calling Python --> C */
107 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
110 /* For 2.3, use the PyGILState_ calls */
111 #if (PY_VERSION_HEX >= 0x02030000)
112 #define MYDB_USE_GILSTATE
113 #endif
115 /* and these are for calling C --> Python */
116 #if defined(MYDB_USE_GILSTATE)
117 #define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119 #define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121 #else /* MYDB_USE_GILSTATE */
122 /* Pre GILState API - do it the long old way */
123 static PyInterpreterState* _db_interpreterState = NULL;
124 #define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
131 #define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
137 #endif /* MYDB_USE_GILSTATE */
139 #else
140 /* Compiled without threads - avoid all this cruft */
141 #define MYDB_BEGIN_ALLOW_THREADS
142 #define MYDB_END_ALLOW_THREADS
143 #define MYDB_BEGIN_BLOCK_THREADS
144 #define MYDB_END_BLOCK_THREADS
146 #endif
148 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
149 #define INCOMPLETE_IS_WARNING 1
151 /* --------------------------------------------------------------------- */
152 /* Exceptions */
154 static PyObject* DBError; /* Base class, all others derive from this */
155 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
156 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
157 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
158 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
159 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
160 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
161 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
162 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
163 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
164 static PyObject* DBNoServerError; /* DB_NOSERVER */
165 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
166 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
167 #if (DBVER >= 33)
168 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
169 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
170 #endif
172 #if !INCOMPLETE_IS_WARNING
173 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
174 #endif
176 static PyObject* DBInvalidArgError; /* EINVAL */
177 static PyObject* DBAccessError; /* EACCES */
178 static PyObject* DBNoSpaceError; /* ENOSPC */
179 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
180 static PyObject* DBAgainError; /* EAGAIN */
181 static PyObject* DBBusyError; /* EBUSY */
182 static PyObject* DBFileExistsError; /* EEXIST */
183 static PyObject* DBNoSuchFileError; /* ENOENT */
184 static PyObject* DBPermissionsError; /* EPERM */
186 #if (DBVER < 43)
187 #define DB_BUFFER_SMALL ENOMEM
188 #endif
191 /* --------------------------------------------------------------------- */
192 /* Structure definitions */
194 #if PYTHON_API_VERSION < 1010
195 #error "Python 2.1 or later required"
196 #endif
199 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
200 #define DEFAULT_GET_RETURNS_NONE 1
201 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
204 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
206 #ifndef Py_Type
207 /* for compatibility with Python 2.5 and earlier */
208 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
209 #endif
211 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
212 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
213 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
214 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
215 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
216 #if (DBVER >= 43)
217 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
218 #endif
221 /* --------------------------------------------------------------------- */
222 /* Utility macros and functions */
224 #define RETURN_IF_ERR() \
225 if (makeDBError(err)) { \
226 return NULL; \
229 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
231 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
232 if ((nonNull) == NULL) { \
233 PyObject *errTuple = NULL; \
234 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
235 PyErr_SetObject((pyErrObj), errTuple); \
236 Py_DECREF(errTuple); \
237 return NULL; \
240 #define CHECK_DB_NOT_CLOSED(dbobj) \
241 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
243 #define CHECK_ENV_NOT_CLOSED(env) \
244 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
246 #define CHECK_CURSOR_NOT_CLOSED(curs) \
247 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
249 #if (DBVER >= 43)
250 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
251 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
252 #endif
254 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
255 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
257 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
259 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
260 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
263 static int makeDBError(int err);
266 /* Return the access method type of the DBObject */
267 static int _DB_get_type(DBObject* self)
269 #if (DBVER >= 33)
270 DBTYPE type;
271 int err;
272 err = self->db->get_type(self->db, &type);
273 if (makeDBError(err)) {
274 return -1;
276 return type;
277 #else
278 return self->db->get_type(self->db);
279 #endif
283 /* Create a DBT structure (containing key and data values) from Python
284 strings. Returns 1 on success, 0 on an error. */
285 static int make_dbt(PyObject* obj, DBT* dbt)
287 CLEAR_DBT(*dbt);
288 if (obj == Py_None) {
289 /* no need to do anything, the structure has already been zeroed */
291 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
292 PyErr_SetString(PyExc_TypeError,
293 "Data values must be of type string or None.");
294 return 0;
296 return 1;
300 /* Recno and Queue DBs can have integer keys. This function figures out
301 what's been given, verifies that it's allowed, and then makes the DBT.
303 Caller MUST call FREE_DBT(key) when done. */
304 static int
305 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
307 db_recno_t recno;
308 int type;
310 CLEAR_DBT(*key);
311 if (keyobj == Py_None) {
312 type = _DB_get_type(self);
313 if (type == -1)
314 return 0;
315 if (type == DB_RECNO || type == DB_QUEUE) {
316 PyErr_SetString(
317 PyExc_TypeError,
318 "None keys not allowed for Recno and Queue DB's");
319 return 0;
321 /* no need to do anything, the structure has already been zeroed */
324 else if (PyString_Check(keyobj)) {
325 /* verify access method type */
326 type = _DB_get_type(self);
327 if (type == -1)
328 return 0;
329 if (type == DB_RECNO || type == DB_QUEUE) {
330 PyErr_SetString(
331 PyExc_TypeError,
332 "String keys not allowed for Recno and Queue DB's");
333 return 0;
337 * NOTE(gps): I don't like doing a data copy here, it seems
338 * wasteful. But without a clean way to tell FREE_DBT if it
339 * should free key->data or not we have to. Other places in
340 * the code check for DB_THREAD and forceably set DBT_MALLOC
341 * when we otherwise would leave flags 0 to indicate that.
343 key->data = malloc(PyString_GET_SIZE(keyobj));
344 if (key->data == NULL) {
345 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
346 return 0;
348 memcpy(key->data, PyString_AS_STRING(keyobj),
349 PyString_GET_SIZE(keyobj));
350 key->flags = DB_DBT_REALLOC;
351 key->size = PyString_GET_SIZE(keyobj);
354 else if (PyInt_Check(keyobj)) {
355 /* verify access method type */
356 type = _DB_get_type(self);
357 if (type == -1)
358 return 0;
359 if (type == DB_BTREE && pflags != NULL) {
360 /* if BTREE then an Integer key is allowed with the
361 * DB_SET_RECNO flag */
362 *pflags |= DB_SET_RECNO;
364 else if (type != DB_RECNO && type != DB_QUEUE) {
365 PyErr_SetString(
366 PyExc_TypeError,
367 "Integer keys only allowed for Recno and Queue DB's");
368 return 0;
371 /* Make a key out of the requested recno, use allocated space so DB
372 * will be able to realloc room for the real key if needed. */
373 recno = PyInt_AS_LONG(keyobj);
374 key->data = malloc(sizeof(db_recno_t));
375 if (key->data == NULL) {
376 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
377 return 0;
379 key->ulen = key->size = sizeof(db_recno_t);
380 memcpy(key->data, &recno, sizeof(db_recno_t));
381 key->flags = DB_DBT_REALLOC;
383 else {
384 PyErr_Format(PyExc_TypeError,
385 "String or Integer object expected for key, %s found",
386 Py_TYPE(keyobj)->tp_name);
387 return 0;
390 return 1;
394 /* Add partial record access to an existing DBT data struct.
395 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
396 and the data storage/retrieval will be done using dlen and doff. */
397 static int add_partial_dbt(DBT* d, int dlen, int doff) {
398 /* if neither were set we do nothing (-1 is the default value) */
399 if ((dlen == -1) && (doff == -1)) {
400 return 1;
403 if ((dlen < 0) || (doff < 0)) {
404 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
405 return 0;
408 d->flags = d->flags | DB_DBT_PARTIAL;
409 d->dlen = (unsigned int) dlen;
410 d->doff = (unsigned int) doff;
411 return 1;
414 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
415 /* TODO: make this use the native libc strlcpy() when available (BSD) */
416 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
418 unsigned int srclen, copylen;
420 srclen = strlen(src);
421 if (n <= 0)
422 return srclen;
423 copylen = (srclen > n-1) ? n-1 : srclen;
424 /* populate dest[0] thru dest[copylen-1] */
425 memcpy(dest, src, copylen);
426 /* guarantee null termination */
427 dest[copylen] = 0;
429 return srclen;
432 /* Callback used to save away more information about errors from the DB
433 * library. */
434 static char _db_errmsg[1024];
435 #if (DBVER <= 42)
436 static void _db_errorCallback(const char* prefix, char* msg)
437 #else
438 static void _db_errorCallback(const DB_ENV *db_env,
439 const char* prefix, const char* msg)
440 #endif
442 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
446 /* make a nice exception object to raise for errors. */
447 static int makeDBError(int err)
449 char errTxt[2048]; /* really big, just in case... */
450 PyObject *errObj = NULL;
451 PyObject *errTuple = NULL;
452 int exceptionRaised = 0;
453 unsigned int bytes_left;
455 switch (err) {
456 case 0: /* successful, no error */ break;
458 #if (DBVER < 41)
459 case DB_INCOMPLETE:
460 #if INCOMPLETE_IS_WARNING
461 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
462 /* Ensure that bytes_left never goes negative */
463 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
464 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
465 assert(bytes_left >= 0);
466 strcat(errTxt, " -- ");
467 strncat(errTxt, _db_errmsg, bytes_left);
469 _db_errmsg[0] = 0;
470 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
472 #else /* do an exception instead */
473 errObj = DBIncompleteError;
474 #endif
475 break;
476 #endif /* DBVER < 41 */
478 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
479 case DB_KEYEXIST: errObj = DBKeyExistError; break;
480 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
481 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
482 case DB_NOTFOUND: errObj = DBNotFoundError; break;
483 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
484 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
485 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
486 case DB_NOSERVER: errObj = DBNoServerError; break;
487 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
488 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
489 #if (DBVER >= 33)
490 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
491 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
492 #endif
493 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
495 #if (DBVER >= 43)
496 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
497 case ENOMEM: errObj = PyExc_MemoryError; break;
498 #endif
499 case EINVAL: errObj = DBInvalidArgError; break;
500 case EACCES: errObj = DBAccessError; break;
501 case ENOSPC: errObj = DBNoSpaceError; break;
502 case EAGAIN: errObj = DBAgainError; break;
503 case EBUSY : errObj = DBBusyError; break;
504 case EEXIST: errObj = DBFileExistsError; break;
505 case ENOENT: errObj = DBNoSuchFileError; break;
506 case EPERM : errObj = DBPermissionsError; break;
508 default: errObj = DBError; break;
511 if (errObj != NULL) {
512 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
513 /* Ensure that bytes_left never goes negative */
514 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
515 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
516 assert(bytes_left >= 0);
517 strcat(errTxt, " -- ");
518 strncat(errTxt, _db_errmsg, bytes_left);
520 _db_errmsg[0] = 0;
522 errTuple = Py_BuildValue("(is)", err, errTxt);
523 PyErr_SetObject(errObj, errTuple);
524 Py_DECREF(errTuple);
527 return ((errObj != NULL) || exceptionRaised);
532 /* set a type exception */
533 static void makeTypeError(char* expected, PyObject* found)
535 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
536 expected, Py_TYPE(found)->tp_name);
540 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
541 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
543 if (txnobj == Py_None || txnobj == NULL) {
544 *txn = NULL;
545 return 1;
547 if (DBTxnObject_Check(txnobj)) {
548 *txn = ((DBTxnObject*)txnobj)->txn;
549 return 1;
551 else
552 makeTypeError("DBTxn", txnobj);
553 return 0;
557 /* Delete a key from a database
558 Returns 0 on success, -1 on an error. */
559 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
561 int err;
563 MYDB_BEGIN_ALLOW_THREADS;
564 err = self->db->del(self->db, txn, key, 0);
565 MYDB_END_ALLOW_THREADS;
566 if (makeDBError(err)) {
567 return -1;
569 self->haveStat = 0;
570 return 0;
574 /* Store a key into a database
575 Returns 0 on success, -1 on an error. */
576 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
578 int err;
580 MYDB_BEGIN_ALLOW_THREADS;
581 err = self->db->put(self->db, txn, key, data, flags);
582 MYDB_END_ALLOW_THREADS;
583 if (makeDBError(err)) {
584 return -1;
586 self->haveStat = 0;
587 return 0;
590 /* Get a key/data pair from a cursor */
591 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
592 PyObject *args, PyObject *kwargs, char *format)
594 int err;
595 PyObject* retval = NULL;
596 DBT key, data;
597 int dlen = -1;
598 int doff = -1;
599 int flags = 0;
600 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
602 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
603 &flags, &dlen, &doff))
604 return NULL;
606 CHECK_CURSOR_NOT_CLOSED(self);
608 flags |= extra_flags;
609 CLEAR_DBT(key);
610 CLEAR_DBT(data);
611 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
612 /* Tell BerkeleyDB to malloc the return value (thread safe) */
613 data.flags = DB_DBT_MALLOC;
614 key.flags = DB_DBT_MALLOC;
616 if (!add_partial_dbt(&data, dlen, doff))
617 return NULL;
619 MYDB_BEGIN_ALLOW_THREADS;
620 err = self->dbc->c_get(self->dbc, &key, &data, flags);
621 MYDB_END_ALLOW_THREADS;
623 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
624 && self->mydb->moduleFlags.getReturnsNone) {
625 Py_INCREF(Py_None);
626 retval = Py_None;
628 else if (makeDBError(err)) {
629 retval = NULL;
631 else { /* otherwise, success! */
633 /* if Recno or Queue, return the key as an Int */
634 switch (_DB_get_type(self->mydb)) {
635 case -1:
636 retval = NULL;
637 break;
639 case DB_RECNO:
640 case DB_QUEUE:
641 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
642 data.data, data.size);
643 break;
644 case DB_HASH:
645 case DB_BTREE:
646 default:
647 retval = Py_BuildValue("s#s#", key.data, key.size,
648 data.data, data.size);
649 break;
652 if (!err) {
653 FREE_DBT(key);
654 FREE_DBT(data);
656 return retval;
660 /* add an integer to a dictionary using the given name as a key */
661 static void _addIntToDict(PyObject* dict, char *name, int value)
663 PyObject* v = PyInt_FromLong((long) value);
664 if (!v || PyDict_SetItemString(dict, name, v))
665 PyErr_Clear();
667 Py_XDECREF(v);
670 /* The same, when the value is a time_t */
671 static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
673 PyObject* v;
674 /* if the value fits in regular int, use that. */
675 #ifdef HAVE_LONG_LONG
676 if (sizeof(time_t) > sizeof(long))
677 v = PyLong_FromLongLong((PY_LONG_LONG) value);
678 else
679 #endif
680 v = PyInt_FromLong((long) value);
681 if (!v || PyDict_SetItemString(dict, name, v))
682 PyErr_Clear();
684 Py_XDECREF(v);
687 #if (DBVER >= 43)
688 /* add an db_seq_t to a dictionary using the given name as a key */
689 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
691 PyObject* v = PyLong_FromLongLong(value);
692 if (!v || PyDict_SetItemString(dict, name, v))
693 PyErr_Clear();
695 Py_XDECREF(v);
697 #endif
701 /* --------------------------------------------------------------------- */
702 /* Allocators and deallocators */
704 static DBObject*
705 newDBObject(DBEnvObject* arg, int flags)
707 DBObject* self;
708 DB_ENV* db_env = NULL;
709 int err;
711 self = PyObject_New(DBObject, &DB_Type);
712 if (self == NULL)
713 return NULL;
715 self->haveStat = 0;
716 self->flags = 0;
717 self->setflags = 0;
718 self->myenvobj = NULL;
719 #if (DBVER >= 33)
720 self->associateCallback = NULL;
721 self->btCompareCallback = NULL;
722 self->primaryDBType = 0;
723 #endif
724 self->in_weakreflist = NULL;
726 /* keep a reference to our python DBEnv object */
727 if (arg) {
728 Py_INCREF(arg);
729 self->myenvobj = arg;
730 db_env = arg->db_env;
733 if (self->myenvobj)
734 self->moduleFlags = self->myenvobj->moduleFlags;
735 else
736 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
737 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
739 MYDB_BEGIN_ALLOW_THREADS;
740 err = db_create(&self->db, db_env, flags);
741 if (self->db != NULL) {
742 self->db->set_errcall(self->db, _db_errorCallback);
743 #if (DBVER >= 33)
744 self->db->app_private = (void*)self;
745 #endif
747 MYDB_END_ALLOW_THREADS;
748 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
749 * list so that a DBEnv can refuse to close without aborting any open
750 * DBTxns and closing any open DBs first. */
751 if (makeDBError(err)) {
752 if (self->myenvobj) {
753 Py_DECREF(self->myenvobj);
754 self->myenvobj = NULL;
756 PyObject_Del(self);
757 self = NULL;
759 return self;
763 static void
764 DB_dealloc(DBObject* self)
766 if (self->db != NULL) {
767 /* avoid closing a DB when its DBEnv has been closed out from under
768 * it */
769 if (!self->myenvobj ||
770 (self->myenvobj && self->myenvobj->db_env))
772 MYDB_BEGIN_ALLOW_THREADS;
773 self->db->close(self->db, 0);
774 MYDB_END_ALLOW_THREADS;
775 } else {
776 PyErr_Warn(PyExc_RuntimeWarning,
777 "DB could not be closed in destructor: DBEnv already closed");
779 self->db = NULL;
781 if (self->in_weakreflist != NULL) {
782 PyObject_ClearWeakRefs((PyObject *) self);
784 if (self->myenvobj) {
785 Py_DECREF(self->myenvobj);
786 self->myenvobj = NULL;
788 #if (DBVER >= 33)
789 if (self->associateCallback != NULL) {
790 Py_DECREF(self->associateCallback);
791 self->associateCallback = NULL;
793 if (self->btCompareCallback != NULL) {
794 Py_DECREF(self->btCompareCallback);
795 self->btCompareCallback = NULL;
797 #endif
798 PyObject_Del(self);
802 static DBCursorObject*
803 newDBCursorObject(DBC* dbc, DBObject* db)
805 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
806 if (self == NULL)
807 return NULL;
809 self->dbc = dbc;
810 self->mydb = db;
811 self->in_weakreflist = NULL;
812 Py_INCREF(self->mydb);
813 return self;
817 static void
818 DBCursor_dealloc(DBCursorObject* self)
820 int err;
822 if (self->in_weakreflist != NULL) {
823 PyObject_ClearWeakRefs((PyObject *) self);
826 if (self->dbc != NULL) {
827 /* If the underlying database has been closed, we don't
828 need to do anything. If the environment has been closed
829 we need to leak, as BerkeleyDB will crash trying to access
830 the environment. There was an exception when the
831 user closed the environment even though there still was
832 a database open. */
833 if (self->mydb->db && self->mydb->myenvobj &&
834 !self->mydb->myenvobj->closed)
835 /* test for: open db + no environment or non-closed environment */
836 if (self->mydb->db && (!self->mydb->myenvobj || (self->mydb->myenvobj &&
837 !self->mydb->myenvobj->closed))) {
838 MYDB_BEGIN_ALLOW_THREADS;
839 err = self->dbc->c_close(self->dbc);
840 MYDB_END_ALLOW_THREADS;
842 self->dbc = NULL;
844 Py_XDECREF( self->mydb );
845 PyObject_Del(self);
849 static DBEnvObject*
850 newDBEnvObject(int flags)
852 int err;
853 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
854 if (self == NULL)
855 return NULL;
857 self->closed = 1;
858 self->flags = flags;
859 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
860 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
861 self->in_weakreflist = NULL;
863 MYDB_BEGIN_ALLOW_THREADS;
864 err = db_env_create(&self->db_env, flags);
865 MYDB_END_ALLOW_THREADS;
866 if (makeDBError(err)) {
867 PyObject_Del(self);
868 self = NULL;
870 else {
871 self->db_env->set_errcall(self->db_env, _db_errorCallback);
873 return self;
877 static void
878 DBEnv_dealloc(DBEnvObject* self)
880 if (self->in_weakreflist != NULL) {
881 PyObject_ClearWeakRefs((PyObject *) self);
884 if (self->db_env && !self->closed) {
885 MYDB_BEGIN_ALLOW_THREADS;
886 self->db_env->close(self->db_env, 0);
887 MYDB_END_ALLOW_THREADS;
889 PyObject_Del(self);
893 static DBTxnObject*
894 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
896 int err;
897 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
898 if (self == NULL)
899 return NULL;
900 Py_INCREF(myenv);
901 self->env = (PyObject*)myenv;
902 self->in_weakreflist = NULL;
904 MYDB_BEGIN_ALLOW_THREADS;
905 #if (DBVER >= 40)
906 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
907 #else
908 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
909 #endif
910 MYDB_END_ALLOW_THREADS;
911 if (makeDBError(err)) {
912 Py_DECREF(self->env);
913 PyObject_Del(self);
914 self = NULL;
916 return self;
920 static void
921 DBTxn_dealloc(DBTxnObject* self)
923 if (self->in_weakreflist != NULL) {
924 PyObject_ClearWeakRefs((PyObject *) self);
927 if (self->txn) {
928 /* it hasn't been finalized, abort it! */
929 MYDB_BEGIN_ALLOW_THREADS;
930 #if (DBVER >= 40)
931 self->txn->abort(self->txn);
932 #else
933 txn_abort(self->txn);
934 #endif
935 MYDB_END_ALLOW_THREADS;
936 PyErr_Warn(PyExc_RuntimeWarning,
937 "DBTxn aborted in destructor. No prior commit() or abort().");
940 Py_DECREF(self->env);
941 PyObject_Del(self);
945 static DBLockObject*
946 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
947 db_lockmode_t lock_mode, int flags)
949 int err;
950 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
951 if (self == NULL)
952 return NULL;
953 self->in_weakreflist = NULL;
955 MYDB_BEGIN_ALLOW_THREADS;
956 #if (DBVER >= 40)
957 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
958 &self->lock);
959 #else
960 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
961 #endif
962 MYDB_END_ALLOW_THREADS;
963 if (makeDBError(err)) {
964 PyObject_Del(self);
965 self = NULL;
968 return self;
972 static void
973 DBLock_dealloc(DBLockObject* self)
975 if (self->in_weakreflist != NULL) {
976 PyObject_ClearWeakRefs((PyObject *) self);
978 /* TODO: is this lock held? should we release it? */
980 PyObject_Del(self);
984 #if (DBVER >= 43)
985 static DBSequenceObject*
986 newDBSequenceObject(DBObject* mydb, int flags)
988 int err;
989 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
990 if (self == NULL)
991 return NULL;
992 Py_INCREF(mydb);
993 self->mydb = mydb;
994 self->in_weakreflist = NULL;
997 MYDB_BEGIN_ALLOW_THREADS;
998 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
999 MYDB_END_ALLOW_THREADS;
1000 if (makeDBError(err)) {
1001 Py_DECREF(self->mydb);
1002 PyObject_Del(self);
1003 self = NULL;
1006 return self;
1010 static void
1011 DBSequence_dealloc(DBSequenceObject* self)
1013 if (self->in_weakreflist != NULL) {
1014 PyObject_ClearWeakRefs((PyObject *) self);
1017 Py_DECREF(self->mydb);
1018 PyObject_Del(self);
1020 #endif
1022 /* --------------------------------------------------------------------- */
1023 /* DB methods */
1025 static PyObject*
1026 DB_append(DBObject* self, PyObject* args)
1028 PyObject* txnobj = NULL;
1029 PyObject* dataobj;
1030 db_recno_t recno;
1031 DBT key, data;
1032 DB_TXN *txn = NULL;
1034 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1035 return NULL;
1037 CHECK_DB_NOT_CLOSED(self);
1039 /* make a dummy key out of a recno */
1040 recno = 0;
1041 CLEAR_DBT(key);
1042 key.data = &recno;
1043 key.size = sizeof(recno);
1044 key.ulen = key.size;
1045 key.flags = DB_DBT_USERMEM;
1047 if (!make_dbt(dataobj, &data)) return NULL;
1048 if (!checkTxnObj(txnobj, &txn)) return NULL;
1050 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1051 return NULL;
1053 return PyInt_FromLong(recno);
1057 #if (DBVER >= 33)
1059 static int
1060 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1061 DBT* secKey)
1063 int retval = DB_DONOTINDEX;
1064 DBObject* secondaryDB = (DBObject*)db->app_private;
1065 PyObject* callback = secondaryDB->associateCallback;
1066 int type = secondaryDB->primaryDBType;
1067 PyObject* args;
1068 PyObject* result = NULL;
1071 if (callback != NULL) {
1072 MYDB_BEGIN_BLOCK_THREADS;
1074 if (type == DB_RECNO || type == DB_QUEUE)
1075 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1076 priData->data, priData->size);
1077 else
1078 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1079 priData->data, priData->size);
1080 if (args != NULL) {
1081 result = PyEval_CallObject(callback, args);
1083 if (args == NULL || result == NULL) {
1084 PyErr_Print();
1086 else if (result == Py_None) {
1087 retval = DB_DONOTINDEX;
1089 else if (PyInt_Check(result)) {
1090 retval = PyInt_AsLong(result);
1092 else if (PyString_Check(result)) {
1093 char* data;
1094 Py_ssize_t size;
1096 CLEAR_DBT(*secKey);
1097 PyString_AsStringAndSize(result, &data, &size);
1098 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1099 secKey->data = malloc(size); /* TODO, check this */
1100 if (secKey->data) {
1101 memcpy(secKey->data, data, size);
1102 secKey->size = size;
1103 retval = 0;
1105 else {
1106 PyErr_SetString(PyExc_MemoryError,
1107 "malloc failed in _db_associateCallback");
1108 PyErr_Print();
1111 else {
1112 PyErr_SetString(
1113 PyExc_TypeError,
1114 "DB associate callback should return DB_DONOTINDEX or string.");
1115 PyErr_Print();
1118 Py_XDECREF(args);
1119 Py_XDECREF(result);
1121 MYDB_END_BLOCK_THREADS;
1123 return retval;
1127 static PyObject*
1128 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1130 int err, flags=0;
1131 DBObject* secondaryDB;
1132 PyObject* callback;
1133 #if (DBVER >= 41)
1134 PyObject *txnobj = NULL;
1135 DB_TXN *txn = NULL;
1136 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1137 NULL};
1138 #else
1139 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1140 #endif
1142 #if (DBVER >= 41)
1143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1144 &secondaryDB, &callback, &flags,
1145 &txnobj)) {
1146 #else
1147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1148 &secondaryDB, &callback, &flags)) {
1149 #endif
1150 return NULL;
1153 #if (DBVER >= 41)
1154 if (!checkTxnObj(txnobj, &txn)) return NULL;
1155 #endif
1157 CHECK_DB_NOT_CLOSED(self);
1158 if (!DBObject_Check(secondaryDB)) {
1159 makeTypeError("DB", (PyObject*)secondaryDB);
1160 return NULL;
1162 CHECK_DB_NOT_CLOSED(secondaryDB);
1163 if (callback == Py_None) {
1164 callback = NULL;
1166 else if (!PyCallable_Check(callback)) {
1167 makeTypeError("Callable", callback);
1168 return NULL;
1171 /* Save a reference to the callback in the secondary DB. */
1172 Py_XDECREF(secondaryDB->associateCallback);
1173 Py_XINCREF(callback);
1174 secondaryDB->associateCallback = callback;
1175 secondaryDB->primaryDBType = _DB_get_type(self);
1177 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1178 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1179 * The global interepreter lock is not initialized until the first
1180 * thread is created using thread.start_new_thread() or fork() is
1181 * called. that would cause the ALLOW_THREADS here to segfault due
1182 * to a null pointer reference if no threads or child processes
1183 * have been created. This works around that and is a no-op if
1184 * threads have already been initialized.
1185 * (see pybsddb-users mailing list post on 2002-08-07)
1187 #ifdef WITH_THREAD
1188 PyEval_InitThreads();
1189 #endif
1190 MYDB_BEGIN_ALLOW_THREADS;
1191 #if (DBVER >= 41)
1192 err = self->db->associate(self->db,
1193 txn,
1194 secondaryDB->db,
1195 _db_associateCallback,
1196 flags);
1197 #else
1198 err = self->db->associate(self->db,
1199 secondaryDB->db,
1200 _db_associateCallback,
1201 flags);
1202 #endif
1203 MYDB_END_ALLOW_THREADS;
1205 if (err) {
1206 Py_XDECREF(secondaryDB->associateCallback);
1207 secondaryDB->associateCallback = NULL;
1208 secondaryDB->primaryDBType = 0;
1211 RETURN_IF_ERR();
1212 RETURN_NONE();
1216 #endif
1219 static PyObject*
1220 DB_close(DBObject* self, PyObject* args)
1222 int err, flags=0;
1223 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1224 return NULL;
1225 if (self->db != NULL) {
1226 if (self->myenvobj)
1227 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1228 err = self->db->close(self->db, flags);
1229 self->db = NULL;
1230 RETURN_IF_ERR();
1232 RETURN_NONE();
1236 static PyObject*
1237 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1239 int err, flags=0, type;
1240 PyObject* txnobj = NULL;
1241 PyObject* retval = NULL;
1242 DBT key, data;
1243 DB_TXN *txn = NULL;
1244 static char* kwnames[] = { "txn", "flags", NULL };
1246 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1247 &txnobj, &flags))
1248 return NULL;
1250 CHECK_DB_NOT_CLOSED(self);
1251 type = _DB_get_type(self);
1252 if (type == -1)
1253 return NULL;
1254 if (type != DB_QUEUE) {
1255 PyErr_SetString(PyExc_TypeError,
1256 "Consume methods only allowed for Queue DB's");
1257 return NULL;
1259 if (!checkTxnObj(txnobj, &txn))
1260 return NULL;
1262 CLEAR_DBT(key);
1263 CLEAR_DBT(data);
1264 if (CHECK_DBFLAG(self, DB_THREAD)) {
1265 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1266 data.flags = DB_DBT_MALLOC;
1267 key.flags = DB_DBT_MALLOC;
1270 MYDB_BEGIN_ALLOW_THREADS;
1271 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1272 MYDB_END_ALLOW_THREADS;
1274 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1275 && self->moduleFlags.getReturnsNone) {
1276 err = 0;
1277 Py_INCREF(Py_None);
1278 retval = Py_None;
1280 else if (!err) {
1281 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1282 data.size);
1283 FREE_DBT(key);
1284 FREE_DBT(data);
1287 RETURN_IF_ERR();
1288 return retval;
1291 static PyObject*
1292 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1294 return _DB_consume(self, args, kwargs, DB_CONSUME);
1297 static PyObject*
1298 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1299 int consume_flag)
1301 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1305 static PyObject*
1306 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1308 int err, flags=0;
1309 DBC* dbc;
1310 PyObject* txnobj = NULL;
1311 DB_TXN *txn = NULL;
1312 static char* kwnames[] = { "txn", "flags", NULL };
1314 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1315 &txnobj, &flags))
1316 return NULL;
1317 CHECK_DB_NOT_CLOSED(self);
1318 if (!checkTxnObj(txnobj, &txn))
1319 return NULL;
1321 MYDB_BEGIN_ALLOW_THREADS;
1322 err = self->db->cursor(self->db, txn, &dbc, flags);
1323 MYDB_END_ALLOW_THREADS;
1324 RETURN_IF_ERR();
1325 return (PyObject*) newDBCursorObject(dbc, self);
1329 static PyObject*
1330 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1332 PyObject* txnobj = NULL;
1333 int flags = 0;
1334 PyObject* keyobj;
1335 DBT key;
1336 DB_TXN *txn = NULL;
1337 static char* kwnames[] = { "key", "txn", "flags", NULL };
1339 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1340 &keyobj, &txnobj, &flags))
1341 return NULL;
1342 CHECK_DB_NOT_CLOSED(self);
1343 if (!make_key_dbt(self, keyobj, &key, NULL))
1344 return NULL;
1345 if (!checkTxnObj(txnobj, &txn)) {
1346 FREE_DBT(key);
1347 return NULL;
1350 if (-1 == _DB_delete(self, txn, &key, 0)) {
1351 FREE_DBT(key);
1352 return NULL;
1355 FREE_DBT(key);
1356 RETURN_NONE();
1360 static PyObject*
1361 DB_fd(DBObject* self, PyObject* args)
1363 int err, the_fd;
1365 if (!PyArg_ParseTuple(args,":fd"))
1366 return NULL;
1367 CHECK_DB_NOT_CLOSED(self);
1369 MYDB_BEGIN_ALLOW_THREADS;
1370 err = self->db->fd(self->db, &the_fd);
1371 MYDB_END_ALLOW_THREADS;
1372 RETURN_IF_ERR();
1373 return PyInt_FromLong(the_fd);
1377 static PyObject*
1378 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1380 int err, flags=0;
1381 PyObject* txnobj = NULL;
1382 PyObject* keyobj;
1383 PyObject* dfltobj = NULL;
1384 PyObject* retval = NULL;
1385 int dlen = -1;
1386 int doff = -1;
1387 DBT key, data;
1388 DB_TXN *txn = NULL;
1389 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1390 "doff", NULL};
1392 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1393 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1394 &doff))
1395 return NULL;
1397 CHECK_DB_NOT_CLOSED(self);
1398 if (!make_key_dbt(self, keyobj, &key, &flags))
1399 return NULL;
1400 if (!checkTxnObj(txnobj, &txn)) {
1401 FREE_DBT(key);
1402 return NULL;
1405 CLEAR_DBT(data);
1406 if (CHECK_DBFLAG(self, DB_THREAD)) {
1407 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1408 data.flags = DB_DBT_MALLOC;
1410 if (!add_partial_dbt(&data, dlen, doff)) {
1411 FREE_DBT(key);
1412 return NULL;
1415 MYDB_BEGIN_ALLOW_THREADS;
1416 err = self->db->get(self->db, txn, &key, &data, flags);
1417 MYDB_END_ALLOW_THREADS;
1419 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1420 err = 0;
1421 Py_INCREF(dfltobj);
1422 retval = dfltobj;
1424 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1425 && self->moduleFlags.getReturnsNone) {
1426 err = 0;
1427 Py_INCREF(Py_None);
1428 retval = Py_None;
1430 else if (!err) {
1431 if (flags & DB_SET_RECNO) /* return both key and data */
1432 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1433 data.size);
1434 else /* return just the data */
1435 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1436 FREE_DBT(data);
1438 FREE_DBT(key);
1440 RETURN_IF_ERR();
1441 return retval;
1444 #if (DBVER >= 33)
1445 static PyObject*
1446 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1448 int err, flags=0;
1449 PyObject* txnobj = NULL;
1450 PyObject* keyobj;
1451 PyObject* dfltobj = NULL;
1452 PyObject* retval = NULL;
1453 int dlen = -1;
1454 int doff = -1;
1455 DBT key, pkey, data;
1456 DB_TXN *txn = NULL;
1457 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1458 "doff", NULL};
1460 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1461 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1462 &doff))
1463 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1466 if (!make_key_dbt(self, keyobj, &key, &flags))
1467 return NULL;
1468 if (!checkTxnObj(txnobj, &txn)) {
1469 FREE_DBT(key);
1470 return NULL;
1473 CLEAR_DBT(data);
1474 if (CHECK_DBFLAG(self, DB_THREAD)) {
1475 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1476 data.flags = DB_DBT_MALLOC;
1478 if (!add_partial_dbt(&data, dlen, doff)) {
1479 FREE_DBT(key);
1480 return NULL;
1483 CLEAR_DBT(pkey);
1484 pkey.flags = DB_DBT_MALLOC;
1486 MYDB_BEGIN_ALLOW_THREADS;
1487 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1488 MYDB_END_ALLOW_THREADS;
1490 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1491 err = 0;
1492 Py_INCREF(dfltobj);
1493 retval = dfltobj;
1495 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1496 && self->moduleFlags.getReturnsNone) {
1497 err = 0;
1498 Py_INCREF(Py_None);
1499 retval = Py_None;
1501 else if (!err) {
1502 PyObject *pkeyObj;
1503 PyObject *dataObj;
1504 dataObj = PyString_FromStringAndSize(data.data, data.size);
1506 if (self->primaryDBType == DB_RECNO ||
1507 self->primaryDBType == DB_QUEUE)
1508 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1509 else
1510 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1512 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1514 PyObject *keyObj;
1515 int type = _DB_get_type(self);
1516 if (type == DB_RECNO || type == DB_QUEUE)
1517 keyObj = PyInt_FromLong(*(int *)key.data);
1518 else
1519 keyObj = PyString_FromStringAndSize(key.data, key.size);
1520 #if (PY_VERSION_HEX >= 0x02040000)
1521 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1522 #else
1523 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1524 #endif
1525 Py_DECREF(keyObj);
1527 else /* return just the pkey and data */
1529 #if (PY_VERSION_HEX >= 0x02040000)
1530 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1531 #else
1532 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1533 #endif
1535 Py_DECREF(dataObj);
1536 Py_DECREF(pkeyObj);
1537 FREE_DBT(pkey);
1538 FREE_DBT(data);
1540 FREE_DBT(key);
1542 RETURN_IF_ERR();
1543 return retval;
1545 #endif
1548 /* Return size of entry */
1549 static PyObject*
1550 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1552 int err, flags=0;
1553 PyObject* txnobj = NULL;
1554 PyObject* keyobj;
1555 PyObject* retval = NULL;
1556 DBT key, data;
1557 DB_TXN *txn = NULL;
1558 static char* kwnames[] = { "key", "txn", NULL };
1560 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1561 &keyobj, &txnobj))
1562 return NULL;
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1570 CLEAR_DBT(data);
1572 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1573 thus getting the record size. */
1574 data.flags = DB_DBT_USERMEM;
1575 data.ulen = 0;
1576 MYDB_BEGIN_ALLOW_THREADS;
1577 err = self->db->get(self->db, txn, &key, &data, flags);
1578 MYDB_END_ALLOW_THREADS;
1579 if (err == DB_BUFFER_SMALL) {
1580 retval = PyInt_FromLong((long)data.size);
1581 err = 0;
1584 FREE_DBT(key);
1585 FREE_DBT(data);
1586 RETURN_IF_ERR();
1587 return retval;
1591 static PyObject*
1592 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1594 int err, flags=0;
1595 PyObject* txnobj = NULL;
1596 PyObject* keyobj;
1597 PyObject* dataobj;
1598 PyObject* retval = NULL;
1599 DBT key, data;
1600 void *orig_data;
1601 DB_TXN *txn = NULL;
1602 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1605 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1606 &keyobj, &dataobj, &txnobj, &flags))
1607 return NULL;
1609 CHECK_DB_NOT_CLOSED(self);
1610 if (!make_key_dbt(self, keyobj, &key, NULL))
1611 return NULL;
1612 if ( !make_dbt(dataobj, &data) ||
1613 !checkTxnObj(txnobj, &txn) )
1615 FREE_DBT(key);
1616 return NULL;
1619 flags |= DB_GET_BOTH;
1620 orig_data = data.data;
1622 if (CHECK_DBFLAG(self, DB_THREAD)) {
1623 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1624 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1625 data.flags = DB_DBT_MALLOC;
1628 MYDB_BEGIN_ALLOW_THREADS;
1629 err = self->db->get(self->db, txn, &key, &data, flags);
1630 MYDB_END_ALLOW_THREADS;
1632 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1633 && self->moduleFlags.getReturnsNone) {
1634 err = 0;
1635 Py_INCREF(Py_None);
1636 retval = Py_None;
1638 else if (!err) {
1639 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1640 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1642 /* Even though the flags require DB_DBT_MALLOC, data is not always
1643 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1644 if (data.data != orig_data)
1645 FREE_DBT(data);
1648 FREE_DBT(key);
1649 RETURN_IF_ERR();
1650 return retval;
1654 static PyObject*
1655 DB_get_byteswapped(DBObject* self, PyObject* args)
1657 #if (DBVER >= 33)
1658 int err = 0;
1659 #endif
1660 int retval = -1;
1662 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1663 return NULL;
1664 CHECK_DB_NOT_CLOSED(self);
1666 #if (DBVER >= 33)
1667 MYDB_BEGIN_ALLOW_THREADS;
1668 err = self->db->get_byteswapped(self->db, &retval);
1669 MYDB_END_ALLOW_THREADS;
1670 RETURN_IF_ERR();
1671 #else
1672 MYDB_BEGIN_ALLOW_THREADS;
1673 retval = self->db->get_byteswapped(self->db);
1674 MYDB_END_ALLOW_THREADS;
1675 #endif
1676 return PyInt_FromLong(retval);
1680 static PyObject*
1681 DB_get_type(DBObject* self, PyObject* args)
1683 int type;
1685 if (!PyArg_ParseTuple(args,":get_type"))
1686 return NULL;
1687 CHECK_DB_NOT_CLOSED(self);
1689 type = _DB_get_type(self);
1690 if (type == -1)
1691 return NULL;
1692 return PyInt_FromLong(type);
1696 static PyObject*
1697 DB_join(DBObject* self, PyObject* args)
1699 int err, flags=0;
1700 int length, x;
1701 PyObject* cursorsObj;
1702 DBC** cursors;
1703 DBC* dbc;
1705 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1706 return NULL;
1708 CHECK_DB_NOT_CLOSED(self);
1710 if (!PySequence_Check(cursorsObj)) {
1711 PyErr_SetString(PyExc_TypeError,
1712 "Sequence of DBCursor objects expected");
1713 return NULL;
1716 length = PyObject_Length(cursorsObj);
1717 cursors = malloc((length+1) * sizeof(DBC*));
1718 if (!cursors) {
1719 PyErr_NoMemory();
1720 return NULL;
1723 cursors[length] = NULL;
1724 for (x=0; x<length; x++) {
1725 PyObject* item = PySequence_GetItem(cursorsObj, x);
1726 if (item == NULL) {
1727 free(cursors);
1728 return NULL;
1730 if (!DBCursorObject_Check(item)) {
1731 PyErr_SetString(PyExc_TypeError,
1732 "Sequence of DBCursor objects expected");
1733 free(cursors);
1734 return NULL;
1736 cursors[x] = ((DBCursorObject*)item)->dbc;
1737 Py_DECREF(item);
1740 MYDB_BEGIN_ALLOW_THREADS;
1741 err = self->db->join(self->db, cursors, &dbc, flags);
1742 MYDB_END_ALLOW_THREADS;
1743 free(cursors);
1744 RETURN_IF_ERR();
1746 /* FIXME: this is a buggy interface. The returned cursor
1747 contains internal references to the passed in cursors
1748 but does not hold python references to them or prevent
1749 them from being closed prematurely. This can cause
1750 python to crash when things are done in the wrong order. */
1751 return (PyObject*) newDBCursorObject(dbc, self);
1755 static PyObject*
1756 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1758 int err, flags=0;
1759 PyObject* txnobj = NULL;
1760 PyObject* keyobj;
1761 DBT key;
1762 DB_TXN *txn = NULL;
1763 DB_KEY_RANGE range;
1764 static char* kwnames[] = { "key", "txn", "flags", NULL };
1766 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1767 &keyobj, &txnobj, &flags))
1768 return NULL;
1769 CHECK_DB_NOT_CLOSED(self);
1770 if (!make_dbt(keyobj, &key))
1771 /* BTree only, don't need to allow for an int key */
1772 return NULL;
1773 if (!checkTxnObj(txnobj, &txn))
1774 return NULL;
1776 MYDB_BEGIN_ALLOW_THREADS;
1777 err = self->db->key_range(self->db, txn, &key, &range, flags);
1778 MYDB_END_ALLOW_THREADS;
1780 RETURN_IF_ERR();
1781 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1785 static PyObject*
1786 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1788 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1789 char* filename = NULL;
1790 char* dbname = NULL;
1791 #if (DBVER >= 41)
1792 PyObject *txnobj = NULL;
1793 DB_TXN *txn = NULL;
1794 /* with dbname */
1795 static char* kwnames[] = {
1796 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1797 /* without dbname */
1798 static char* kwnames_basic[] = {
1799 "filename", "dbtype", "flags", "mode", "txn", NULL};
1800 #else
1801 /* with dbname */
1802 static char* kwnames[] = {
1803 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1804 /* without dbname */
1805 static char* kwnames_basic[] = {
1806 "filename", "dbtype", "flags", "mode", NULL};
1807 #endif
1809 #if (DBVER >= 41)
1810 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1811 &filename, &dbname, &type, &flags, &mode,
1812 &txnobj))
1813 #else
1814 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1815 &filename, &dbname, &type, &flags,
1816 &mode))
1817 #endif
1819 PyErr_Clear();
1820 type = DB_UNKNOWN; flags = 0; mode = 0660;
1821 filename = NULL; dbname = NULL;
1822 #if (DBVER >= 41)
1823 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1824 kwnames_basic,
1825 &filename, &type, &flags, &mode,
1826 &txnobj))
1827 return NULL;
1828 #else
1829 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1830 kwnames_basic,
1831 &filename, &type, &flags, &mode))
1832 return NULL;
1833 #endif
1836 #if (DBVER >= 41)
1837 if (!checkTxnObj(txnobj, &txn)) return NULL;
1838 #endif
1840 if (NULL == self->db) {
1841 PyObject *t = Py_BuildValue("(is)", 0,
1842 "Cannot call open() twice for DB object");
1843 PyErr_SetObject(DBError, t);
1844 Py_DECREF(t);
1845 return NULL;
1848 MYDB_BEGIN_ALLOW_THREADS;
1849 #if (DBVER >= 41)
1850 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1851 #else
1852 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1853 #endif
1854 MYDB_END_ALLOW_THREADS;
1855 if (makeDBError(err)) {
1856 self->db->close(self->db, 0);
1857 self->db = NULL;
1858 return NULL;
1861 #if (DBVER >= 42)
1862 self->db->get_flags(self->db, &self->setflags);
1863 #endif
1865 self->flags = flags;
1866 RETURN_NONE();
1870 static PyObject*
1871 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1873 int flags=0;
1874 PyObject* txnobj = NULL;
1875 int dlen = -1;
1876 int doff = -1;
1877 PyObject* keyobj, *dataobj, *retval;
1878 DBT key, data;
1879 DB_TXN *txn = NULL;
1880 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1881 "doff", NULL };
1883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1884 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1885 return NULL;
1887 CHECK_DB_NOT_CLOSED(self);
1888 if (!make_key_dbt(self, keyobj, &key, NULL))
1889 return NULL;
1890 if ( !make_dbt(dataobj, &data) ||
1891 !add_partial_dbt(&data, dlen, doff) ||
1892 !checkTxnObj(txnobj, &txn) )
1894 FREE_DBT(key);
1895 return NULL;
1898 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1899 FREE_DBT(key);
1900 return NULL;
1903 if (flags & DB_APPEND)
1904 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1905 else {
1906 retval = Py_None;
1907 Py_INCREF(retval);
1909 FREE_DBT(key);
1910 return retval;
1915 static PyObject*
1916 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1918 char* filename;
1919 char* database = NULL;
1920 int err, flags=0;
1921 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
1923 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1924 &filename, &database, &flags))
1925 return NULL;
1926 CHECK_DB_NOT_CLOSED(self);
1928 err = self->db->remove(self->db, filename, database, flags);
1929 self->db = NULL;
1930 RETURN_IF_ERR();
1931 RETURN_NONE();
1936 static PyObject*
1937 DB_rename(DBObject* self, PyObject* args)
1939 char* filename;
1940 char* database;
1941 char* newname;
1942 int err, flags=0;
1944 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1945 &flags))
1946 return NULL;
1947 CHECK_DB_NOT_CLOSED(self);
1949 MYDB_BEGIN_ALLOW_THREADS;
1950 err = self->db->rename(self->db, filename, database, newname, flags);
1951 MYDB_END_ALLOW_THREADS;
1952 RETURN_IF_ERR();
1953 RETURN_NONE();
1957 static PyObject*
1958 DB_set_bt_minkey(DBObject* self, PyObject* args)
1960 int err, minkey;
1962 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1963 return NULL;
1964 CHECK_DB_NOT_CLOSED(self);
1966 MYDB_BEGIN_ALLOW_THREADS;
1967 err = self->db->set_bt_minkey(self->db, minkey);
1968 MYDB_END_ALLOW_THREADS;
1969 RETURN_IF_ERR();
1970 RETURN_NONE();
1973 #if (DBVER >= 33)
1974 static int
1975 _default_cmp(const DBT *leftKey,
1976 const DBT *rightKey)
1978 int res;
1979 int lsize = leftKey->size, rsize = rightKey->size;
1981 res = memcmp(leftKey->data, rightKey->data,
1982 lsize < rsize ? lsize : rsize);
1984 if (res == 0) {
1985 if (lsize < rsize) {
1986 res = -1;
1988 else if (lsize > rsize) {
1989 res = 1;
1992 return res;
1995 static int
1996 _db_compareCallback(DB* db,
1997 const DBT *leftKey,
1998 const DBT *rightKey)
2000 int res = 0;
2001 PyObject *args;
2002 PyObject *result = NULL;
2003 DBObject *self = (DBObject *)db->app_private;
2005 if (self == NULL || self->btCompareCallback == NULL) {
2006 MYDB_BEGIN_BLOCK_THREADS;
2007 PyErr_SetString(PyExc_TypeError,
2008 (self == 0
2009 ? "DB_bt_compare db is NULL."
2010 : "DB_bt_compare callback is NULL."));
2011 /* we're in a callback within the DB code, we can't raise */
2012 PyErr_Print();
2013 res = _default_cmp(leftKey, rightKey);
2014 MYDB_END_BLOCK_THREADS;
2015 } else {
2016 MYDB_BEGIN_BLOCK_THREADS;
2018 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2019 rightKey->data, rightKey->size);
2020 if (args != NULL) {
2021 /* XXX(twouters) I highly doubt this INCREF is correct */
2022 Py_INCREF(self);
2023 result = PyEval_CallObject(self->btCompareCallback, args);
2025 if (args == NULL || result == NULL) {
2026 /* we're in a callback within the DB code, we can't raise */
2027 PyErr_Print();
2028 res = _default_cmp(leftKey, rightKey);
2029 } else if (PyInt_Check(result)) {
2030 res = PyInt_AsLong(result);
2031 } else {
2032 PyErr_SetString(PyExc_TypeError,
2033 "DB_bt_compare callback MUST return an int.");
2034 /* we're in a callback within the DB code, we can't raise */
2035 PyErr_Print();
2036 res = _default_cmp(leftKey, rightKey);
2039 Py_XDECREF(args);
2040 Py_XDECREF(result);
2042 MYDB_END_BLOCK_THREADS;
2044 return res;
2047 static PyObject*
2048 DB_set_bt_compare(DBObject* self, PyObject* args)
2050 int err;
2051 PyObject *comparator;
2052 PyObject *tuple, *result;
2054 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2055 return NULL;
2057 CHECK_DB_NOT_CLOSED(self);
2059 if (!PyCallable_Check(comparator)) {
2060 makeTypeError("Callable", comparator);
2061 return NULL;
2065 * Perform a test call of the comparator function with two empty
2066 * string objects here. verify that it returns an int (0).
2067 * err if not.
2069 tuple = Py_BuildValue("(ss)", "", "");
2070 result = PyEval_CallObject(comparator, tuple);
2071 Py_DECREF(tuple);
2072 if (result == NULL)
2073 return NULL;
2074 if (!PyInt_Check(result)) {
2075 PyErr_SetString(PyExc_TypeError,
2076 "callback MUST return an int");
2077 return NULL;
2078 } else if (PyInt_AsLong(result) != 0) {
2079 PyErr_SetString(PyExc_TypeError,
2080 "callback failed to return 0 on two empty strings");
2081 return NULL;
2083 Py_DECREF(result);
2085 /* We don't accept multiple set_bt_compare operations, in order to
2086 * simplify the code. This would have no real use, as one cannot
2087 * change the function once the db is opened anyway */
2088 if (self->btCompareCallback != NULL) {
2089 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2090 return NULL;
2093 Py_INCREF(comparator);
2094 self->btCompareCallback = comparator;
2096 /* This is to workaround a problem with un-initialized threads (see
2097 comment in DB_associate) */
2098 #ifdef WITH_THREAD
2099 PyEval_InitThreads();
2100 #endif
2102 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2104 if (err) {
2105 /* restore the old state in case of error */
2106 Py_DECREF(comparator);
2107 self->btCompareCallback = NULL;
2110 RETURN_IF_ERR();
2111 RETURN_NONE();
2113 #endif /* DBVER >= 33 */
2116 static PyObject*
2117 DB_set_cachesize(DBObject* self, PyObject* args)
2119 int err;
2120 int gbytes = 0, bytes = 0, ncache = 0;
2122 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2123 &gbytes,&bytes,&ncache))
2124 return NULL;
2125 CHECK_DB_NOT_CLOSED(self);
2127 MYDB_BEGIN_ALLOW_THREADS;
2128 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2129 MYDB_END_ALLOW_THREADS;
2130 RETURN_IF_ERR();
2131 RETURN_NONE();
2135 static PyObject*
2136 DB_set_flags(DBObject* self, PyObject* args)
2138 int err, flags;
2140 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2141 return NULL;
2142 CHECK_DB_NOT_CLOSED(self);
2144 MYDB_BEGIN_ALLOW_THREADS;
2145 err = self->db->set_flags(self->db, flags);
2146 MYDB_END_ALLOW_THREADS;
2147 RETURN_IF_ERR();
2149 self->setflags |= flags;
2150 RETURN_NONE();
2154 static PyObject*
2155 DB_set_h_ffactor(DBObject* self, PyObject* args)
2157 int err, ffactor;
2159 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2160 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2163 MYDB_BEGIN_ALLOW_THREADS;
2164 err = self->db->set_h_ffactor(self->db, ffactor);
2165 MYDB_END_ALLOW_THREADS;
2166 RETURN_IF_ERR();
2167 RETURN_NONE();
2171 static PyObject*
2172 DB_set_h_nelem(DBObject* self, PyObject* args)
2174 int err, nelem;
2176 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2177 return NULL;
2178 CHECK_DB_NOT_CLOSED(self);
2180 MYDB_BEGIN_ALLOW_THREADS;
2181 err = self->db->set_h_nelem(self->db, nelem);
2182 MYDB_END_ALLOW_THREADS;
2183 RETURN_IF_ERR();
2184 RETURN_NONE();
2188 static PyObject*
2189 DB_set_lorder(DBObject* self, PyObject* args)
2191 int err, lorder;
2193 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2194 return NULL;
2195 CHECK_DB_NOT_CLOSED(self);
2197 MYDB_BEGIN_ALLOW_THREADS;
2198 err = self->db->set_lorder(self->db, lorder);
2199 MYDB_END_ALLOW_THREADS;
2200 RETURN_IF_ERR();
2201 RETURN_NONE();
2205 static PyObject*
2206 DB_set_pagesize(DBObject* self, PyObject* args)
2208 int err, pagesize;
2210 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2211 return NULL;
2212 CHECK_DB_NOT_CLOSED(self);
2214 MYDB_BEGIN_ALLOW_THREADS;
2215 err = self->db->set_pagesize(self->db, pagesize);
2216 MYDB_END_ALLOW_THREADS;
2217 RETURN_IF_ERR();
2218 RETURN_NONE();
2222 static PyObject*
2223 DB_set_re_delim(DBObject* self, PyObject* args)
2225 int err;
2226 char delim;
2228 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2229 PyErr_Clear();
2230 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2231 return NULL;
2234 CHECK_DB_NOT_CLOSED(self);
2236 MYDB_BEGIN_ALLOW_THREADS;
2237 err = self->db->set_re_delim(self->db, delim);
2238 MYDB_END_ALLOW_THREADS;
2239 RETURN_IF_ERR();
2240 RETURN_NONE();
2243 static PyObject*
2244 DB_set_re_len(DBObject* self, PyObject* args)
2246 int err, len;
2248 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2249 return NULL;
2250 CHECK_DB_NOT_CLOSED(self);
2252 MYDB_BEGIN_ALLOW_THREADS;
2253 err = self->db->set_re_len(self->db, len);
2254 MYDB_END_ALLOW_THREADS;
2255 RETURN_IF_ERR();
2256 RETURN_NONE();
2260 static PyObject*
2261 DB_set_re_pad(DBObject* self, PyObject* args)
2263 int err;
2264 char pad;
2266 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2267 PyErr_Clear();
2268 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2269 return NULL;
2271 CHECK_DB_NOT_CLOSED(self);
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_re_pad(self->db, pad);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2281 static PyObject*
2282 DB_set_re_source(DBObject* self, PyObject* args)
2284 int err;
2285 char *re_source;
2287 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2288 return NULL;
2289 CHECK_DB_NOT_CLOSED(self);
2291 MYDB_BEGIN_ALLOW_THREADS;
2292 err = self->db->set_re_source(self->db, re_source);
2293 MYDB_END_ALLOW_THREADS;
2294 RETURN_IF_ERR();
2295 RETURN_NONE();
2299 static PyObject*
2300 DB_set_q_extentsize(DBObject* self, PyObject* args)
2302 int err;
2303 int extentsize;
2305 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2306 return NULL;
2307 CHECK_DB_NOT_CLOSED(self);
2309 MYDB_BEGIN_ALLOW_THREADS;
2310 err = self->db->set_q_extentsize(self->db, extentsize);
2311 MYDB_END_ALLOW_THREADS;
2312 RETURN_IF_ERR();
2313 RETURN_NONE();
2316 static PyObject*
2317 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2319 int err, flags = 0, type;
2320 void* sp;
2321 PyObject* d;
2322 #if (DBVER >= 43)
2323 PyObject* txnobj = NULL;
2324 DB_TXN *txn = NULL;
2325 static char* kwnames[] = { "flags", "txn", NULL };
2326 #else
2327 static char* kwnames[] = { "flags", NULL };
2328 #endif
2330 #if (DBVER >= 43)
2331 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2332 &flags, &txnobj))
2333 return NULL;
2334 if (!checkTxnObj(txnobj, &txn))
2335 return NULL;
2336 #else
2337 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2338 return NULL;
2339 #endif
2340 CHECK_DB_NOT_CLOSED(self);
2342 MYDB_BEGIN_ALLOW_THREADS;
2343 #if (DBVER >= 43)
2344 err = self->db->stat(self->db, txn, &sp, flags);
2345 #elif (DBVER >= 33)
2346 err = self->db->stat(self->db, &sp, flags);
2347 #else
2348 err = self->db->stat(self->db, &sp, NULL, flags);
2349 #endif
2350 MYDB_END_ALLOW_THREADS;
2351 RETURN_IF_ERR();
2353 self->haveStat = 1;
2355 /* Turn the stat structure into a dictionary */
2356 type = _DB_get_type(self);
2357 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2358 free(sp);
2359 return NULL;
2362 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2363 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2364 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2366 switch (type) {
2367 case DB_HASH:
2368 MAKE_HASH_ENTRY(magic);
2369 MAKE_HASH_ENTRY(version);
2370 MAKE_HASH_ENTRY(nkeys);
2371 MAKE_HASH_ENTRY(ndata);
2372 MAKE_HASH_ENTRY(pagesize);
2373 #if (DBVER < 41)
2374 MAKE_HASH_ENTRY(nelem);
2375 #endif
2376 MAKE_HASH_ENTRY(ffactor);
2377 MAKE_HASH_ENTRY(buckets);
2378 MAKE_HASH_ENTRY(free);
2379 MAKE_HASH_ENTRY(bfree);
2380 MAKE_HASH_ENTRY(bigpages);
2381 MAKE_HASH_ENTRY(big_bfree);
2382 MAKE_HASH_ENTRY(overflows);
2383 MAKE_HASH_ENTRY(ovfl_free);
2384 MAKE_HASH_ENTRY(dup);
2385 MAKE_HASH_ENTRY(dup_free);
2386 break;
2388 case DB_BTREE:
2389 case DB_RECNO:
2390 MAKE_BT_ENTRY(magic);
2391 MAKE_BT_ENTRY(version);
2392 MAKE_BT_ENTRY(nkeys);
2393 MAKE_BT_ENTRY(ndata);
2394 MAKE_BT_ENTRY(pagesize);
2395 MAKE_BT_ENTRY(minkey);
2396 MAKE_BT_ENTRY(re_len);
2397 MAKE_BT_ENTRY(re_pad);
2398 MAKE_BT_ENTRY(levels);
2399 MAKE_BT_ENTRY(int_pg);
2400 MAKE_BT_ENTRY(leaf_pg);
2401 MAKE_BT_ENTRY(dup_pg);
2402 MAKE_BT_ENTRY(over_pg);
2403 MAKE_BT_ENTRY(free);
2404 MAKE_BT_ENTRY(int_pgfree);
2405 MAKE_BT_ENTRY(leaf_pgfree);
2406 MAKE_BT_ENTRY(dup_pgfree);
2407 MAKE_BT_ENTRY(over_pgfree);
2408 break;
2410 case DB_QUEUE:
2411 MAKE_QUEUE_ENTRY(magic);
2412 MAKE_QUEUE_ENTRY(version);
2413 MAKE_QUEUE_ENTRY(nkeys);
2414 MAKE_QUEUE_ENTRY(ndata);
2415 MAKE_QUEUE_ENTRY(pagesize);
2416 MAKE_QUEUE_ENTRY(pages);
2417 MAKE_QUEUE_ENTRY(re_len);
2418 MAKE_QUEUE_ENTRY(re_pad);
2419 MAKE_QUEUE_ENTRY(pgfree);
2420 #if (DBVER == 31)
2421 MAKE_QUEUE_ENTRY(start);
2422 #endif
2423 MAKE_QUEUE_ENTRY(first_recno);
2424 MAKE_QUEUE_ENTRY(cur_recno);
2425 break;
2427 default:
2428 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2429 Py_DECREF(d);
2430 d = NULL;
2433 #undef MAKE_HASH_ENTRY
2434 #undef MAKE_BT_ENTRY
2435 #undef MAKE_QUEUE_ENTRY
2437 free(sp);
2438 return d;
2441 static PyObject*
2442 DB_sync(DBObject* self, PyObject* args)
2444 int err;
2445 int flags = 0;
2447 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2448 return NULL;
2449 CHECK_DB_NOT_CLOSED(self);
2451 MYDB_BEGIN_ALLOW_THREADS;
2452 err = self->db->sync(self->db, flags);
2453 MYDB_END_ALLOW_THREADS;
2454 RETURN_IF_ERR();
2455 RETURN_NONE();
2459 #if (DBVER >= 33)
2460 static PyObject*
2461 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2463 int err, flags=0;
2464 u_int32_t count=0;
2465 PyObject* txnobj = NULL;
2466 DB_TXN *txn = NULL;
2467 static char* kwnames[] = { "txn", "flags", NULL };
2469 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2470 &txnobj, &flags))
2471 return NULL;
2472 CHECK_DB_NOT_CLOSED(self);
2473 if (!checkTxnObj(txnobj, &txn))
2474 return NULL;
2476 MYDB_BEGIN_ALLOW_THREADS;
2477 err = self->db->truncate(self->db, txn, &count, flags);
2478 MYDB_END_ALLOW_THREADS;
2479 RETURN_IF_ERR();
2480 return PyInt_FromLong(count);
2482 #endif
2485 static PyObject*
2486 DB_upgrade(DBObject* self, PyObject* args)
2488 int err, flags=0;
2489 char *filename;
2491 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2492 return NULL;
2493 CHECK_DB_NOT_CLOSED(self);
2495 MYDB_BEGIN_ALLOW_THREADS;
2496 err = self->db->upgrade(self->db, filename, flags);
2497 MYDB_END_ALLOW_THREADS;
2498 RETURN_IF_ERR();
2499 RETURN_NONE();
2503 static PyObject*
2504 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2506 int err, flags=0;
2507 char* fileName;
2508 char* dbName=NULL;
2509 char* outFileName=NULL;
2510 FILE* outFile=NULL;
2511 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2512 NULL };
2514 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2515 &fileName, &dbName, &outFileName, &flags))
2516 return NULL;
2518 CHECK_DB_NOT_CLOSED(self);
2519 if (outFileName)
2520 outFile = fopen(outFileName, "w");
2521 /* XXX(nnorwitz): it should probably be an exception if outFile
2522 can't be opened. */
2524 MYDB_BEGIN_ALLOW_THREADS;
2525 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2526 MYDB_END_ALLOW_THREADS;
2527 if (outFile)
2528 fclose(outFile);
2530 /* DB.verify acts as a DB handle destructor (like close); this was
2531 * documented in BerkeleyDB 4.2 but had the undocumented effect
2532 * of not being safe in prior versions while still requiring an explicit
2533 * DB.close call afterwards. Lets call close for the user to emulate
2534 * the safe 4.2 behaviour. */
2535 #if (DBVER <= 41)
2536 self->db->close(self->db, 0);
2537 #endif
2538 self->db = NULL;
2540 RETURN_IF_ERR();
2541 RETURN_NONE();
2545 static PyObject*
2546 DB_set_get_returns_none(DBObject* self, PyObject* args)
2548 int flags=0;
2549 int oldValue=0;
2551 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2552 return NULL;
2553 CHECK_DB_NOT_CLOSED(self);
2555 if (self->moduleFlags.getReturnsNone)
2556 ++oldValue;
2557 if (self->moduleFlags.cursorSetReturnsNone)
2558 ++oldValue;
2559 self->moduleFlags.getReturnsNone = (flags >= 1);
2560 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2561 return PyInt_FromLong(oldValue);
2564 #if (DBVER >= 41)
2565 static PyObject*
2566 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2568 int err;
2569 u_int32_t flags=0;
2570 char *passwd = NULL;
2571 static char* kwnames[] = { "passwd", "flags", NULL };
2573 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2574 &passwd, &flags)) {
2575 return NULL;
2578 MYDB_BEGIN_ALLOW_THREADS;
2579 err = self->db->set_encrypt(self->db, passwd, flags);
2580 MYDB_END_ALLOW_THREADS;
2582 RETURN_IF_ERR();
2583 RETURN_NONE();
2585 #endif /* DBVER >= 41 */
2588 /*-------------------------------------------------------------- */
2589 /* Mapping and Dictionary-like access routines */
2591 Py_ssize_t DB_length(PyObject* _self)
2593 int err;
2594 Py_ssize_t size = 0;
2595 int flags = 0;
2596 void* sp;
2597 DBObject* self = (DBObject*)_self;
2599 if (self->db == NULL) {
2600 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2601 PyErr_SetObject(DBError, t);
2602 Py_DECREF(t);
2603 return -1;
2606 if (self->haveStat) { /* Has the stat function been called recently? If
2607 so, we can use the cached value. */
2608 flags = DB_FAST_STAT;
2611 MYDB_BEGIN_ALLOW_THREADS;
2612 redo_stat_for_length:
2613 #if (DBVER >= 43)
2614 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2615 #elif (DBVER >= 33)
2616 err = self->db->stat(self->db, &sp, flags);
2617 #else
2618 err = self->db->stat(self->db, &sp, NULL, flags);
2619 #endif
2621 /* All the stat structures have matching fields upto the ndata field,
2622 so we can use any of them for the type cast */
2623 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2625 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2626 * redo a full stat to make sure.
2627 * Fixes SF python bug 1493322, pybsddb bug 1184012
2629 if (size == 0 && (flags & DB_FAST_STAT)) {
2630 flags = 0;
2631 if (!err)
2632 free(sp);
2633 goto redo_stat_for_length;
2636 MYDB_END_ALLOW_THREADS;
2638 if (err)
2639 return -1;
2641 self->haveStat = 1;
2643 free(sp);
2644 return size;
2648 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2650 int err;
2651 PyObject* retval;
2652 DBT key;
2653 DBT data;
2655 CHECK_DB_NOT_CLOSED(self);
2656 if (!make_key_dbt(self, keyobj, &key, NULL))
2657 return NULL;
2659 CLEAR_DBT(data);
2660 if (CHECK_DBFLAG(self, DB_THREAD)) {
2661 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2662 data.flags = DB_DBT_MALLOC;
2664 MYDB_BEGIN_ALLOW_THREADS;
2665 err = self->db->get(self->db, NULL, &key, &data, 0);
2666 MYDB_END_ALLOW_THREADS;
2667 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2668 PyErr_SetObject(PyExc_KeyError, keyobj);
2669 retval = NULL;
2671 else if (makeDBError(err)) {
2672 retval = NULL;
2674 else {
2675 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2676 FREE_DBT(data);
2679 FREE_DBT(key);
2680 return retval;
2684 static int
2685 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2687 DBT key, data;
2688 int retval;
2689 int flags = 0;
2691 if (self->db == NULL) {
2692 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2693 PyErr_SetObject(DBError, t);
2694 Py_DECREF(t);
2695 return -1;
2698 if (!make_key_dbt(self, keyobj, &key, NULL))
2699 return -1;
2701 if (dataobj != NULL) {
2702 if (!make_dbt(dataobj, &data))
2703 retval = -1;
2704 else {
2705 if (self->setflags & (DB_DUP|DB_DUPSORT))
2706 /* dictionaries shouldn't have duplicate keys */
2707 flags = DB_NOOVERWRITE;
2708 retval = _DB_put(self, NULL, &key, &data, flags);
2710 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2711 /* try deleting any old record that matches and then PUT it
2712 * again... */
2713 _DB_delete(self, NULL, &key, 0);
2714 PyErr_Clear();
2715 retval = _DB_put(self, NULL, &key, &data, flags);
2719 else {
2720 /* dataobj == NULL, so delete the key */
2721 retval = _DB_delete(self, NULL, &key, 0);
2723 FREE_DBT(key);
2724 return retval;
2728 static PyObject*
2729 DB_has_key(DBObject* self, PyObject* args)
2731 int err;
2732 PyObject* keyobj;
2733 DBT key, data;
2734 PyObject* txnobj = NULL;
2735 DB_TXN *txn = NULL;
2737 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2738 return NULL;
2739 CHECK_DB_NOT_CLOSED(self);
2740 if (!make_key_dbt(self, keyobj, &key, NULL))
2741 return NULL;
2742 if (!checkTxnObj(txnobj, &txn)) {
2743 FREE_DBT(key);
2744 return NULL;
2747 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2748 it has a record but can't allocate a buffer for the data. This saves
2749 having to deal with data we won't be using.
2751 CLEAR_DBT(data);
2752 data.flags = DB_DBT_USERMEM;
2754 MYDB_BEGIN_ALLOW_THREADS;
2755 err = self->db->get(self->db, txn, &key, &data, 0);
2756 MYDB_END_ALLOW_THREADS;
2757 FREE_DBT(key);
2759 if (err == DB_BUFFER_SMALL || err == 0) {
2760 return PyInt_FromLong(1);
2761 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2762 return PyInt_FromLong(0);
2765 makeDBError(err);
2766 return NULL;
2770 #define _KEYS_LIST 1
2771 #define _VALUES_LIST 2
2772 #define _ITEMS_LIST 3
2774 static PyObject*
2775 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2777 int err, dbtype;
2778 DBT key;
2779 DBT data;
2780 DBC *cursor;
2781 PyObject* list;
2782 PyObject* item = NULL;
2784 CHECK_DB_NOT_CLOSED(self);
2785 CLEAR_DBT(key);
2786 CLEAR_DBT(data);
2788 dbtype = _DB_get_type(self);
2789 if (dbtype == -1)
2790 return NULL;
2792 list = PyList_New(0);
2793 if (list == NULL)
2794 return NULL;
2796 /* get a cursor */
2797 MYDB_BEGIN_ALLOW_THREADS;
2798 err = self->db->cursor(self->db, txn, &cursor, 0);
2799 MYDB_END_ALLOW_THREADS;
2800 if (makeDBError(err)) {
2801 Py_DECREF(list);
2802 return NULL;
2805 if (CHECK_DBFLAG(self, DB_THREAD)) {
2806 key.flags = DB_DBT_REALLOC;
2807 data.flags = DB_DBT_REALLOC;
2810 while (1) { /* use the cursor to traverse the DB, collecting items */
2811 MYDB_BEGIN_ALLOW_THREADS;
2812 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2813 MYDB_END_ALLOW_THREADS;
2815 if (err) {
2816 /* for any error, break out of the loop */
2817 break;
2820 switch (type) {
2821 case _KEYS_LIST:
2822 switch(dbtype) {
2823 case DB_BTREE:
2824 case DB_HASH:
2825 default:
2826 item = PyString_FromStringAndSize((char*)key.data, key.size);
2827 break;
2828 case DB_RECNO:
2829 case DB_QUEUE:
2830 item = PyInt_FromLong(*((db_recno_t*)key.data));
2831 break;
2833 break;
2835 case _VALUES_LIST:
2836 item = PyString_FromStringAndSize((char*)data.data, data.size);
2837 break;
2839 case _ITEMS_LIST:
2840 switch(dbtype) {
2841 case DB_BTREE:
2842 case DB_HASH:
2843 default:
2844 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2845 data.size);
2846 break;
2847 case DB_RECNO:
2848 case DB_QUEUE:
2849 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2850 data.data, data.size);
2851 break;
2853 break;
2854 default:
2855 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2856 item = NULL;
2857 break;
2859 if (item == NULL) {
2860 Py_DECREF(list);
2861 list = NULL;
2862 goto done;
2864 PyList_Append(list, item);
2865 Py_DECREF(item);
2868 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2869 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2870 Py_DECREF(list);
2871 list = NULL;
2874 done:
2875 FREE_DBT(key);
2876 FREE_DBT(data);
2877 MYDB_BEGIN_ALLOW_THREADS;
2878 cursor->c_close(cursor);
2879 MYDB_END_ALLOW_THREADS;
2880 return list;
2884 static PyObject*
2885 DB_keys(DBObject* self, PyObject* args)
2887 PyObject* txnobj = NULL;
2888 DB_TXN *txn = NULL;
2890 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2891 return NULL;
2892 if (!checkTxnObj(txnobj, &txn))
2893 return NULL;
2894 return _DB_make_list(self, txn, _KEYS_LIST);
2898 static PyObject*
2899 DB_items(DBObject* self, PyObject* args)
2901 PyObject* txnobj = NULL;
2902 DB_TXN *txn = NULL;
2904 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
2905 return NULL;
2906 if (!checkTxnObj(txnobj, &txn))
2907 return NULL;
2908 return _DB_make_list(self, txn, _ITEMS_LIST);
2912 static PyObject*
2913 DB_values(DBObject* self, PyObject* args)
2915 PyObject* txnobj = NULL;
2916 DB_TXN *txn = NULL;
2918 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
2919 return NULL;
2920 if (!checkTxnObj(txnobj, &txn))
2921 return NULL;
2922 return _DB_make_list(self, txn, _VALUES_LIST);
2925 /* --------------------------------------------------------------------- */
2926 /* DBCursor methods */
2929 static PyObject*
2930 DBC_close(DBCursorObject* self, PyObject* args)
2932 int err = 0;
2934 if (!PyArg_ParseTuple(args, ":close"))
2935 return NULL;
2937 if (self->dbc != NULL) {
2938 MYDB_BEGIN_ALLOW_THREADS;
2939 err = self->dbc->c_close(self->dbc);
2940 self->dbc = NULL;
2941 MYDB_END_ALLOW_THREADS;
2943 RETURN_IF_ERR();
2944 RETURN_NONE();
2948 static PyObject*
2949 DBC_count(DBCursorObject* self, PyObject* args)
2951 int err = 0;
2952 db_recno_t count;
2953 int flags = 0;
2955 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2956 return NULL;
2958 CHECK_CURSOR_NOT_CLOSED(self);
2960 MYDB_BEGIN_ALLOW_THREADS;
2961 err = self->dbc->c_count(self->dbc, &count, flags);
2962 MYDB_END_ALLOW_THREADS;
2963 RETURN_IF_ERR();
2965 return PyInt_FromLong(count);
2969 static PyObject*
2970 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2972 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2976 static PyObject*
2977 DBC_delete(DBCursorObject* self, PyObject* args)
2979 int err, flags=0;
2981 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2982 return NULL;
2984 CHECK_CURSOR_NOT_CLOSED(self);
2986 MYDB_BEGIN_ALLOW_THREADS;
2987 err = self->dbc->c_del(self->dbc, flags);
2988 MYDB_END_ALLOW_THREADS;
2989 RETURN_IF_ERR();
2991 self->mydb->haveStat = 0;
2992 RETURN_NONE();
2996 static PyObject*
2997 DBC_dup(DBCursorObject* self, PyObject* args)
2999 int err, flags =0;
3000 DBC* dbc = NULL;
3002 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3003 return NULL;
3005 CHECK_CURSOR_NOT_CLOSED(self);
3007 MYDB_BEGIN_ALLOW_THREADS;
3008 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3009 MYDB_END_ALLOW_THREADS;
3010 RETURN_IF_ERR();
3012 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3015 static PyObject*
3016 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3018 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3022 static PyObject*
3023 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3025 int err, flags=0;
3026 PyObject* keyobj = NULL;
3027 PyObject* dataobj = NULL;
3028 PyObject* retval = NULL;
3029 int dlen = -1;
3030 int doff = -1;
3031 DBT key, data;
3032 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3033 NULL };
3035 CLEAR_DBT(key);
3036 CLEAR_DBT(data);
3037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3038 &flags, &dlen, &doff))
3040 PyErr_Clear();
3041 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3042 &kwnames[1],
3043 &keyobj, &flags, &dlen, &doff))
3045 PyErr_Clear();
3046 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3047 kwnames, &keyobj, &dataobj,
3048 &flags, &dlen, &doff))
3050 return NULL;
3055 CHECK_CURSOR_NOT_CLOSED(self);
3057 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3058 return NULL;
3059 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3060 (!add_partial_dbt(&data, dlen, doff)) )
3062 FREE_DBT(key);
3063 return NULL;
3066 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3067 data.flags = DB_DBT_MALLOC;
3068 if (!(key.flags & DB_DBT_REALLOC)) {
3069 key.flags |= DB_DBT_MALLOC;
3073 MYDB_BEGIN_ALLOW_THREADS;
3074 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3075 MYDB_END_ALLOW_THREADS;
3077 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3078 && self->mydb->moduleFlags.getReturnsNone) {
3079 Py_INCREF(Py_None);
3080 retval = Py_None;
3082 else if (makeDBError(err)) {
3083 retval = NULL;
3085 else {
3086 switch (_DB_get_type(self->mydb)) {
3087 case -1:
3088 retval = NULL;
3089 break;
3090 case DB_BTREE:
3091 case DB_HASH:
3092 default:
3093 retval = Py_BuildValue("s#s#", key.data, key.size,
3094 data.data, data.size);
3095 break;
3096 case DB_RECNO:
3097 case DB_QUEUE:
3098 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3099 data.data, data.size);
3100 break;
3102 FREE_DBT(data);
3104 FREE_DBT(key);
3105 return retval;
3108 #if (DBVER >= 33)
3109 static PyObject*
3110 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3112 int err, flags=0;
3113 PyObject* keyobj = NULL;
3114 PyObject* dataobj = NULL;
3115 PyObject* retval = NULL;
3116 int dlen = -1;
3117 int doff = -1;
3118 DBT key, pkey, data;
3119 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3120 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3122 CLEAR_DBT(key);
3123 CLEAR_DBT(data);
3124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3125 &flags, &dlen, &doff))
3127 PyErr_Clear();
3128 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3129 kwnames_keyOnly,
3130 &keyobj, &flags, &dlen, &doff))
3132 PyErr_Clear();
3133 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3134 kwnames, &keyobj, &dataobj,
3135 &flags, &dlen, &doff))
3137 return NULL;
3142 CHECK_CURSOR_NOT_CLOSED(self);
3144 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3145 return NULL;
3146 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3147 (!add_partial_dbt(&data, dlen, doff)) ) {
3148 FREE_DBT(key);
3149 return NULL;
3152 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3153 data.flags = DB_DBT_MALLOC;
3154 if (!(key.flags & DB_DBT_REALLOC)) {
3155 key.flags |= DB_DBT_MALLOC;
3159 CLEAR_DBT(pkey);
3160 pkey.flags = DB_DBT_MALLOC;
3162 MYDB_BEGIN_ALLOW_THREADS;
3163 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3164 MYDB_END_ALLOW_THREADS;
3166 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3167 && self->mydb->moduleFlags.getReturnsNone) {
3168 Py_INCREF(Py_None);
3169 retval = Py_None;
3171 else if (makeDBError(err)) {
3172 retval = NULL;
3174 else {
3175 PyObject *pkeyObj;
3176 PyObject *dataObj;
3177 dataObj = PyString_FromStringAndSize(data.data, data.size);
3179 if (self->mydb->primaryDBType == DB_RECNO ||
3180 self->mydb->primaryDBType == DB_QUEUE)
3181 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3182 else
3183 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3185 if (key.data && key.size) /* return key, pkey and data */
3187 PyObject *keyObj;
3188 int type = _DB_get_type(self->mydb);
3189 if (type == DB_RECNO || type == DB_QUEUE)
3190 keyObj = PyInt_FromLong(*(int *)key.data);
3191 else
3192 keyObj = PyString_FromStringAndSize(key.data, key.size);
3193 #if (PY_VERSION_HEX >= 0x02040000)
3194 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3195 #else
3196 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3197 #endif
3198 Py_DECREF(keyObj);
3199 FREE_DBT(key);
3201 else /* return just the pkey and data */
3203 #if (PY_VERSION_HEX >= 0x02040000)
3204 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3205 #else
3206 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3207 #endif
3209 Py_DECREF(dataObj);
3210 Py_DECREF(pkeyObj);
3211 FREE_DBT(pkey);
3212 FREE_DBT(data);
3214 /* the only time REALLOC should be set is if we used an integer
3215 * key that make_key_dbt malloc'd for us. always free these. */
3216 if (key.flags & DB_DBT_REALLOC) {
3217 FREE_DBT(key);
3219 return retval;
3221 #endif
3224 static PyObject*
3225 DBC_get_recno(DBCursorObject* self, PyObject* args)
3227 int err;
3228 db_recno_t recno;
3229 DBT key;
3230 DBT data;
3232 if (!PyArg_ParseTuple(args, ":get_recno"))
3233 return NULL;
3235 CHECK_CURSOR_NOT_CLOSED(self);
3237 CLEAR_DBT(key);
3238 CLEAR_DBT(data);
3239 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3240 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3241 data.flags = DB_DBT_MALLOC;
3242 key.flags = DB_DBT_MALLOC;
3245 MYDB_BEGIN_ALLOW_THREADS;
3246 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3247 MYDB_END_ALLOW_THREADS;
3248 RETURN_IF_ERR();
3250 recno = *((db_recno_t*)data.data);
3251 FREE_DBT(key);
3252 FREE_DBT(data);
3253 return PyInt_FromLong(recno);
3257 static PyObject*
3258 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3260 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3264 static PyObject*
3265 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3267 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3271 static PyObject*
3272 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3274 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3278 static PyObject*
3279 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3281 int err, flags = 0;
3282 PyObject* keyobj, *dataobj;
3283 DBT key, data;
3284 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3285 NULL };
3286 int dlen = -1;
3287 int doff = -1;
3289 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3290 &keyobj, &dataobj, &flags, &dlen, &doff))
3291 return NULL;
3293 CHECK_CURSOR_NOT_CLOSED(self);
3295 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3296 return NULL;
3297 if (!make_dbt(dataobj, &data) ||
3298 !add_partial_dbt(&data, dlen, doff) )
3300 FREE_DBT(key);
3301 return NULL;
3304 MYDB_BEGIN_ALLOW_THREADS;
3305 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3306 MYDB_END_ALLOW_THREADS;
3307 FREE_DBT(key);
3308 RETURN_IF_ERR();
3309 self->mydb->haveStat = 0;
3310 RETURN_NONE();
3314 static PyObject*
3315 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3317 int err, flags = 0;
3318 DBT key, data;
3319 PyObject* retval, *keyobj;
3320 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3321 int dlen = -1;
3322 int doff = -1;
3324 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3325 &keyobj, &flags, &dlen, &doff))
3326 return NULL;
3328 CHECK_CURSOR_NOT_CLOSED(self);
3330 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3331 return NULL;
3333 CLEAR_DBT(data);
3334 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3335 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3336 data.flags = DB_DBT_MALLOC;
3338 if (!add_partial_dbt(&data, dlen, doff)) {
3339 FREE_DBT(key);
3340 return NULL;
3343 MYDB_BEGIN_ALLOW_THREADS;
3344 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3345 MYDB_END_ALLOW_THREADS;
3346 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3347 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3348 Py_INCREF(Py_None);
3349 retval = Py_None;
3351 else if (makeDBError(err)) {
3352 retval = NULL;
3354 else {
3355 switch (_DB_get_type(self->mydb)) {
3356 case -1:
3357 retval = NULL;
3358 break;
3359 case DB_BTREE:
3360 case DB_HASH:
3361 default:
3362 retval = Py_BuildValue("s#s#", key.data, key.size,
3363 data.data, data.size);
3364 break;
3365 case DB_RECNO:
3366 case DB_QUEUE:
3367 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3368 data.data, data.size);
3369 break;
3371 FREE_DBT(data);
3372 FREE_DBT(key);
3374 /* the only time REALLOC should be set is if we used an integer
3375 * key that make_key_dbt malloc'd for us. always free these. */
3376 if (key.flags & DB_DBT_REALLOC) {
3377 FREE_DBT(key);
3380 return retval;
3384 static PyObject*
3385 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3387 int err, flags = 0;
3388 DBT key, data;
3389 PyObject* retval, *keyobj;
3390 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3391 int dlen = -1;
3392 int doff = -1;
3394 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3395 &keyobj, &flags, &dlen, &doff))
3396 return NULL;
3398 CHECK_CURSOR_NOT_CLOSED(self);
3400 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3401 return NULL;
3403 CLEAR_DBT(data);
3404 if (!add_partial_dbt(&data, dlen, doff)) {
3405 FREE_DBT(key);
3406 return NULL;
3408 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3409 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3410 data.flags |= DB_DBT_MALLOC;
3411 /* only BTREE databases will return anything in the key */
3412 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3413 key.flags |= DB_DBT_MALLOC;
3416 MYDB_BEGIN_ALLOW_THREADS;
3417 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3418 MYDB_END_ALLOW_THREADS;
3419 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3420 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3421 Py_INCREF(Py_None);
3422 retval = Py_None;
3424 else if (makeDBError(err)) {
3425 retval = NULL;
3427 else {
3428 switch (_DB_get_type(self->mydb)) {
3429 case -1:
3430 retval = NULL;
3431 break;
3432 case DB_BTREE:
3433 case DB_HASH:
3434 default:
3435 retval = Py_BuildValue("s#s#", key.data, key.size,
3436 data.data, data.size);
3437 break;
3438 case DB_RECNO:
3439 case DB_QUEUE:
3440 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3441 data.data, data.size);
3442 break;
3444 FREE_DBT(key);
3445 FREE_DBT(data);
3447 /* the only time REALLOC should be set is if we used an integer
3448 * key that make_key_dbt malloc'd for us. always free these. */
3449 if (key.flags & DB_DBT_REALLOC) {
3450 FREE_DBT(key);
3453 return retval;
3456 static PyObject*
3457 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3458 int flags, unsigned int returnsNone)
3460 int err;
3461 DBT key, data;
3462 PyObject* retval;
3464 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3465 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3466 return NULL;
3467 if (!make_dbt(dataobj, &data)) {
3468 FREE_DBT(key);
3469 return NULL;
3472 MYDB_BEGIN_ALLOW_THREADS;
3473 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3474 MYDB_END_ALLOW_THREADS;
3475 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3476 Py_INCREF(Py_None);
3477 retval = Py_None;
3479 else if (makeDBError(err)) {
3480 retval = NULL;
3482 else {
3483 switch (_DB_get_type(self->mydb)) {
3484 case -1:
3485 retval = NULL;
3486 break;
3487 case DB_BTREE:
3488 case DB_HASH:
3489 default:
3490 retval = Py_BuildValue("s#s#", key.data, key.size,
3491 data.data, data.size);
3492 break;
3493 case DB_RECNO:
3494 case DB_QUEUE:
3495 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3496 data.data, data.size);
3497 break;
3501 FREE_DBT(key);
3502 return retval;
3505 static PyObject*
3506 DBC_get_both(DBCursorObject* self, PyObject* args)
3508 int flags=0;
3509 PyObject *keyobj, *dataobj;
3511 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3512 return NULL;
3514 /* if the cursor is closed, self->mydb may be invalid */
3515 CHECK_CURSOR_NOT_CLOSED(self);
3517 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3518 self->mydb->moduleFlags.getReturnsNone);
3521 /* Return size of entry */
3522 static PyObject*
3523 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3525 int err, flags=DB_CURRENT;
3526 PyObject* retval = NULL;
3527 DBT key, data;
3529 if (!PyArg_ParseTuple(args, ":get_current_size"))
3530 return NULL;
3531 CHECK_CURSOR_NOT_CLOSED(self);
3532 CLEAR_DBT(key);
3533 CLEAR_DBT(data);
3535 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3536 getting the record size. */
3537 data.flags = DB_DBT_USERMEM;
3538 data.ulen = 0;
3539 MYDB_BEGIN_ALLOW_THREADS;
3540 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3541 MYDB_END_ALLOW_THREADS;
3542 if (err == DB_BUFFER_SMALL || !err) {
3543 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3544 retval = PyInt_FromLong((long)data.size);
3545 err = 0;
3548 FREE_DBT(key);
3549 FREE_DBT(data);
3550 RETURN_IF_ERR();
3551 return retval;
3554 static PyObject*
3555 DBC_set_both(DBCursorObject* self, PyObject* args)
3557 int flags=0;
3558 PyObject *keyobj, *dataobj;
3560 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3561 return NULL;
3563 /* if the cursor is closed, self->mydb may be invalid */
3564 CHECK_CURSOR_NOT_CLOSED(self);
3566 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3567 self->mydb->moduleFlags.cursorSetReturnsNone);
3571 static PyObject*
3572 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3574 int err, irecno, flags=0;
3575 db_recno_t recno;
3576 DBT key, data;
3577 PyObject* retval;
3578 int dlen = -1;
3579 int doff = -1;
3580 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3582 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3583 &irecno, &flags, &dlen, &doff))
3584 return NULL;
3586 CHECK_CURSOR_NOT_CLOSED(self);
3588 CLEAR_DBT(key);
3589 recno = (db_recno_t) irecno;
3590 /* use allocated space so DB will be able to realloc room for the real
3591 * key */
3592 key.data = malloc(sizeof(db_recno_t));
3593 if (key.data == NULL) {
3594 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3595 return NULL;
3597 key.size = sizeof(db_recno_t);
3598 key.ulen = key.size;
3599 memcpy(key.data, &recno, sizeof(db_recno_t));
3600 key.flags = DB_DBT_REALLOC;
3602 CLEAR_DBT(data);
3603 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3604 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3605 data.flags = DB_DBT_MALLOC;
3607 if (!add_partial_dbt(&data, dlen, doff)) {
3608 FREE_DBT(key);
3609 return NULL;
3612 MYDB_BEGIN_ALLOW_THREADS;
3613 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3614 MYDB_END_ALLOW_THREADS;
3615 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3616 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3617 Py_INCREF(Py_None);
3618 retval = Py_None;
3620 else if (makeDBError(err)) {
3621 retval = NULL;
3623 else { /* Can only be used for BTrees, so no need to return int key */
3624 retval = Py_BuildValue("s#s#", key.data, key.size,
3625 data.data, data.size);
3626 FREE_DBT(data);
3628 FREE_DBT(key);
3630 return retval;
3634 static PyObject*
3635 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3637 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3641 static PyObject*
3642 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3644 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3648 static PyObject*
3649 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3651 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3655 static PyObject*
3656 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3658 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3662 static PyObject*
3663 DBC_join_item(DBCursorObject* self, PyObject* args)
3665 int err, flags=0;
3666 DBT key, data;
3667 PyObject* retval;
3669 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3670 return NULL;
3672 CHECK_CURSOR_NOT_CLOSED(self);
3674 CLEAR_DBT(key);
3675 CLEAR_DBT(data);
3676 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3677 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3678 key.flags = DB_DBT_MALLOC;
3681 MYDB_BEGIN_ALLOW_THREADS;
3682 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3683 MYDB_END_ALLOW_THREADS;
3684 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3685 && self->mydb->moduleFlags.getReturnsNone) {
3686 Py_INCREF(Py_None);
3687 retval = Py_None;
3689 else if (makeDBError(err)) {
3690 retval = NULL;
3692 else {
3693 retval = Py_BuildValue("s#", key.data, key.size);
3694 FREE_DBT(key);
3697 return retval;
3702 /* --------------------------------------------------------------------- */
3703 /* DBEnv methods */
3706 static PyObject*
3707 DBEnv_close(DBEnvObject* self, PyObject* args)
3709 int err, flags = 0;
3711 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3712 return NULL;
3713 if (!self->closed) { /* Don't close more than once */
3714 MYDB_BEGIN_ALLOW_THREADS;
3715 err = self->db_env->close(self->db_env, flags);
3716 MYDB_END_ALLOW_THREADS;
3717 /* after calling DBEnv->close, regardless of error, this DBEnv
3718 * may not be accessed again (BerkeleyDB docs). */
3719 self->closed = 1;
3720 self->db_env = NULL;
3721 RETURN_IF_ERR();
3723 RETURN_NONE();
3727 static PyObject*
3728 DBEnv_open(DBEnvObject* self, PyObject* args)
3730 int err, flags=0, mode=0660;
3731 char *db_home;
3733 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3734 return NULL;
3736 CHECK_ENV_NOT_CLOSED(self);
3738 MYDB_BEGIN_ALLOW_THREADS;
3739 err = self->db_env->open(self->db_env, db_home, flags, mode);
3740 MYDB_END_ALLOW_THREADS;
3741 RETURN_IF_ERR();
3742 self->closed = 0;
3743 self->flags = flags;
3744 RETURN_NONE();
3748 static PyObject*
3749 DBEnv_remove(DBEnvObject* self, PyObject* args)
3751 int err, flags=0;
3752 char *db_home;
3754 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3755 return NULL;
3756 CHECK_ENV_NOT_CLOSED(self);
3757 MYDB_BEGIN_ALLOW_THREADS;
3758 err = self->db_env->remove(self->db_env, db_home, flags);
3759 MYDB_END_ALLOW_THREADS;
3760 RETURN_IF_ERR();
3761 RETURN_NONE();
3764 #if (DBVER >= 41)
3765 static PyObject*
3766 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3768 int err;
3769 u_int32_t flags=0;
3770 char *file = NULL;
3771 char *database = NULL;
3772 PyObject *txnobj = NULL;
3773 DB_TXN *txn = NULL;
3774 static char* kwnames[] = { "file", "database", "txn", "flags",
3775 NULL };
3777 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
3778 &file, &database, &txnobj, &flags)) {
3779 return NULL;
3781 if (!checkTxnObj(txnobj, &txn)) {
3782 return NULL;
3784 CHECK_ENV_NOT_CLOSED(self);
3785 MYDB_BEGIN_ALLOW_THREADS;
3786 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3787 MYDB_END_ALLOW_THREADS;
3788 RETURN_IF_ERR();
3789 RETURN_NONE();
3792 static PyObject*
3793 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3795 int err;
3796 u_int32_t flags=0;
3797 char *file = NULL;
3798 char *database = NULL;
3799 char *newname = NULL;
3800 PyObject *txnobj = NULL;
3801 DB_TXN *txn = NULL;
3802 static char* kwnames[] = { "file", "database", "newname", "txn",
3803 "flags", NULL };
3805 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
3806 &file, &database, &newname, &txnobj, &flags)) {
3807 return NULL;
3809 if (!checkTxnObj(txnobj, &txn)) {
3810 return NULL;
3812 CHECK_ENV_NOT_CLOSED(self);
3813 MYDB_BEGIN_ALLOW_THREADS;
3814 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3815 flags);
3816 MYDB_END_ALLOW_THREADS;
3817 RETURN_IF_ERR();
3818 RETURN_NONE();
3821 static PyObject*
3822 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3824 int err;
3825 u_int32_t flags=0;
3826 char *passwd = NULL;
3827 static char* kwnames[] = { "passwd", "flags", NULL };
3829 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3830 &passwd, &flags)) {
3831 return NULL;
3834 MYDB_BEGIN_ALLOW_THREADS;
3835 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3836 MYDB_END_ALLOW_THREADS;
3838 RETURN_IF_ERR();
3839 RETURN_NONE();
3841 #endif /* DBVER >= 41 */
3843 #if (DBVER >= 40)
3844 static PyObject*
3845 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3847 int err;
3848 u_int32_t flags=0;
3849 u_int32_t timeout = 0;
3850 static char* kwnames[] = { "timeout", "flags", NULL };
3852 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3853 &timeout, &flags)) {
3854 return NULL;
3857 MYDB_BEGIN_ALLOW_THREADS;
3858 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3859 MYDB_END_ALLOW_THREADS;
3861 RETURN_IF_ERR();
3862 RETURN_NONE();
3864 #endif /* DBVER >= 40 */
3866 static PyObject*
3867 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3869 int err;
3870 long shm_key = 0;
3872 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3873 return NULL;
3874 CHECK_ENV_NOT_CLOSED(self);
3876 err = self->db_env->set_shm_key(self->db_env, shm_key);
3877 RETURN_IF_ERR();
3878 RETURN_NONE();
3881 static PyObject*
3882 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3884 int err, gbytes=0, bytes=0, ncache=0;
3886 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3887 &gbytes, &bytes, &ncache))
3888 return NULL;
3889 CHECK_ENV_NOT_CLOSED(self);
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3893 MYDB_END_ALLOW_THREADS;
3894 RETURN_IF_ERR();
3895 RETURN_NONE();
3899 static PyObject*
3900 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3902 int err, flags=0, onoff=0;
3904 if (!PyArg_ParseTuple(args, "ii:set_flags",
3905 &flags, &onoff))
3906 return NULL;
3907 CHECK_ENV_NOT_CLOSED(self);
3909 MYDB_BEGIN_ALLOW_THREADS;
3910 err = self->db_env->set_flags(self->db_env, flags, onoff);
3911 MYDB_END_ALLOW_THREADS;
3912 RETURN_IF_ERR();
3913 RETURN_NONE();
3917 static PyObject*
3918 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3920 int err;
3921 char *dir;
3923 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3924 return NULL;
3925 CHECK_ENV_NOT_CLOSED(self);
3927 MYDB_BEGIN_ALLOW_THREADS;
3928 err = self->db_env->set_data_dir(self->db_env, dir);
3929 MYDB_END_ALLOW_THREADS;
3930 RETURN_IF_ERR();
3931 RETURN_NONE();
3935 static PyObject*
3936 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3938 int err, lg_bsize;
3940 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3941 return NULL;
3942 CHECK_ENV_NOT_CLOSED(self);
3944 MYDB_BEGIN_ALLOW_THREADS;
3945 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3946 MYDB_END_ALLOW_THREADS;
3947 RETURN_IF_ERR();
3948 RETURN_NONE();
3952 static PyObject*
3953 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3955 int err;
3956 char *dir;
3958 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3959 return NULL;
3960 CHECK_ENV_NOT_CLOSED(self);
3962 MYDB_BEGIN_ALLOW_THREADS;
3963 err = self->db_env->set_lg_dir(self->db_env, dir);
3964 MYDB_END_ALLOW_THREADS;
3965 RETURN_IF_ERR();
3966 RETURN_NONE();
3969 static PyObject*
3970 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3972 int err, lg_max;
3974 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3975 return NULL;
3976 CHECK_ENV_NOT_CLOSED(self);
3978 MYDB_BEGIN_ALLOW_THREADS;
3979 err = self->db_env->set_lg_max(self->db_env, lg_max);
3980 MYDB_END_ALLOW_THREADS;
3981 RETURN_IF_ERR();
3982 RETURN_NONE();
3986 #if (DBVER >= 33)
3987 static PyObject*
3988 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3990 int err, lg_max;
3992 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3993 return NULL;
3994 CHECK_ENV_NOT_CLOSED(self);
3996 MYDB_BEGIN_ALLOW_THREADS;
3997 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3998 MYDB_END_ALLOW_THREADS;
3999 RETURN_IF_ERR();
4000 RETURN_NONE();
4002 #endif
4005 static PyObject*
4006 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4008 int err, lk_detect;
4010 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4011 return NULL;
4012 CHECK_ENV_NOT_CLOSED(self);
4014 MYDB_BEGIN_ALLOW_THREADS;
4015 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4016 MYDB_END_ALLOW_THREADS;
4017 RETURN_IF_ERR();
4018 RETURN_NONE();
4022 #if (DBVER < 45)
4023 static PyObject*
4024 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4026 int err, max;
4028 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4029 return NULL;
4030 CHECK_ENV_NOT_CLOSED(self);
4032 MYDB_BEGIN_ALLOW_THREADS;
4033 err = self->db_env->set_lk_max(self->db_env, max);
4034 MYDB_END_ALLOW_THREADS;
4035 RETURN_IF_ERR();
4036 RETURN_NONE();
4038 #endif
4042 static PyObject*
4043 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4045 int err, max;
4047 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4048 return NULL;
4049 CHECK_ENV_NOT_CLOSED(self);
4051 MYDB_BEGIN_ALLOW_THREADS;
4052 err = self->db_env->set_lk_max_locks(self->db_env, max);
4053 MYDB_END_ALLOW_THREADS;
4054 RETURN_IF_ERR();
4055 RETURN_NONE();
4059 static PyObject*
4060 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4062 int err, max;
4064 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4065 return NULL;
4066 CHECK_ENV_NOT_CLOSED(self);
4068 MYDB_BEGIN_ALLOW_THREADS;
4069 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4070 MYDB_END_ALLOW_THREADS;
4071 RETURN_IF_ERR();
4072 RETURN_NONE();
4076 static PyObject*
4077 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4079 int err, max;
4081 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4082 return NULL;
4083 CHECK_ENV_NOT_CLOSED(self);
4085 MYDB_BEGIN_ALLOW_THREADS;
4086 err = self->db_env->set_lk_max_objects(self->db_env, max);
4087 MYDB_END_ALLOW_THREADS;
4088 RETURN_IF_ERR();
4089 RETURN_NONE();
4093 static PyObject*
4094 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4096 int err, mp_mmapsize;
4098 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4099 return NULL;
4100 CHECK_ENV_NOT_CLOSED(self);
4102 MYDB_BEGIN_ALLOW_THREADS;
4103 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4104 MYDB_END_ALLOW_THREADS;
4105 RETURN_IF_ERR();
4106 RETURN_NONE();
4110 static PyObject*
4111 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4113 int err;
4114 char *dir;
4116 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4117 return NULL;
4118 CHECK_ENV_NOT_CLOSED(self);
4120 MYDB_BEGIN_ALLOW_THREADS;
4121 err = self->db_env->set_tmp_dir(self->db_env, dir);
4122 MYDB_END_ALLOW_THREADS;
4123 RETURN_IF_ERR();
4124 RETURN_NONE();
4128 static PyObject*
4129 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4131 int flags = 0;
4132 PyObject* txnobj = NULL;
4133 DB_TXN *txn = NULL;
4134 static char* kwnames[] = { "parent", "flags", NULL };
4136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4137 &txnobj, &flags))
4138 return NULL;
4140 if (!checkTxnObj(txnobj, &txn))
4141 return NULL;
4142 CHECK_ENV_NOT_CLOSED(self);
4144 return (PyObject*)newDBTxnObject(self, txn, flags);
4148 static PyObject*
4149 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4151 int err, kbyte=0, min=0, flags=0;
4153 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4154 return NULL;
4155 CHECK_ENV_NOT_CLOSED(self);
4157 MYDB_BEGIN_ALLOW_THREADS;
4158 #if (DBVER >= 40)
4159 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4160 #else
4161 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4162 #endif
4163 MYDB_END_ALLOW_THREADS;
4164 RETURN_IF_ERR();
4165 RETURN_NONE();
4169 static PyObject*
4170 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4172 int err, max;
4174 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4175 return NULL;
4176 CHECK_ENV_NOT_CLOSED(self);
4178 err = self->db_env->set_tx_max(self->db_env, max);
4179 RETURN_IF_ERR();
4180 RETURN_NONE();
4184 static PyObject*
4185 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4187 int err;
4188 long stamp;
4189 time_t timestamp;
4191 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4194 timestamp = (time_t)stamp;
4195 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4196 RETURN_IF_ERR();
4197 RETURN_NONE();
4201 static PyObject*
4202 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4204 int err, atype, flags=0;
4205 int aborted = 0;
4207 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4211 MYDB_BEGIN_ALLOW_THREADS;
4212 #if (DBVER >= 40)
4213 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4214 #else
4215 err = lock_detect(self->db_env, flags, atype, &aborted);
4216 #endif
4217 MYDB_END_ALLOW_THREADS;
4218 RETURN_IF_ERR();
4219 return PyInt_FromLong(aborted);
4223 static PyObject*
4224 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4226 int flags=0;
4227 int locker, lock_mode;
4228 DBT obj;
4229 PyObject* objobj;
4231 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4232 return NULL;
4235 if (!make_dbt(objobj, &obj))
4236 return NULL;
4238 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4242 static PyObject*
4243 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4245 int err;
4246 u_int32_t theID;
4248 if (!PyArg_ParseTuple(args, ":lock_id"))
4249 return NULL;
4251 CHECK_ENV_NOT_CLOSED(self);
4252 MYDB_BEGIN_ALLOW_THREADS;
4253 #if (DBVER >= 40)
4254 err = self->db_env->lock_id(self->db_env, &theID);
4255 #else
4256 err = lock_id(self->db_env, &theID);
4257 #endif
4258 MYDB_END_ALLOW_THREADS;
4259 RETURN_IF_ERR();
4261 return PyInt_FromLong((long)theID);
4264 #if (DBVER >= 40)
4265 static PyObject*
4266 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4268 int err;
4269 u_int32_t theID;
4271 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4272 return NULL;
4274 CHECK_ENV_NOT_CLOSED(self);
4275 MYDB_BEGIN_ALLOW_THREADS;
4276 err = self->db_env->lock_id_free(self->db_env, theID);
4277 MYDB_END_ALLOW_THREADS;
4278 RETURN_IF_ERR();
4279 RETURN_NONE();
4281 #endif
4283 static PyObject*
4284 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4286 int err;
4287 DBLockObject* dblockobj;
4289 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4290 return NULL;
4292 CHECK_ENV_NOT_CLOSED(self);
4293 MYDB_BEGIN_ALLOW_THREADS;
4294 #if (DBVER >= 40)
4295 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4296 #else
4297 err = lock_put(self->db_env, &dblockobj->lock);
4298 #endif
4299 MYDB_END_ALLOW_THREADS;
4300 RETURN_IF_ERR();
4301 RETURN_NONE();
4304 #if (DBVER >= 44)
4305 static PyObject*
4306 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4308 int err;
4309 char *file;
4310 u_int32_t flags = 0;
4311 static char* kwnames[] = { "file", "flags", NULL};
4313 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4314 &file, &flags))
4315 return NULL;
4316 CHECK_ENV_NOT_CLOSED(self);
4318 MYDB_BEGIN_ALLOW_THREADS;
4319 err = self->db_env->lsn_reset(self->db_env, file, flags);
4320 MYDB_END_ALLOW_THREADS;
4321 RETURN_IF_ERR();
4322 RETURN_NONE();
4324 #endif /* DBVER >= 4.4 */
4326 #if (DBVER >= 40)
4327 static PyObject*
4328 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4330 int err;
4331 DB_LOG_STAT* statp = NULL;
4332 PyObject* d = NULL;
4333 u_int32_t flags = 0;
4335 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4336 return NULL;
4337 CHECK_ENV_NOT_CLOSED(self);
4339 MYDB_BEGIN_ALLOW_THREADS;
4340 err = self->db_env->log_stat(self->db_env, &statp, flags);
4341 MYDB_END_ALLOW_THREADS;
4342 RETURN_IF_ERR();
4344 /* Turn the stat structure into a dictionary */
4345 d = PyDict_New();
4346 if (d == NULL) {
4347 if (statp)
4348 free(statp);
4349 return NULL;
4352 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4354 MAKE_ENTRY(magic);
4355 MAKE_ENTRY(version);
4356 MAKE_ENTRY(mode);
4357 MAKE_ENTRY(lg_bsize);
4358 #if (DBVER >= 44)
4359 MAKE_ENTRY(lg_size);
4360 MAKE_ENTRY(record);
4361 #endif
4362 #if (DBVER <= 40)
4363 MAKE_ENTRY(lg_max);
4364 #endif
4365 MAKE_ENTRY(w_mbytes);
4366 MAKE_ENTRY(w_bytes);
4367 MAKE_ENTRY(wc_mbytes);
4368 MAKE_ENTRY(wc_bytes);
4369 MAKE_ENTRY(wcount);
4370 MAKE_ENTRY(wcount_fill);
4371 #if (DBVER >= 44)
4372 MAKE_ENTRY(rcount);
4373 #endif
4374 MAKE_ENTRY(scount);
4375 MAKE_ENTRY(cur_file);
4376 MAKE_ENTRY(cur_offset);
4377 MAKE_ENTRY(disk_file);
4378 MAKE_ENTRY(disk_offset);
4379 MAKE_ENTRY(maxcommitperflush);
4380 MAKE_ENTRY(mincommitperflush);
4381 MAKE_ENTRY(regsize);
4382 MAKE_ENTRY(region_wait);
4383 MAKE_ENTRY(region_nowait);
4385 #undef MAKE_ENTRY
4386 free(statp);
4387 return d;
4388 } /* DBEnv_log_stat */
4389 #endif /* DBVER >= 4.0 for log_stat method */
4392 static PyObject*
4393 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4395 int err;
4396 DB_LOCK_STAT* sp;
4397 PyObject* d = NULL;
4398 u_int32_t flags = 0;
4400 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4401 return NULL;
4402 CHECK_ENV_NOT_CLOSED(self);
4404 MYDB_BEGIN_ALLOW_THREADS;
4405 #if (DBVER >= 40)
4406 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4407 #else
4408 #if (DBVER >= 33)
4409 err = lock_stat(self->db_env, &sp);
4410 #else
4411 err = lock_stat(self->db_env, &sp, NULL);
4412 #endif
4413 #endif
4414 MYDB_END_ALLOW_THREADS;
4415 RETURN_IF_ERR();
4417 /* Turn the stat structure into a dictionary */
4418 d = PyDict_New();
4419 if (d == NULL) {
4420 free(sp);
4421 return NULL;
4424 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4426 #if (DBVER < 41)
4427 MAKE_ENTRY(lastid);
4428 #endif
4429 MAKE_ENTRY(nmodes);
4430 MAKE_ENTRY(maxlocks);
4431 MAKE_ENTRY(maxlockers);
4432 MAKE_ENTRY(maxobjects);
4433 MAKE_ENTRY(nlocks);
4434 MAKE_ENTRY(maxnlocks);
4435 MAKE_ENTRY(nlockers);
4436 MAKE_ENTRY(maxnlockers);
4437 MAKE_ENTRY(nobjects);
4438 MAKE_ENTRY(maxnobjects);
4439 MAKE_ENTRY(nrequests);
4440 MAKE_ENTRY(nreleases);
4441 #if (DBVER < 44)
4442 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4443 MAKE_ENTRY(nconflicts);
4444 #else
4445 MAKE_ENTRY(lock_nowait);
4446 MAKE_ENTRY(lock_wait);
4447 #endif
4448 MAKE_ENTRY(ndeadlocks);
4449 MAKE_ENTRY(regsize);
4450 MAKE_ENTRY(region_wait);
4451 MAKE_ENTRY(region_nowait);
4453 #undef MAKE_ENTRY
4454 free(sp);
4455 return d;
4459 static PyObject*
4460 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4462 int flags=0;
4463 int err;
4464 char **log_list = NULL;
4465 PyObject* list;
4466 PyObject* item = NULL;
4468 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4469 return NULL;
4471 CHECK_ENV_NOT_CLOSED(self);
4472 MYDB_BEGIN_ALLOW_THREADS;
4473 #if (DBVER >= 40)
4474 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4475 #elif (DBVER == 33)
4476 err = log_archive(self->db_env, &log_list, flags);
4477 #else
4478 err = log_archive(self->db_env, &log_list, flags, NULL);
4479 #endif
4480 MYDB_END_ALLOW_THREADS;
4481 RETURN_IF_ERR();
4483 list = PyList_New(0);
4484 if (list == NULL) {
4485 if (log_list)
4486 free(log_list);
4487 return NULL;
4490 if (log_list) {
4491 char **log_list_start;
4492 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4493 item = PyString_FromString (*log_list);
4494 if (item == NULL) {
4495 Py_DECREF(list);
4496 list = NULL;
4497 break;
4499 PyList_Append(list, item);
4500 Py_DECREF(item);
4502 free(log_list_start);
4504 return list;
4508 static PyObject*
4509 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4511 int err;
4512 DB_TXN_STAT* sp;
4513 PyObject* d = NULL;
4514 u_int32_t flags=0;
4516 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4517 return NULL;
4518 CHECK_ENV_NOT_CLOSED(self);
4520 MYDB_BEGIN_ALLOW_THREADS;
4521 #if (DBVER >= 40)
4522 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4523 #elif (DBVER == 33)
4524 err = txn_stat(self->db_env, &sp);
4525 #else
4526 err = txn_stat(self->db_env, &sp, NULL);
4527 #endif
4528 MYDB_END_ALLOW_THREADS;
4529 RETURN_IF_ERR();
4531 /* Turn the stat structure into a dictionary */
4532 d = PyDict_New();
4533 if (d == NULL) {
4534 free(sp);
4535 return NULL;
4538 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4539 #define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
4541 MAKE_TIME_T_ENTRY(time_ckp);
4542 MAKE_ENTRY(last_txnid);
4543 MAKE_ENTRY(maxtxns);
4544 MAKE_ENTRY(nactive);
4545 MAKE_ENTRY(maxnactive);
4546 MAKE_ENTRY(nbegins);
4547 MAKE_ENTRY(naborts);
4548 MAKE_ENTRY(ncommits);
4549 MAKE_ENTRY(regsize);
4550 MAKE_ENTRY(region_wait);
4551 MAKE_ENTRY(region_nowait);
4553 #undef MAKE_ENTRY
4554 #undef MAKE_TIME_T_ENTRY
4555 free(sp);
4556 return d;
4560 static PyObject*
4561 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4563 int flags=0;
4564 int oldValue=0;
4566 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4567 return NULL;
4568 CHECK_ENV_NOT_CLOSED(self);
4570 if (self->moduleFlags.getReturnsNone)
4571 ++oldValue;
4572 if (self->moduleFlags.cursorSetReturnsNone)
4573 ++oldValue;
4574 self->moduleFlags.getReturnsNone = (flags >= 1);
4575 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4576 return PyInt_FromLong(oldValue);
4580 /* --------------------------------------------------------------------- */
4581 /* DBTxn methods */
4584 static PyObject*
4585 DBTxn_commit(DBTxnObject* self, PyObject* args)
4587 int flags=0, err;
4588 DB_TXN *txn;
4590 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4591 return NULL;
4593 if (!self->txn) {
4594 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4595 "after txn_commit or txn_abort");
4596 PyErr_SetObject(DBError, t);
4597 Py_DECREF(t);
4598 return NULL;
4600 txn = self->txn;
4601 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4602 MYDB_BEGIN_ALLOW_THREADS;
4603 #if (DBVER >= 40)
4604 err = txn->commit(txn, flags);
4605 #else
4606 err = txn_commit(txn, flags);
4607 #endif
4608 MYDB_END_ALLOW_THREADS;
4609 RETURN_IF_ERR();
4610 RETURN_NONE();
4613 static PyObject*
4614 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4616 #if (DBVER >= 33)
4617 int err;
4618 char* gid=NULL;
4619 int gid_size=0;
4621 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4622 return NULL;
4624 if (gid_size != DB_XIDDATASIZE) {
4625 PyErr_SetString(PyExc_TypeError,
4626 "gid must be DB_XIDDATASIZE bytes long");
4627 return NULL;
4630 if (!self->txn) {
4631 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4632 "after txn_commit or txn_abort");
4633 PyErr_SetObject(DBError, t);
4634 Py_DECREF(t);
4635 return NULL;
4637 MYDB_BEGIN_ALLOW_THREADS;
4638 #if (DBVER >= 40)
4639 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4640 #else
4641 err = txn_prepare(self->txn, (u_int8_t*)gid);
4642 #endif
4643 MYDB_END_ALLOW_THREADS;
4644 RETURN_IF_ERR();
4645 RETURN_NONE();
4646 #else
4647 int err;
4649 if (!PyArg_ParseTuple(args, ":prepare"))
4650 return NULL;
4652 if (!self->txn) {
4653 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4654 "after txn_commit or txn_abort");
4655 PyErr_SetObject(DBError, t);
4656 Py_DECREF(t);
4657 return NULL;
4659 MYDB_BEGIN_ALLOW_THREADS;
4660 err = txn_prepare(self->txn);
4661 MYDB_END_ALLOW_THREADS;
4662 RETURN_IF_ERR();
4663 RETURN_NONE();
4664 #endif
4668 static PyObject*
4669 DBTxn_abort(DBTxnObject* self, PyObject* args)
4671 int err;
4672 DB_TXN *txn;
4674 if (!PyArg_ParseTuple(args, ":abort"))
4675 return NULL;
4677 if (!self->txn) {
4678 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4679 "after txn_commit or txn_abort");
4680 PyErr_SetObject(DBError, t);
4681 Py_DECREF(t);
4682 return NULL;
4684 txn = self->txn;
4685 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4686 MYDB_BEGIN_ALLOW_THREADS;
4687 #if (DBVER >= 40)
4688 err = txn->abort(txn);
4689 #else
4690 err = txn_abort(txn);
4691 #endif
4692 MYDB_END_ALLOW_THREADS;
4693 RETURN_IF_ERR();
4694 RETURN_NONE();
4698 static PyObject*
4699 DBTxn_id(DBTxnObject* self, PyObject* args)
4701 int id;
4703 if (!PyArg_ParseTuple(args, ":id"))
4704 return NULL;
4706 if (!self->txn) {
4707 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4708 "after txn_commit or txn_abort");
4709 PyErr_SetObject(DBError, t);
4710 Py_DECREF(t);
4711 return NULL;
4713 MYDB_BEGIN_ALLOW_THREADS;
4714 #if (DBVER >= 40)
4715 id = self->txn->id(self->txn);
4716 #else
4717 id = txn_id(self->txn);
4718 #endif
4719 MYDB_END_ALLOW_THREADS;
4720 return PyInt_FromLong(id);
4723 #if (DBVER >= 43)
4724 /* --------------------------------------------------------------------- */
4725 /* DBSequence methods */
4728 static PyObject*
4729 DBSequence_close(DBSequenceObject* self, PyObject* args)
4731 int err, flags=0;
4732 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4733 return NULL;
4734 CHECK_SEQUENCE_NOT_CLOSED(self)
4736 MYDB_BEGIN_ALLOW_THREADS
4737 err = self->sequence->close(self->sequence, flags);
4738 self->sequence = NULL;
4739 MYDB_END_ALLOW_THREADS
4741 RETURN_IF_ERR();
4743 RETURN_NONE();
4746 static PyObject*
4747 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4749 int err, flags = 0;
4750 int delta = 1;
4751 db_seq_t value;
4752 PyObject *txnobj = NULL;
4753 DB_TXN *txn = NULL;
4754 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4755 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4756 return NULL;
4757 CHECK_SEQUENCE_NOT_CLOSED(self)
4759 if (!checkTxnObj(txnobj, &txn))
4760 return NULL;
4762 MYDB_BEGIN_ALLOW_THREADS
4763 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4764 MYDB_END_ALLOW_THREADS
4766 RETURN_IF_ERR();
4767 return PyLong_FromLongLong(value);
4771 static PyObject*
4772 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4774 if (!PyArg_ParseTuple(args,":get_dbp"))
4775 return NULL;
4776 CHECK_SEQUENCE_NOT_CLOSED(self)
4777 Py_INCREF(self->mydb);
4778 return (PyObject* )self->mydb;
4781 static PyObject*
4782 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4784 int err;
4785 DBT key;
4786 PyObject *retval = NULL;
4787 key.flags = DB_DBT_MALLOC;
4788 CHECK_SEQUENCE_NOT_CLOSED(self)
4789 MYDB_BEGIN_ALLOW_THREADS
4790 err = self->sequence->get_key(self->sequence, &key);
4791 MYDB_END_ALLOW_THREADS
4793 if (!err)
4794 retval = PyString_FromStringAndSize(key.data, key.size);
4796 FREE_DBT(key);
4797 RETURN_IF_ERR();
4799 return retval;
4802 static PyObject*
4803 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4805 int err;
4806 db_seq_t value;
4807 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4808 return NULL;
4809 CHECK_SEQUENCE_NOT_CLOSED(self)
4811 MYDB_BEGIN_ALLOW_THREADS
4812 err = self->sequence->initial_value(self->sequence, value);
4813 MYDB_END_ALLOW_THREADS
4815 RETURN_IF_ERR();
4817 RETURN_NONE();
4820 static PyObject*
4821 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4823 int err, flags = 0;
4824 PyObject* keyobj;
4825 PyObject *txnobj = NULL;
4826 DB_TXN *txn = NULL;
4827 DBT key;
4829 static char* kwnames[] = {"key", "txn", "flags", NULL };
4830 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4831 return NULL;
4833 if (!checkTxnObj(txnobj, &txn))
4834 return NULL;
4836 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4837 return NULL;
4839 MYDB_BEGIN_ALLOW_THREADS
4840 err = self->sequence->open(self->sequence, txn, &key, flags);
4841 MYDB_END_ALLOW_THREADS
4843 CLEAR_DBT(key);
4844 RETURN_IF_ERR();
4846 RETURN_NONE();
4849 static PyObject*
4850 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4852 int err, flags = 0;
4853 PyObject *txnobj = NULL;
4854 DB_TXN *txn = NULL;
4856 static char* kwnames[] = {"txn", "flags", NULL };
4857 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4858 return NULL;
4860 if (!checkTxnObj(txnobj, &txn))
4861 return NULL;
4863 CHECK_SEQUENCE_NOT_CLOSED(self)
4865 MYDB_BEGIN_ALLOW_THREADS
4866 err = self->sequence->remove(self->sequence, txn, flags);
4867 MYDB_END_ALLOW_THREADS
4869 RETURN_IF_ERR();
4870 RETURN_NONE();
4873 static PyObject*
4874 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4876 int err, size;
4877 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4878 return NULL;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4881 MYDB_BEGIN_ALLOW_THREADS
4882 err = self->sequence->set_cachesize(self->sequence, size);
4883 MYDB_END_ALLOW_THREADS
4885 RETURN_IF_ERR();
4886 RETURN_NONE();
4889 static PyObject*
4890 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4892 int err, size;
4893 if (!PyArg_ParseTuple(args,":get_cachesize"))
4894 return NULL;
4895 CHECK_SEQUENCE_NOT_CLOSED(self)
4897 MYDB_BEGIN_ALLOW_THREADS
4898 err = self->sequence->get_cachesize(self->sequence, &size);
4899 MYDB_END_ALLOW_THREADS
4901 RETURN_IF_ERR();
4902 return PyInt_FromLong(size);
4905 static PyObject*
4906 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4908 int err, flags = 0;
4909 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4910 return NULL;
4911 CHECK_SEQUENCE_NOT_CLOSED(self)
4913 MYDB_BEGIN_ALLOW_THREADS
4914 err = self->sequence->set_flags(self->sequence, flags);
4915 MYDB_END_ALLOW_THREADS
4917 RETURN_IF_ERR();
4918 RETURN_NONE();
4922 static PyObject*
4923 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4925 unsigned int flags;
4926 int err;
4927 if (!PyArg_ParseTuple(args,":get_flags"))
4928 return NULL;
4929 CHECK_SEQUENCE_NOT_CLOSED(self)
4931 MYDB_BEGIN_ALLOW_THREADS
4932 err = self->sequence->get_flags(self->sequence, &flags);
4933 MYDB_END_ALLOW_THREADS
4935 RETURN_IF_ERR();
4936 return PyInt_FromLong((int)flags);
4939 static PyObject*
4940 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4942 int err;
4943 db_seq_t min, max;
4944 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
4945 return NULL;
4946 CHECK_SEQUENCE_NOT_CLOSED(self)
4948 MYDB_BEGIN_ALLOW_THREADS
4949 err = self->sequence->set_range(self->sequence, min, max);
4950 MYDB_END_ALLOW_THREADS
4952 RETURN_IF_ERR();
4953 RETURN_NONE();
4956 static PyObject*
4957 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4959 int err;
4960 db_seq_t min, max;
4961 if (!PyArg_ParseTuple(args,":get_range"))
4962 return NULL;
4963 CHECK_SEQUENCE_NOT_CLOSED(self)
4965 MYDB_BEGIN_ALLOW_THREADS
4966 err = self->sequence->get_range(self->sequence, &min, &max);
4967 MYDB_END_ALLOW_THREADS
4969 RETURN_IF_ERR();
4970 return Py_BuildValue("(LL)", min, max);
4973 static PyObject*
4974 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4976 int err, flags = 0;
4977 DB_SEQUENCE_STAT* sp = NULL;
4978 PyObject* dict_stat;
4979 static char* kwnames[] = {"flags", NULL };
4980 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4981 return NULL;
4982 CHECK_SEQUENCE_NOT_CLOSED(self);
4984 MYDB_BEGIN_ALLOW_THREADS;
4985 err = self->sequence->stat(self->sequence, &sp, flags);
4986 MYDB_END_ALLOW_THREADS;
4987 RETURN_IF_ERR();
4989 if ((dict_stat = PyDict_New()) == NULL) {
4990 free(sp);
4991 return NULL;
4995 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4996 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4998 MAKE_INT_ENTRY(wait);
4999 MAKE_INT_ENTRY(nowait);
5000 MAKE_LONG_LONG_ENTRY(current);
5001 MAKE_LONG_LONG_ENTRY(value);
5002 MAKE_LONG_LONG_ENTRY(last_value);
5003 MAKE_LONG_LONG_ENTRY(min);
5004 MAKE_LONG_LONG_ENTRY(max);
5005 MAKE_INT_ENTRY(cache_size);
5006 MAKE_INT_ENTRY(flags);
5008 #undef MAKE_INT_ENTRY
5009 #undef MAKE_LONG_LONG_ENTRY
5011 free(sp);
5012 return dict_stat;
5014 #endif
5017 /* --------------------------------------------------------------------- */
5018 /* Method definition tables and type objects */
5020 static PyMethodDef DB_methods[] = {
5021 {"append", (PyCFunction)DB_append, METH_VARARGS},
5022 #if (DBVER >= 33)
5023 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5024 #endif
5025 {"close", (PyCFunction)DB_close, METH_VARARGS},
5026 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5027 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5028 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5029 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5030 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5031 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5032 #if (DBVER >= 33)
5033 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5034 #endif
5035 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5036 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5037 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5038 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5039 {"join", (PyCFunction)DB_join, METH_VARARGS},
5040 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5041 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5042 {"items", (PyCFunction)DB_items, METH_VARARGS},
5043 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5044 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5045 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5046 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5047 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5048 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5049 #if (DBVER >= 33)
5050 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5051 #endif
5052 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5053 #if (DBVER >= 41)
5054 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5055 #endif
5056 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5057 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5058 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5059 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5060 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5061 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5062 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5063 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5064 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5065 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5066 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5067 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5068 #if (DBVER >= 33)
5069 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5070 #endif
5071 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5072 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5073 {"values", (PyCFunction)DB_values, METH_VARARGS},
5074 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5075 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5076 {NULL, NULL} /* sentinel */
5080 static PyMappingMethods DB_mapping = {
5081 DB_length, /*mp_length*/
5082 (binaryfunc)DB_subscript, /*mp_subscript*/
5083 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5087 static PyMethodDef DBCursor_methods[] = {
5088 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5089 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5090 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5091 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5092 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5093 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5094 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5095 #if (DBVER >= 33)
5096 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5097 #endif
5098 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5099 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5100 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5101 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5102 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5103 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5104 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5105 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5106 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5107 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5108 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5109 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5110 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5111 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5112 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5113 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5114 {NULL, NULL} /* sentinel */
5118 static PyMethodDef DBEnv_methods[] = {
5119 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5120 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5121 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5122 #if (DBVER >= 41)
5123 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5124 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5125 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5126 #endif
5127 #if (DBVER >= 40)
5128 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5129 #endif
5130 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5131 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5132 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5133 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5134 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5135 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5136 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5137 #if (DBVER >= 33)
5138 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5139 #endif
5140 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5141 #if (DBVER < 45)
5142 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5143 #endif
5144 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5145 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5146 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5147 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5148 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5149 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5150 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5151 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5152 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5153 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5154 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5155 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5156 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5157 #if (DBVER >= 40)
5158 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5159 #endif
5160 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5161 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5162 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5163 #if (DBVER >= 40)
5164 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5165 #endif
5166 #if (DBVER >= 44)
5167 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5168 #endif
5169 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5170 {NULL, NULL} /* sentinel */
5174 static PyMethodDef DBTxn_methods[] = {
5175 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5176 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5177 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5178 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5179 {NULL, NULL} /* sentinel */
5183 #if (DBVER >= 43)
5184 static PyMethodDef DBSequence_methods[] = {
5185 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5186 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5187 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5188 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5189 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5190 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5191 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5192 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5193 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5194 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5195 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5196 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5197 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5198 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5199 {NULL, NULL} /* sentinel */
5201 #endif
5204 static PyObject*
5205 DB_getattr(DBObject* self, char *name)
5207 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5211 static PyObject*
5212 DBEnv_getattr(DBEnvObject* self, char *name)
5214 if (!strcmp(name, "db_home")) {
5215 CHECK_ENV_NOT_CLOSED(self);
5216 if (self->db_env->db_home == NULL) {
5217 RETURN_NONE();
5219 return PyString_FromString(self->db_env->db_home);
5222 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5226 static PyObject*
5227 DBCursor_getattr(DBCursorObject* self, char *name)
5229 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5232 static PyObject*
5233 DBTxn_getattr(DBTxnObject* self, char *name)
5235 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5238 static PyObject*
5239 DBLock_getattr(DBLockObject* self, char *name)
5241 return NULL;
5244 #if (DBVER >= 43)
5245 static PyObject*
5246 DBSequence_getattr(DBSequenceObject* self, char *name)
5248 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5250 #endif
5252 statichere PyTypeObject DB_Type = {
5253 PyObject_HEAD_INIT(NULL)
5254 0, /*ob_size*/
5255 "DB", /*tp_name*/
5256 sizeof(DBObject), /*tp_basicsize*/
5257 0, /*tp_itemsize*/
5258 /* methods */
5259 (destructor)DB_dealloc, /*tp_dealloc*/
5260 0, /*tp_print*/
5261 (getattrfunc)DB_getattr, /*tp_getattr*/
5262 0, /*tp_setattr*/
5263 0, /*tp_compare*/
5264 0, /*tp_repr*/
5265 0, /*tp_as_number*/
5266 0, /*tp_as_sequence*/
5267 &DB_mapping,/*tp_as_mapping*/
5268 0, /*tp_hash*/
5269 0, /* tp_call */
5270 0, /* tp_str */
5271 0, /* tp_getattro */
5272 0, /* tp_setattro */
5273 0, /* tp_as_buffer */
5274 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5275 0, /* tp_doc */
5276 0, /* tp_traverse */
5277 0, /* tp_clear */
5278 0, /* tp_richcompare */
5279 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5283 statichere PyTypeObject DBCursor_Type = {
5284 PyObject_HEAD_INIT(NULL)
5285 0, /*ob_size*/
5286 "DBCursor", /*tp_name*/
5287 sizeof(DBCursorObject), /*tp_basicsize*/
5288 0, /*tp_itemsize*/
5289 /* methods */
5290 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5291 0, /*tp_print*/
5292 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5293 0, /*tp_setattr*/
5294 0, /*tp_compare*/
5295 0, /*tp_repr*/
5296 0, /*tp_as_number*/
5297 0, /*tp_as_sequence*/
5298 0, /*tp_as_mapping*/
5299 0, /*tp_hash*/
5300 0, /* tp_call */
5301 0, /* tp_str */
5302 0, /* tp_getattro */
5303 0, /* tp_setattro */
5304 0, /* tp_as_buffer */
5305 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5306 0, /* tp_doc */
5307 0, /* tp_traverse */
5308 0, /* tp_clear */
5309 0, /* tp_richcompare */
5310 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5314 statichere PyTypeObject DBEnv_Type = {
5315 PyObject_HEAD_INIT(NULL)
5316 0, /*ob_size*/
5317 "DBEnv", /*tp_name*/
5318 sizeof(DBEnvObject), /*tp_basicsize*/
5319 0, /*tp_itemsize*/
5320 /* methods */
5321 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5322 0, /*tp_print*/
5323 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5324 0, /*tp_setattr*/
5325 0, /*tp_compare*/
5326 0, /*tp_repr*/
5327 0, /*tp_as_number*/
5328 0, /*tp_as_sequence*/
5329 0, /*tp_as_mapping*/
5330 0, /*tp_hash*/
5331 0, /* tp_call */
5332 0, /* tp_str */
5333 0, /* tp_getattro */
5334 0, /* tp_setattro */
5335 0, /* tp_as_buffer */
5336 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5337 0, /* tp_doc */
5338 0, /* tp_traverse */
5339 0, /* tp_clear */
5340 0, /* tp_richcompare */
5341 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5344 statichere PyTypeObject DBTxn_Type = {
5345 PyObject_HEAD_INIT(NULL)
5346 0, /*ob_size*/
5347 "DBTxn", /*tp_name*/
5348 sizeof(DBTxnObject), /*tp_basicsize*/
5349 0, /*tp_itemsize*/
5350 /* methods */
5351 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5352 0, /*tp_print*/
5353 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5354 0, /*tp_setattr*/
5355 0, /*tp_compare*/
5356 0, /*tp_repr*/
5357 0, /*tp_as_number*/
5358 0, /*tp_as_sequence*/
5359 0, /*tp_as_mapping*/
5360 0, /*tp_hash*/
5361 0, /* tp_call */
5362 0, /* tp_str */
5363 0, /* tp_getattro */
5364 0, /* tp_setattro */
5365 0, /* tp_as_buffer */
5366 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5367 0, /* tp_doc */
5368 0, /* tp_traverse */
5369 0, /* tp_clear */
5370 0, /* tp_richcompare */
5371 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5375 statichere PyTypeObject DBLock_Type = {
5376 PyObject_HEAD_INIT(NULL)
5377 0, /*ob_size*/
5378 "DBLock", /*tp_name*/
5379 sizeof(DBLockObject), /*tp_basicsize*/
5380 0, /*tp_itemsize*/
5381 /* methods */
5382 (destructor)DBLock_dealloc, /*tp_dealloc*/
5383 0, /*tp_print*/
5384 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5385 0, /*tp_setattr*/
5386 0, /*tp_compare*/
5387 0, /*tp_repr*/
5388 0, /*tp_as_number*/
5389 0, /*tp_as_sequence*/
5390 0, /*tp_as_mapping*/
5391 0, /*tp_hash*/
5392 0, /* tp_call */
5393 0, /* tp_str */
5394 0, /* tp_getattro */
5395 0, /* tp_setattro */
5396 0, /* tp_as_buffer */
5397 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5398 0, /* tp_doc */
5399 0, /* tp_traverse */
5400 0, /* tp_clear */
5401 0, /* tp_richcompare */
5402 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5405 #if (DBVER >= 43)
5406 statichere PyTypeObject DBSequence_Type = {
5407 PyObject_HEAD_INIT(NULL)
5408 0, /*ob_size*/
5409 "DBSequence", /*tp_name*/
5410 sizeof(DBSequenceObject), /*tp_basicsize*/
5411 0, /*tp_itemsize*/
5412 /* methods */
5413 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5414 0, /*tp_print*/
5415 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5416 0, /*tp_setattr*/
5417 0, /*tp_compare*/
5418 0, /*tp_repr*/
5419 0, /*tp_as_number*/
5420 0, /*tp_as_sequence*/
5421 0, /*tp_as_mapping*/
5422 0, /*tp_hash*/
5423 0, /* tp_call */
5424 0, /* tp_str */
5425 0, /* tp_getattro */
5426 0, /* tp_setattro */
5427 0, /* tp_as_buffer */
5428 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5429 0, /* tp_doc */
5430 0, /* tp_traverse */
5431 0, /* tp_clear */
5432 0, /* tp_richcompare */
5433 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5435 #endif
5437 /* --------------------------------------------------------------------- */
5438 /* Module-level functions */
5440 static PyObject*
5441 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5443 PyObject* dbenvobj = NULL;
5444 int flags = 0;
5445 static char* kwnames[] = { "dbEnv", "flags", NULL};
5447 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5448 &dbenvobj, &flags))
5449 return NULL;
5450 if (dbenvobj == Py_None)
5451 dbenvobj = NULL;
5452 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5453 makeTypeError("DBEnv", dbenvobj);
5454 return NULL;
5457 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5461 static PyObject*
5462 DBEnv_construct(PyObject* self, PyObject* args)
5464 int flags = 0;
5465 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5466 return (PyObject* )newDBEnvObject(flags);
5469 #if (DBVER >= 43)
5470 static PyObject*
5471 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5473 PyObject* dbobj;
5474 int flags = 0;
5475 static char* kwnames[] = { "db", "flags", NULL};
5477 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5478 return NULL;
5479 if (!DBObject_Check(dbobj)) {
5480 makeTypeError("DB", dbobj);
5481 return NULL;
5483 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5485 #endif
5487 static char bsddb_version_doc[] =
5488 "Returns a tuple of major, minor, and patch release numbers of the\n\
5489 underlying DB library.";
5491 static PyObject*
5492 bsddb_version(PyObject* self, PyObject* args)
5494 int major, minor, patch;
5496 if (!PyArg_ParseTuple(args, ":version"))
5497 return NULL;
5498 db_version(&major, &minor, &patch);
5499 return Py_BuildValue("(iii)", major, minor, patch);
5503 /* List of functions defined in the module */
5505 static PyMethodDef bsddb_methods[] = {
5506 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5507 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5508 #if (DBVER >= 43)
5509 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5510 #endif
5511 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5512 {NULL, NULL} /* sentinel */
5515 /* API structure */
5516 static BSDDB_api bsddb_api;
5519 /* --------------------------------------------------------------------- */
5520 /* Module initialization */
5523 /* Convenience routine to export an integer value.
5524 * Errors are silently ignored, for better or for worse...
5526 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5528 #define MODULE_NAME_MAX_LEN 11
5529 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5531 DL_EXPORT(void) init_bsddb(void)
5533 PyObject* m;
5534 PyObject* d;
5535 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5536 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5537 PyObject* cvsid_s = PyString_FromString( rcs_id );
5538 PyObject* py_api;
5540 /* Initialize the type of the new type objects here; doing it here
5541 is required for portability to Windows without requiring C++. */
5542 Py_TYPE(&DB_Type) = &PyType_Type;
5543 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5544 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5545 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5546 Py_TYPE(&DBLock_Type) = &PyType_Type;
5547 #if (DBVER >= 43)
5548 Py_TYPE(&DBSequence_Type) = &PyType_Type;
5549 #endif
5552 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5553 /* Save the current interpreter, so callbacks can do the right thing. */
5554 _db_interpreterState = PyThreadState_GET()->interp;
5555 #endif
5557 /* Create the module and add the functions */
5558 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5559 if (m == NULL)
5560 return;
5562 /* Add some symbolic constants to the module */
5563 d = PyModule_GetDict(m);
5564 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5565 PyDict_SetItemString(d, "cvsid", cvsid_s);
5566 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5567 Py_DECREF(pybsddb_version_s);
5568 pybsddb_version_s = NULL;
5569 Py_DECREF(cvsid_s);
5570 cvsid_s = NULL;
5571 Py_DECREF(db_version_s);
5572 db_version_s = NULL;
5574 ADD_INT(d, DB_VERSION_MAJOR);
5575 ADD_INT(d, DB_VERSION_MINOR);
5576 ADD_INT(d, DB_VERSION_PATCH);
5578 ADD_INT(d, DB_MAX_PAGES);
5579 ADD_INT(d, DB_MAX_RECORDS);
5581 #if (DBVER >= 42)
5582 ADD_INT(d, DB_RPCCLIENT);
5583 #else
5584 ADD_INT(d, DB_CLIENT);
5585 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5586 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5587 #endif
5588 ADD_INT(d, DB_XA_CREATE);
5590 ADD_INT(d, DB_CREATE);
5591 ADD_INT(d, DB_NOMMAP);
5592 ADD_INT(d, DB_THREAD);
5594 ADD_INT(d, DB_FORCE);
5595 ADD_INT(d, DB_INIT_CDB);
5596 ADD_INT(d, DB_INIT_LOCK);
5597 ADD_INT(d, DB_INIT_LOG);
5598 ADD_INT(d, DB_INIT_MPOOL);
5599 ADD_INT(d, DB_INIT_TXN);
5600 ADD_INT(d, DB_JOINENV);
5602 ADD_INT(d, DB_RECOVER);
5603 ADD_INT(d, DB_RECOVER_FATAL);
5604 ADD_INT(d, DB_TXN_NOSYNC);
5605 ADD_INT(d, DB_USE_ENVIRON);
5606 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5608 ADD_INT(d, DB_LOCKDOWN);
5609 ADD_INT(d, DB_PRIVATE);
5610 ADD_INT(d, DB_SYSTEM_MEM);
5612 ADD_INT(d, DB_TXN_SYNC);
5613 ADD_INT(d, DB_TXN_NOWAIT);
5615 ADD_INT(d, DB_EXCL);
5616 ADD_INT(d, DB_FCNTL_LOCKING);
5617 ADD_INT(d, DB_ODDFILESIZE);
5618 ADD_INT(d, DB_RDWRMASTER);
5619 ADD_INT(d, DB_RDONLY);
5620 ADD_INT(d, DB_TRUNCATE);
5621 ADD_INT(d, DB_EXTENT);
5622 ADD_INT(d, DB_CDB_ALLDB);
5623 ADD_INT(d, DB_VERIFY);
5624 ADD_INT(d, DB_UPGRADE);
5626 ADD_INT(d, DB_AGGRESSIVE);
5627 ADD_INT(d, DB_NOORDERCHK);
5628 ADD_INT(d, DB_ORDERCHKONLY);
5629 ADD_INT(d, DB_PR_PAGE);
5630 #if ! (DBVER >= 33)
5631 ADD_INT(d, DB_VRFY_FLAGMASK);
5632 ADD_INT(d, DB_PR_HEADERS);
5633 #endif
5634 ADD_INT(d, DB_PR_RECOVERYTEST);
5635 ADD_INT(d, DB_SALVAGE);
5637 ADD_INT(d, DB_LOCK_NORUN);
5638 ADD_INT(d, DB_LOCK_DEFAULT);
5639 ADD_INT(d, DB_LOCK_OLDEST);
5640 ADD_INT(d, DB_LOCK_RANDOM);
5641 ADD_INT(d, DB_LOCK_YOUNGEST);
5642 #if (DBVER >= 33)
5643 ADD_INT(d, DB_LOCK_MAXLOCKS);
5644 ADD_INT(d, DB_LOCK_MINLOCKS);
5645 ADD_INT(d, DB_LOCK_MINWRITE);
5646 #endif
5649 #if (DBVER >= 33)
5650 /* docs say to use zero instead */
5651 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5652 #else
5653 ADD_INT(d, DB_LOCK_CONFLICT);
5654 #endif
5656 ADD_INT(d, DB_LOCK_DUMP);
5657 ADD_INT(d, DB_LOCK_GET);
5658 ADD_INT(d, DB_LOCK_INHERIT);
5659 ADD_INT(d, DB_LOCK_PUT);
5660 ADD_INT(d, DB_LOCK_PUT_ALL);
5661 ADD_INT(d, DB_LOCK_PUT_OBJ);
5663 ADD_INT(d, DB_LOCK_NG);
5664 ADD_INT(d, DB_LOCK_READ);
5665 ADD_INT(d, DB_LOCK_WRITE);
5666 ADD_INT(d, DB_LOCK_NOWAIT);
5667 ADD_INT(d, DB_LOCK_WAIT);
5668 ADD_INT(d, DB_LOCK_IWRITE);
5669 ADD_INT(d, DB_LOCK_IREAD);
5670 ADD_INT(d, DB_LOCK_IWR);
5671 #if (DBVER >= 33)
5672 #if (DBVER < 44)
5673 ADD_INT(d, DB_LOCK_DIRTY);
5674 #else
5675 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5676 #endif
5677 ADD_INT(d, DB_LOCK_WWRITE);
5678 #endif
5680 ADD_INT(d, DB_LOCK_RECORD);
5681 ADD_INT(d, DB_LOCK_UPGRADE);
5682 ADD_INT(d, DB_LOCK_SWITCH);
5683 #if (DBVER >= 33)
5684 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5685 #endif
5687 ADD_INT(d, DB_LOCK_NOWAIT);
5688 ADD_INT(d, DB_LOCK_RECORD);
5689 ADD_INT(d, DB_LOCK_UPGRADE);
5691 #if (DBVER >= 33)
5692 ADD_INT(d, DB_LSTAT_ABORTED);
5693 #if (DBVER < 43)
5694 ADD_INT(d, DB_LSTAT_ERR);
5695 #endif
5696 ADD_INT(d, DB_LSTAT_FREE);
5697 ADD_INT(d, DB_LSTAT_HELD);
5698 #if (DBVER == 33)
5699 ADD_INT(d, DB_LSTAT_NOGRANT);
5700 #endif
5701 ADD_INT(d, DB_LSTAT_PENDING);
5702 ADD_INT(d, DB_LSTAT_WAITING);
5703 #endif
5705 ADD_INT(d, DB_ARCH_ABS);
5706 ADD_INT(d, DB_ARCH_DATA);
5707 ADD_INT(d, DB_ARCH_LOG);
5708 #if (DBVER >= 42)
5709 ADD_INT(d, DB_ARCH_REMOVE);
5710 #endif
5712 ADD_INT(d, DB_BTREE);
5713 ADD_INT(d, DB_HASH);
5714 ADD_INT(d, DB_RECNO);
5715 ADD_INT(d, DB_QUEUE);
5716 ADD_INT(d, DB_UNKNOWN);
5718 ADD_INT(d, DB_DUP);
5719 ADD_INT(d, DB_DUPSORT);
5720 ADD_INT(d, DB_RECNUM);
5721 ADD_INT(d, DB_RENUMBER);
5722 ADD_INT(d, DB_REVSPLITOFF);
5723 ADD_INT(d, DB_SNAPSHOT);
5725 ADD_INT(d, DB_JOIN_NOSORT);
5727 ADD_INT(d, DB_AFTER);
5728 ADD_INT(d, DB_APPEND);
5729 ADD_INT(d, DB_BEFORE);
5730 #if (DBVER < 45)
5731 ADD_INT(d, DB_CACHED_COUNTS);
5732 #endif
5733 #if (DBVER >= 41)
5734 _addIntToDict(d, "DB_CHECKPOINT", 0);
5735 #else
5736 ADD_INT(d, DB_CHECKPOINT);
5737 ADD_INT(d, DB_CURLSN);
5738 #endif
5739 #if ((DBVER >= 33) && (DBVER <= 41))
5740 ADD_INT(d, DB_COMMIT);
5741 #endif
5742 ADD_INT(d, DB_CONSUME);
5743 ADD_INT(d, DB_CONSUME_WAIT);
5744 ADD_INT(d, DB_CURRENT);
5745 #if (DBVER >= 33)
5746 ADD_INT(d, DB_FAST_STAT);
5747 #endif
5748 ADD_INT(d, DB_FIRST);
5749 ADD_INT(d, DB_FLUSH);
5750 ADD_INT(d, DB_GET_BOTH);
5751 ADD_INT(d, DB_GET_RECNO);
5752 ADD_INT(d, DB_JOIN_ITEM);
5753 ADD_INT(d, DB_KEYFIRST);
5754 ADD_INT(d, DB_KEYLAST);
5755 ADD_INT(d, DB_LAST);
5756 ADD_INT(d, DB_NEXT);
5757 ADD_INT(d, DB_NEXT_DUP);
5758 ADD_INT(d, DB_NEXT_NODUP);
5759 ADD_INT(d, DB_NODUPDATA);
5760 ADD_INT(d, DB_NOOVERWRITE);
5761 ADD_INT(d, DB_NOSYNC);
5762 ADD_INT(d, DB_POSITION);
5763 ADD_INT(d, DB_PREV);
5764 ADD_INT(d, DB_PREV_NODUP);
5765 #if (DBVER < 45)
5766 ADD_INT(d, DB_RECORDCOUNT);
5767 #endif
5768 ADD_INT(d, DB_SET);
5769 ADD_INT(d, DB_SET_RANGE);
5770 ADD_INT(d, DB_SET_RECNO);
5771 ADD_INT(d, DB_WRITECURSOR);
5773 ADD_INT(d, DB_OPFLAGS_MASK);
5774 ADD_INT(d, DB_RMW);
5775 #if (DBVER >= 33)
5776 ADD_INT(d, DB_DIRTY_READ);
5777 ADD_INT(d, DB_MULTIPLE);
5778 ADD_INT(d, DB_MULTIPLE_KEY);
5779 #endif
5781 #if (DBVER >= 44)
5782 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5783 ADD_INT(d, DB_READ_COMMITTED);
5784 #endif
5786 #if (DBVER >= 33)
5787 ADD_INT(d, DB_DONOTINDEX);
5788 #endif
5790 #if (DBVER >= 41)
5791 _addIntToDict(d, "DB_INCOMPLETE", 0);
5792 #else
5793 ADD_INT(d, DB_INCOMPLETE);
5794 #endif
5795 ADD_INT(d, DB_KEYEMPTY);
5796 ADD_INT(d, DB_KEYEXIST);
5797 ADD_INT(d, DB_LOCK_DEADLOCK);
5798 ADD_INT(d, DB_LOCK_NOTGRANTED);
5799 ADD_INT(d, DB_NOSERVER);
5800 ADD_INT(d, DB_NOSERVER_HOME);
5801 ADD_INT(d, DB_NOSERVER_ID);
5802 ADD_INT(d, DB_NOTFOUND);
5803 ADD_INT(d, DB_OLD_VERSION);
5804 ADD_INT(d, DB_RUNRECOVERY);
5805 ADD_INT(d, DB_VERIFY_BAD);
5806 #if (DBVER >= 33)
5807 ADD_INT(d, DB_PAGE_NOTFOUND);
5808 ADD_INT(d, DB_SECONDARY_BAD);
5809 #endif
5810 #if (DBVER >= 40)
5811 ADD_INT(d, DB_STAT_CLEAR);
5812 ADD_INT(d, DB_REGION_INIT);
5813 ADD_INT(d, DB_NOLOCKING);
5814 ADD_INT(d, DB_YIELDCPU);
5815 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5816 ADD_INT(d, DB_NOPANIC);
5817 #endif
5819 #ifdef DB_REGISTER
5820 ADD_INT(d, DB_REGISTER);
5821 #endif
5823 #if (DBVER >= 42)
5824 ADD_INT(d, DB_TIME_NOTGRANTED);
5825 ADD_INT(d, DB_TXN_NOT_DURABLE);
5826 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5827 ADD_INT(d, DB_LOG_AUTOREMOVE);
5828 ADD_INT(d, DB_DIRECT_LOG);
5829 ADD_INT(d, DB_DIRECT_DB);
5830 ADD_INT(d, DB_INIT_REP);
5831 ADD_INT(d, DB_ENCRYPT);
5832 ADD_INT(d, DB_CHKSUM);
5833 #endif
5835 #if (DBVER >= 43)
5836 ADD_INT(d, DB_LOG_INMEMORY);
5837 ADD_INT(d, DB_BUFFER_SMALL);
5838 ADD_INT(d, DB_SEQ_DEC);
5839 ADD_INT(d, DB_SEQ_INC);
5840 ADD_INT(d, DB_SEQ_WRAP);
5841 #endif
5843 #if (DBVER >= 41)
5844 ADD_INT(d, DB_ENCRYPT_AES);
5845 ADD_INT(d, DB_AUTO_COMMIT);
5846 #else
5847 /* allow berkeleydb 4.1 aware apps to run on older versions */
5848 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5849 #endif
5851 ADD_INT(d, EINVAL);
5852 ADD_INT(d, EACCES);
5853 ADD_INT(d, ENOSPC);
5854 ADD_INT(d, ENOMEM);
5855 ADD_INT(d, EAGAIN);
5856 ADD_INT(d, EBUSY);
5857 ADD_INT(d, EEXIST);
5858 ADD_INT(d, ENOENT);
5859 ADD_INT(d, EPERM);
5861 #if (DBVER >= 40)
5862 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5863 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5864 #endif
5866 /* The exception name must be correct for pickled exception *
5867 * objects to unpickle properly. */
5868 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5869 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5870 #else
5871 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5872 #endif
5874 /* All the rest of the exceptions derive only from DBError */
5875 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5876 PyDict_SetItemString(d, #name, name)
5878 /* The base exception class is DBError */
5879 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5880 MAKE_EX(DBError);
5882 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5883 * from both DBError and KeyError, since the API only supports
5884 * using one base class. */
5885 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5886 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5887 "class DBKeyEmptyError(DBError, KeyError): pass",
5888 Py_file_input, d, d);
5889 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5890 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5891 PyDict_DelItemString(d, "KeyError");
5894 #if !INCOMPLETE_IS_WARNING
5895 MAKE_EX(DBIncompleteError);
5896 #endif
5897 MAKE_EX(DBCursorClosedError);
5898 MAKE_EX(DBKeyEmptyError);
5899 MAKE_EX(DBKeyExistError);
5900 MAKE_EX(DBLockDeadlockError);
5901 MAKE_EX(DBLockNotGrantedError);
5902 MAKE_EX(DBOldVersionError);
5903 MAKE_EX(DBRunRecoveryError);
5904 MAKE_EX(DBVerifyBadError);
5905 MAKE_EX(DBNoServerError);
5906 MAKE_EX(DBNoServerHomeError);
5907 MAKE_EX(DBNoServerIDError);
5908 #if (DBVER >= 33)
5909 MAKE_EX(DBPageNotFoundError);
5910 MAKE_EX(DBSecondaryBadError);
5911 #endif
5913 MAKE_EX(DBInvalidArgError);
5914 MAKE_EX(DBAccessError);
5915 MAKE_EX(DBNoSpaceError);
5916 MAKE_EX(DBNoMemoryError);
5917 MAKE_EX(DBAgainError);
5918 MAKE_EX(DBBusyError);
5919 MAKE_EX(DBFileExistsError);
5920 MAKE_EX(DBNoSuchFileError);
5921 MAKE_EX(DBPermissionsError);
5923 #undef MAKE_EX
5925 /* Initiliase the C API structure and add it to the module */
5926 bsddb_api.db_type = &DB_Type;
5927 bsddb_api.dbcursor_type = &DBCursor_Type;
5928 bsddb_api.dbenv_type = &DBEnv_Type;
5929 bsddb_api.dbtxn_type = &DBTxn_Type;
5930 bsddb_api.dblock_type = &DBLock_Type;
5931 #if (DBVER >= 43)
5932 bsddb_api.dbsequence_type = &DBSequence_Type;
5933 #endif
5934 bsddb_api.makeDBError = makeDBError;
5936 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5937 PyDict_SetItemString(d, "api", py_api);
5938 Py_DECREF(py_api);
5940 /* Check for errors */
5941 if (PyErr_Occurred()) {
5942 PyErr_Print();
5943 Py_FatalError("can't initialize module _bsddb");
5947 /* allow this module to be named _pybsddb so that it can be installed
5948 * and imported on top of python >= 2.3 that includes its own older
5949 * copy of the library named _bsddb without importing the old version. */
5950 DL_EXPORT(void) init_pybsddb(void)
5952 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5953 init_bsddb();