Added section about adding contextual information to log output.
[python.git] / Modules / _bsddb.c
blobf40743493c3723ec1065e812df68df9b3612f6f6
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 MYDB_BEGIN_ALLOW_THREADS;
828 /* If the underlying database has been closed, we don't
829 need to do anything. If the environment has been closed
830 we need to leak, as BerkeleyDB will crash trying to access
831 the environment. There was an exception when the
832 user closed the environment even though there still was
833 a database open. */
834 if (self->mydb->db && self->mydb->myenvobj &&
835 !self->mydb->myenvobj->closed)
836 err = self->dbc->c_close(self->dbc);
837 self->dbc = NULL;
838 MYDB_END_ALLOW_THREADS;
840 Py_XDECREF( self->mydb );
841 PyObject_Del(self);
845 static DBEnvObject*
846 newDBEnvObject(int flags)
848 int err;
849 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
850 if (self == NULL)
851 return NULL;
853 self->closed = 1;
854 self->flags = flags;
855 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
856 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
857 self->in_weakreflist = NULL;
859 MYDB_BEGIN_ALLOW_THREADS;
860 err = db_env_create(&self->db_env, flags);
861 MYDB_END_ALLOW_THREADS;
862 if (makeDBError(err)) {
863 PyObject_Del(self);
864 self = NULL;
866 else {
867 self->db_env->set_errcall(self->db_env, _db_errorCallback);
869 return self;
873 static void
874 DBEnv_dealloc(DBEnvObject* self)
876 if (self->in_weakreflist != NULL) {
877 PyObject_ClearWeakRefs((PyObject *) self);
880 if (self->db_env && !self->closed) {
881 MYDB_BEGIN_ALLOW_THREADS;
882 self->db_env->close(self->db_env, 0);
883 MYDB_END_ALLOW_THREADS;
885 PyObject_Del(self);
889 static DBTxnObject*
890 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
892 int err;
893 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
894 if (self == NULL)
895 return NULL;
896 Py_INCREF(myenv);
897 self->env = (PyObject*)myenv;
898 self->in_weakreflist = NULL;
900 MYDB_BEGIN_ALLOW_THREADS;
901 #if (DBVER >= 40)
902 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
903 #else
904 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
905 #endif
906 MYDB_END_ALLOW_THREADS;
907 if (makeDBError(err)) {
908 Py_DECREF(self->env);
909 PyObject_Del(self);
910 self = NULL;
912 return self;
916 static void
917 DBTxn_dealloc(DBTxnObject* self)
919 if (self->in_weakreflist != NULL) {
920 PyObject_ClearWeakRefs((PyObject *) self);
923 if (self->txn) {
924 /* it hasn't been finalized, abort it! */
925 MYDB_BEGIN_ALLOW_THREADS;
926 #if (DBVER >= 40)
927 self->txn->abort(self->txn);
928 #else
929 txn_abort(self->txn);
930 #endif
931 MYDB_END_ALLOW_THREADS;
932 PyErr_Warn(PyExc_RuntimeWarning,
933 "DBTxn aborted in destructor. No prior commit() or abort().");
936 Py_DECREF(self->env);
937 PyObject_Del(self);
941 static DBLockObject*
942 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
943 db_lockmode_t lock_mode, int flags)
945 int err;
946 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
947 if (self == NULL)
948 return NULL;
949 self->in_weakreflist = NULL;
951 MYDB_BEGIN_ALLOW_THREADS;
952 #if (DBVER >= 40)
953 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
954 &self->lock);
955 #else
956 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
957 #endif
958 MYDB_END_ALLOW_THREADS;
959 if (makeDBError(err)) {
960 PyObject_Del(self);
961 self = NULL;
964 return self;
968 static void
969 DBLock_dealloc(DBLockObject* self)
971 if (self->in_weakreflist != NULL) {
972 PyObject_ClearWeakRefs((PyObject *) self);
974 /* TODO: is this lock held? should we release it? */
976 PyObject_Del(self);
980 #if (DBVER >= 43)
981 static DBSequenceObject*
982 newDBSequenceObject(DBObject* mydb, int flags)
984 int err;
985 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
986 if (self == NULL)
987 return NULL;
988 Py_INCREF(mydb);
989 self->mydb = mydb;
990 self->in_weakreflist = NULL;
993 MYDB_BEGIN_ALLOW_THREADS;
994 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
995 MYDB_END_ALLOW_THREADS;
996 if (makeDBError(err)) {
997 Py_DECREF(self->mydb);
998 PyObject_Del(self);
999 self = NULL;
1002 return self;
1006 static void
1007 DBSequence_dealloc(DBSequenceObject* self)
1009 if (self->in_weakreflist != NULL) {
1010 PyObject_ClearWeakRefs((PyObject *) self);
1013 Py_DECREF(self->mydb);
1014 PyObject_Del(self);
1016 #endif
1018 /* --------------------------------------------------------------------- */
1019 /* DB methods */
1021 static PyObject*
1022 DB_append(DBObject* self, PyObject* args)
1024 PyObject* txnobj = NULL;
1025 PyObject* dataobj;
1026 db_recno_t recno;
1027 DBT key, data;
1028 DB_TXN *txn = NULL;
1030 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1031 return NULL;
1033 CHECK_DB_NOT_CLOSED(self);
1035 /* make a dummy key out of a recno */
1036 recno = 0;
1037 CLEAR_DBT(key);
1038 key.data = &recno;
1039 key.size = sizeof(recno);
1040 key.ulen = key.size;
1041 key.flags = DB_DBT_USERMEM;
1043 if (!make_dbt(dataobj, &data)) return NULL;
1044 if (!checkTxnObj(txnobj, &txn)) return NULL;
1046 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1047 return NULL;
1049 return PyInt_FromLong(recno);
1053 #if (DBVER >= 33)
1055 static int
1056 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1057 DBT* secKey)
1059 int retval = DB_DONOTINDEX;
1060 DBObject* secondaryDB = (DBObject*)db->app_private;
1061 PyObject* callback = secondaryDB->associateCallback;
1062 int type = secondaryDB->primaryDBType;
1063 PyObject* args;
1064 PyObject* result = NULL;
1067 if (callback != NULL) {
1068 MYDB_BEGIN_BLOCK_THREADS;
1070 if (type == DB_RECNO || type == DB_QUEUE)
1071 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1072 priData->data, priData->size);
1073 else
1074 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1075 priData->data, priData->size);
1076 if (args != NULL) {
1077 result = PyEval_CallObject(callback, args);
1079 if (args == NULL || result == NULL) {
1080 PyErr_Print();
1082 else if (result == Py_None) {
1083 retval = DB_DONOTINDEX;
1085 else if (PyInt_Check(result)) {
1086 retval = PyInt_AsLong(result);
1088 else if (PyString_Check(result)) {
1089 char* data;
1090 Py_ssize_t size;
1092 CLEAR_DBT(*secKey);
1093 PyString_AsStringAndSize(result, &data, &size);
1094 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1095 secKey->data = malloc(size); /* TODO, check this */
1096 if (secKey->data) {
1097 memcpy(secKey->data, data, size);
1098 secKey->size = size;
1099 retval = 0;
1101 else {
1102 PyErr_SetString(PyExc_MemoryError,
1103 "malloc failed in _db_associateCallback");
1104 PyErr_Print();
1107 else {
1108 PyErr_SetString(
1109 PyExc_TypeError,
1110 "DB associate callback should return DB_DONOTINDEX or string.");
1111 PyErr_Print();
1114 Py_XDECREF(args);
1115 Py_XDECREF(result);
1117 MYDB_END_BLOCK_THREADS;
1119 return retval;
1123 static PyObject*
1124 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1126 int err, flags=0;
1127 DBObject* secondaryDB;
1128 PyObject* callback;
1129 #if (DBVER >= 41)
1130 PyObject *txnobj = NULL;
1131 DB_TXN *txn = NULL;
1132 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1133 NULL};
1134 #else
1135 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1136 #endif
1138 #if (DBVER >= 41)
1139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1140 &secondaryDB, &callback, &flags,
1141 &txnobj)) {
1142 #else
1143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1144 &secondaryDB, &callback, &flags)) {
1145 #endif
1146 return NULL;
1149 #if (DBVER >= 41)
1150 if (!checkTxnObj(txnobj, &txn)) return NULL;
1151 #endif
1153 CHECK_DB_NOT_CLOSED(self);
1154 if (!DBObject_Check(secondaryDB)) {
1155 makeTypeError("DB", (PyObject*)secondaryDB);
1156 return NULL;
1158 CHECK_DB_NOT_CLOSED(secondaryDB);
1159 if (callback == Py_None) {
1160 callback = NULL;
1162 else if (!PyCallable_Check(callback)) {
1163 makeTypeError("Callable", callback);
1164 return NULL;
1167 /* Save a reference to the callback in the secondary DB. */
1168 Py_XDECREF(secondaryDB->associateCallback);
1169 Py_XINCREF(callback);
1170 secondaryDB->associateCallback = callback;
1171 secondaryDB->primaryDBType = _DB_get_type(self);
1173 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1174 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1175 * The global interepreter lock is not initialized until the first
1176 * thread is created using thread.start_new_thread() or fork() is
1177 * called. that would cause the ALLOW_THREADS here to segfault due
1178 * to a null pointer reference if no threads or child processes
1179 * have been created. This works around that and is a no-op if
1180 * threads have already been initialized.
1181 * (see pybsddb-users mailing list post on 2002-08-07)
1183 #ifdef WITH_THREAD
1184 PyEval_InitThreads();
1185 #endif
1186 MYDB_BEGIN_ALLOW_THREADS;
1187 #if (DBVER >= 41)
1188 err = self->db->associate(self->db,
1189 txn,
1190 secondaryDB->db,
1191 _db_associateCallback,
1192 flags);
1193 #else
1194 err = self->db->associate(self->db,
1195 secondaryDB->db,
1196 _db_associateCallback,
1197 flags);
1198 #endif
1199 MYDB_END_ALLOW_THREADS;
1201 if (err) {
1202 Py_XDECREF(secondaryDB->associateCallback);
1203 secondaryDB->associateCallback = NULL;
1204 secondaryDB->primaryDBType = 0;
1207 RETURN_IF_ERR();
1208 RETURN_NONE();
1212 #endif
1215 static PyObject*
1216 DB_close(DBObject* self, PyObject* args)
1218 int err, flags=0;
1219 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1220 return NULL;
1221 if (self->db != NULL) {
1222 if (self->myenvobj)
1223 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1224 err = self->db->close(self->db, flags);
1225 self->db = NULL;
1226 RETURN_IF_ERR();
1228 RETURN_NONE();
1232 static PyObject*
1233 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1235 int err, flags=0, type;
1236 PyObject* txnobj = NULL;
1237 PyObject* retval = NULL;
1238 DBT key, data;
1239 DB_TXN *txn = NULL;
1240 static char* kwnames[] = { "txn", "flags", NULL };
1242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1243 &txnobj, &flags))
1244 return NULL;
1246 CHECK_DB_NOT_CLOSED(self);
1247 type = _DB_get_type(self);
1248 if (type == -1)
1249 return NULL;
1250 if (type != DB_QUEUE) {
1251 PyErr_SetString(PyExc_TypeError,
1252 "Consume methods only allowed for Queue DB's");
1253 return NULL;
1255 if (!checkTxnObj(txnobj, &txn))
1256 return NULL;
1258 CLEAR_DBT(key);
1259 CLEAR_DBT(data);
1260 if (CHECK_DBFLAG(self, DB_THREAD)) {
1261 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1262 data.flags = DB_DBT_MALLOC;
1263 key.flags = DB_DBT_MALLOC;
1266 MYDB_BEGIN_ALLOW_THREADS;
1267 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1268 MYDB_END_ALLOW_THREADS;
1270 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1271 && self->moduleFlags.getReturnsNone) {
1272 err = 0;
1273 Py_INCREF(Py_None);
1274 retval = Py_None;
1276 else if (!err) {
1277 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1278 data.size);
1279 FREE_DBT(key);
1280 FREE_DBT(data);
1283 RETURN_IF_ERR();
1284 return retval;
1287 static PyObject*
1288 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1290 return _DB_consume(self, args, kwargs, DB_CONSUME);
1293 static PyObject*
1294 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1295 int consume_flag)
1297 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1301 static PyObject*
1302 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1304 int err, flags=0;
1305 DBC* dbc;
1306 PyObject* txnobj = NULL;
1307 DB_TXN *txn = NULL;
1308 static char* kwnames[] = { "txn", "flags", NULL };
1310 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1311 &txnobj, &flags))
1312 return NULL;
1313 CHECK_DB_NOT_CLOSED(self);
1314 if (!checkTxnObj(txnobj, &txn))
1315 return NULL;
1317 MYDB_BEGIN_ALLOW_THREADS;
1318 err = self->db->cursor(self->db, txn, &dbc, flags);
1319 MYDB_END_ALLOW_THREADS;
1320 RETURN_IF_ERR();
1321 return (PyObject*) newDBCursorObject(dbc, self);
1325 static PyObject*
1326 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1328 PyObject* txnobj = NULL;
1329 int flags = 0;
1330 PyObject* keyobj;
1331 DBT key;
1332 DB_TXN *txn = NULL;
1333 static char* kwnames[] = { "key", "txn", "flags", NULL };
1335 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1336 &keyobj, &txnobj, &flags))
1337 return NULL;
1338 CHECK_DB_NOT_CLOSED(self);
1339 if (!make_key_dbt(self, keyobj, &key, NULL))
1340 return NULL;
1341 if (!checkTxnObj(txnobj, &txn)) {
1342 FREE_DBT(key);
1343 return NULL;
1346 if (-1 == _DB_delete(self, txn, &key, 0)) {
1347 FREE_DBT(key);
1348 return NULL;
1351 FREE_DBT(key);
1352 RETURN_NONE();
1356 static PyObject*
1357 DB_fd(DBObject* self, PyObject* args)
1359 int err, the_fd;
1361 if (!PyArg_ParseTuple(args,":fd"))
1362 return NULL;
1363 CHECK_DB_NOT_CLOSED(self);
1365 MYDB_BEGIN_ALLOW_THREADS;
1366 err = self->db->fd(self->db, &the_fd);
1367 MYDB_END_ALLOW_THREADS;
1368 RETURN_IF_ERR();
1369 return PyInt_FromLong(the_fd);
1373 static PyObject*
1374 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1376 int err, flags=0;
1377 PyObject* txnobj = NULL;
1378 PyObject* keyobj;
1379 PyObject* dfltobj = NULL;
1380 PyObject* retval = NULL;
1381 int dlen = -1;
1382 int doff = -1;
1383 DBT key, data;
1384 DB_TXN *txn = NULL;
1385 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1386 "doff", NULL};
1388 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1389 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1390 &doff))
1391 return NULL;
1393 CHECK_DB_NOT_CLOSED(self);
1394 if (!make_key_dbt(self, keyobj, &key, &flags))
1395 return NULL;
1396 if (!checkTxnObj(txnobj, &txn)) {
1397 FREE_DBT(key);
1398 return NULL;
1401 CLEAR_DBT(data);
1402 if (CHECK_DBFLAG(self, DB_THREAD)) {
1403 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1404 data.flags = DB_DBT_MALLOC;
1406 if (!add_partial_dbt(&data, dlen, doff)) {
1407 FREE_DBT(key);
1408 return NULL;
1411 MYDB_BEGIN_ALLOW_THREADS;
1412 err = self->db->get(self->db, txn, &key, &data, flags);
1413 MYDB_END_ALLOW_THREADS;
1415 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1416 err = 0;
1417 Py_INCREF(dfltobj);
1418 retval = dfltobj;
1420 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1421 && self->moduleFlags.getReturnsNone) {
1422 err = 0;
1423 Py_INCREF(Py_None);
1424 retval = Py_None;
1426 else if (!err) {
1427 if (flags & DB_SET_RECNO) /* return both key and data */
1428 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1429 data.size);
1430 else /* return just the data */
1431 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1432 FREE_DBT(data);
1434 FREE_DBT(key);
1436 RETURN_IF_ERR();
1437 return retval;
1440 #if (DBVER >= 33)
1441 static PyObject*
1442 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1444 int err, flags=0;
1445 PyObject* txnobj = NULL;
1446 PyObject* keyobj;
1447 PyObject* dfltobj = NULL;
1448 PyObject* retval = NULL;
1449 int dlen = -1;
1450 int doff = -1;
1451 DBT key, pkey, data;
1452 DB_TXN *txn = NULL;
1453 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1454 "doff", NULL};
1456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1457 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1458 &doff))
1459 return NULL;
1461 CHECK_DB_NOT_CLOSED(self);
1462 if (!make_key_dbt(self, keyobj, &key, &flags))
1463 return NULL;
1464 if (!checkTxnObj(txnobj, &txn)) {
1465 FREE_DBT(key);
1466 return NULL;
1469 CLEAR_DBT(data);
1470 if (CHECK_DBFLAG(self, DB_THREAD)) {
1471 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1472 data.flags = DB_DBT_MALLOC;
1474 if (!add_partial_dbt(&data, dlen, doff)) {
1475 FREE_DBT(key);
1476 return NULL;
1479 CLEAR_DBT(pkey);
1480 pkey.flags = DB_DBT_MALLOC;
1482 MYDB_BEGIN_ALLOW_THREADS;
1483 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1484 MYDB_END_ALLOW_THREADS;
1486 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1487 err = 0;
1488 Py_INCREF(dfltobj);
1489 retval = dfltobj;
1491 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1492 && self->moduleFlags.getReturnsNone) {
1493 err = 0;
1494 Py_INCREF(Py_None);
1495 retval = Py_None;
1497 else if (!err) {
1498 PyObject *pkeyObj;
1499 PyObject *dataObj;
1500 dataObj = PyString_FromStringAndSize(data.data, data.size);
1502 if (self->primaryDBType == DB_RECNO ||
1503 self->primaryDBType == DB_QUEUE)
1504 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1505 else
1506 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1508 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1510 PyObject *keyObj;
1511 int type = _DB_get_type(self);
1512 if (type == DB_RECNO || type == DB_QUEUE)
1513 keyObj = PyInt_FromLong(*(int *)key.data);
1514 else
1515 keyObj = PyString_FromStringAndSize(key.data, key.size);
1516 #if (PY_VERSION_HEX >= 0x02040000)
1517 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1518 #else
1519 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1520 #endif
1521 Py_DECREF(keyObj);
1523 else /* return just the pkey and data */
1525 #if (PY_VERSION_HEX >= 0x02040000)
1526 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1527 #else
1528 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1529 #endif
1531 Py_DECREF(dataObj);
1532 Py_DECREF(pkeyObj);
1533 FREE_DBT(pkey);
1534 FREE_DBT(data);
1536 FREE_DBT(key);
1538 RETURN_IF_ERR();
1539 return retval;
1541 #endif
1544 /* Return size of entry */
1545 static PyObject*
1546 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1548 int err, flags=0;
1549 PyObject* txnobj = NULL;
1550 PyObject* keyobj;
1551 PyObject* retval = NULL;
1552 DBT key, data;
1553 DB_TXN *txn = NULL;
1554 static char* kwnames[] = { "key", "txn", NULL };
1556 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1557 &keyobj, &txnobj))
1558 return NULL;
1559 CHECK_DB_NOT_CLOSED(self);
1560 if (!make_key_dbt(self, keyobj, &key, &flags))
1561 return NULL;
1562 if (!checkTxnObj(txnobj, &txn)) {
1563 FREE_DBT(key);
1564 return NULL;
1566 CLEAR_DBT(data);
1568 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1569 thus getting the record size. */
1570 data.flags = DB_DBT_USERMEM;
1571 data.ulen = 0;
1572 MYDB_BEGIN_ALLOW_THREADS;
1573 err = self->db->get(self->db, txn, &key, &data, flags);
1574 MYDB_END_ALLOW_THREADS;
1575 if (err == DB_BUFFER_SMALL) {
1576 retval = PyInt_FromLong((long)data.size);
1577 err = 0;
1580 FREE_DBT(key);
1581 FREE_DBT(data);
1582 RETURN_IF_ERR();
1583 return retval;
1587 static PyObject*
1588 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1590 int err, flags=0;
1591 PyObject* txnobj = NULL;
1592 PyObject* keyobj;
1593 PyObject* dataobj;
1594 PyObject* retval = NULL;
1595 DBT key, data;
1596 void *orig_data;
1597 DB_TXN *txn = NULL;
1598 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1601 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1602 &keyobj, &dataobj, &txnobj, &flags))
1603 return NULL;
1605 CHECK_DB_NOT_CLOSED(self);
1606 if (!make_key_dbt(self, keyobj, &key, NULL))
1607 return NULL;
1608 if ( !make_dbt(dataobj, &data) ||
1609 !checkTxnObj(txnobj, &txn) )
1611 FREE_DBT(key);
1612 return NULL;
1615 flags |= DB_GET_BOTH;
1616 orig_data = data.data;
1618 if (CHECK_DBFLAG(self, DB_THREAD)) {
1619 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1620 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1621 data.flags = DB_DBT_MALLOC;
1624 MYDB_BEGIN_ALLOW_THREADS;
1625 err = self->db->get(self->db, txn, &key, &data, flags);
1626 MYDB_END_ALLOW_THREADS;
1628 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1629 && self->moduleFlags.getReturnsNone) {
1630 err = 0;
1631 Py_INCREF(Py_None);
1632 retval = Py_None;
1634 else if (!err) {
1635 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1636 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1638 /* Even though the flags require DB_DBT_MALLOC, data is not always
1639 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1640 if (data.data != orig_data)
1641 FREE_DBT(data);
1644 FREE_DBT(key);
1645 RETURN_IF_ERR();
1646 return retval;
1650 static PyObject*
1651 DB_get_byteswapped(DBObject* self, PyObject* args)
1653 #if (DBVER >= 33)
1654 int err = 0;
1655 #endif
1656 int retval = -1;
1658 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1659 return NULL;
1660 CHECK_DB_NOT_CLOSED(self);
1662 #if (DBVER >= 33)
1663 MYDB_BEGIN_ALLOW_THREADS;
1664 err = self->db->get_byteswapped(self->db, &retval);
1665 MYDB_END_ALLOW_THREADS;
1666 RETURN_IF_ERR();
1667 #else
1668 MYDB_BEGIN_ALLOW_THREADS;
1669 retval = self->db->get_byteswapped(self->db);
1670 MYDB_END_ALLOW_THREADS;
1671 #endif
1672 return PyInt_FromLong(retval);
1676 static PyObject*
1677 DB_get_type(DBObject* self, PyObject* args)
1679 int type;
1681 if (!PyArg_ParseTuple(args,":get_type"))
1682 return NULL;
1683 CHECK_DB_NOT_CLOSED(self);
1685 type = _DB_get_type(self);
1686 if (type == -1)
1687 return NULL;
1688 return PyInt_FromLong(type);
1692 static PyObject*
1693 DB_join(DBObject* self, PyObject* args)
1695 int err, flags=0;
1696 int length, x;
1697 PyObject* cursorsObj;
1698 DBC** cursors;
1699 DBC* dbc;
1701 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1702 return NULL;
1704 CHECK_DB_NOT_CLOSED(self);
1706 if (!PySequence_Check(cursorsObj)) {
1707 PyErr_SetString(PyExc_TypeError,
1708 "Sequence of DBCursor objects expected");
1709 return NULL;
1712 length = PyObject_Length(cursorsObj);
1713 cursors = malloc((length+1) * sizeof(DBC*));
1714 if (!cursors) {
1715 PyErr_NoMemory();
1716 return NULL;
1719 cursors[length] = NULL;
1720 for (x=0; x<length; x++) {
1721 PyObject* item = PySequence_GetItem(cursorsObj, x);
1722 if (item == NULL) {
1723 free(cursors);
1724 return NULL;
1726 if (!DBCursorObject_Check(item)) {
1727 PyErr_SetString(PyExc_TypeError,
1728 "Sequence of DBCursor objects expected");
1729 free(cursors);
1730 return NULL;
1732 cursors[x] = ((DBCursorObject*)item)->dbc;
1733 Py_DECREF(item);
1736 MYDB_BEGIN_ALLOW_THREADS;
1737 err = self->db->join(self->db, cursors, &dbc, flags);
1738 MYDB_END_ALLOW_THREADS;
1739 free(cursors);
1740 RETURN_IF_ERR();
1742 /* FIXME: this is a buggy interface. The returned cursor
1743 contains internal references to the passed in cursors
1744 but does not hold python references to them or prevent
1745 them from being closed prematurely. This can cause
1746 python to crash when things are done in the wrong order. */
1747 return (PyObject*) newDBCursorObject(dbc, self);
1751 static PyObject*
1752 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1754 int err, flags=0;
1755 PyObject* txnobj = NULL;
1756 PyObject* keyobj;
1757 DBT key;
1758 DB_TXN *txn = NULL;
1759 DB_KEY_RANGE range;
1760 static char* kwnames[] = { "key", "txn", "flags", NULL };
1762 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1763 &keyobj, &txnobj, &flags))
1764 return NULL;
1765 CHECK_DB_NOT_CLOSED(self);
1766 if (!make_dbt(keyobj, &key))
1767 /* BTree only, don't need to allow for an int key */
1768 return NULL;
1769 if (!checkTxnObj(txnobj, &txn))
1770 return NULL;
1772 MYDB_BEGIN_ALLOW_THREADS;
1773 err = self->db->key_range(self->db, txn, &key, &range, flags);
1774 MYDB_END_ALLOW_THREADS;
1776 RETURN_IF_ERR();
1777 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1781 static PyObject*
1782 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1784 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1785 char* filename = NULL;
1786 char* dbname = NULL;
1787 #if (DBVER >= 41)
1788 PyObject *txnobj = NULL;
1789 DB_TXN *txn = NULL;
1790 /* with dbname */
1791 static char* kwnames[] = {
1792 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1793 /* without dbname */
1794 static char* kwnames_basic[] = {
1795 "filename", "dbtype", "flags", "mode", "txn", NULL};
1796 #else
1797 /* with dbname */
1798 static char* kwnames[] = {
1799 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1800 /* without dbname */
1801 static char* kwnames_basic[] = {
1802 "filename", "dbtype", "flags", "mode", NULL};
1803 #endif
1805 #if (DBVER >= 41)
1806 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1807 &filename, &dbname, &type, &flags, &mode,
1808 &txnobj))
1809 #else
1810 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1811 &filename, &dbname, &type, &flags,
1812 &mode))
1813 #endif
1815 PyErr_Clear();
1816 type = DB_UNKNOWN; flags = 0; mode = 0660;
1817 filename = NULL; dbname = NULL;
1818 #if (DBVER >= 41)
1819 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1820 kwnames_basic,
1821 &filename, &type, &flags, &mode,
1822 &txnobj))
1823 return NULL;
1824 #else
1825 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1826 kwnames_basic,
1827 &filename, &type, &flags, &mode))
1828 return NULL;
1829 #endif
1832 #if (DBVER >= 41)
1833 if (!checkTxnObj(txnobj, &txn)) return NULL;
1834 #endif
1836 if (NULL == self->db) {
1837 PyObject *t = Py_BuildValue("(is)", 0,
1838 "Cannot call open() twice for DB object");
1839 PyErr_SetObject(DBError, t);
1840 Py_DECREF(t);
1841 return NULL;
1844 MYDB_BEGIN_ALLOW_THREADS;
1845 #if (DBVER >= 41)
1846 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1847 #else
1848 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1849 #endif
1850 MYDB_END_ALLOW_THREADS;
1851 if (makeDBError(err)) {
1852 self->db->close(self->db, 0);
1853 self->db = NULL;
1854 return NULL;
1857 #if (DBVER >= 42)
1858 self->db->get_flags(self->db, &self->setflags);
1859 #endif
1861 self->flags = flags;
1862 RETURN_NONE();
1866 static PyObject*
1867 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1869 int flags=0;
1870 PyObject* txnobj = NULL;
1871 int dlen = -1;
1872 int doff = -1;
1873 PyObject* keyobj, *dataobj, *retval;
1874 DBT key, data;
1875 DB_TXN *txn = NULL;
1876 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1877 "doff", NULL };
1879 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1880 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1881 return NULL;
1883 CHECK_DB_NOT_CLOSED(self);
1884 if (!make_key_dbt(self, keyobj, &key, NULL))
1885 return NULL;
1886 if ( !make_dbt(dataobj, &data) ||
1887 !add_partial_dbt(&data, dlen, doff) ||
1888 !checkTxnObj(txnobj, &txn) )
1890 FREE_DBT(key);
1891 return NULL;
1894 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1895 FREE_DBT(key);
1896 return NULL;
1899 if (flags & DB_APPEND)
1900 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1901 else {
1902 retval = Py_None;
1903 Py_INCREF(retval);
1905 FREE_DBT(key);
1906 return retval;
1911 static PyObject*
1912 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1914 char* filename;
1915 char* database = NULL;
1916 int err, flags=0;
1917 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
1919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1920 &filename, &database, &flags))
1921 return NULL;
1922 CHECK_DB_NOT_CLOSED(self);
1924 err = self->db->remove(self->db, filename, database, flags);
1925 self->db = NULL;
1926 RETURN_IF_ERR();
1927 RETURN_NONE();
1932 static PyObject*
1933 DB_rename(DBObject* self, PyObject* args)
1935 char* filename;
1936 char* database;
1937 char* newname;
1938 int err, flags=0;
1940 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1941 &flags))
1942 return NULL;
1943 CHECK_DB_NOT_CLOSED(self);
1945 MYDB_BEGIN_ALLOW_THREADS;
1946 err = self->db->rename(self->db, filename, database, newname, flags);
1947 MYDB_END_ALLOW_THREADS;
1948 RETURN_IF_ERR();
1949 RETURN_NONE();
1953 static PyObject*
1954 DB_set_bt_minkey(DBObject* self, PyObject* args)
1956 int err, minkey;
1958 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1959 return NULL;
1960 CHECK_DB_NOT_CLOSED(self);
1962 MYDB_BEGIN_ALLOW_THREADS;
1963 err = self->db->set_bt_minkey(self->db, minkey);
1964 MYDB_END_ALLOW_THREADS;
1965 RETURN_IF_ERR();
1966 RETURN_NONE();
1969 #if (DBVER >= 33)
1970 static int
1971 _default_cmp(const DBT *leftKey,
1972 const DBT *rightKey)
1974 int res;
1975 int lsize = leftKey->size, rsize = rightKey->size;
1977 res = memcmp(leftKey->data, rightKey->data,
1978 lsize < rsize ? lsize : rsize);
1980 if (res == 0) {
1981 if (lsize < rsize) {
1982 res = -1;
1984 else if (lsize > rsize) {
1985 res = 1;
1988 return res;
1991 static int
1992 _db_compareCallback(DB* db,
1993 const DBT *leftKey,
1994 const DBT *rightKey)
1996 int res = 0;
1997 PyObject *args;
1998 PyObject *result = NULL;
1999 DBObject *self = (DBObject *)db->app_private;
2001 if (self == NULL || self->btCompareCallback == NULL) {
2002 MYDB_BEGIN_BLOCK_THREADS;
2003 PyErr_SetString(PyExc_TypeError,
2004 (self == 0
2005 ? "DB_bt_compare db is NULL."
2006 : "DB_bt_compare callback is NULL."));
2007 /* we're in a callback within the DB code, we can't raise */
2008 PyErr_Print();
2009 res = _default_cmp(leftKey, rightKey);
2010 MYDB_END_BLOCK_THREADS;
2011 } else {
2012 MYDB_BEGIN_BLOCK_THREADS;
2014 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2015 rightKey->data, rightKey->size);
2016 if (args != NULL) {
2017 /* XXX(twouters) I highly doubt this INCREF is correct */
2018 Py_INCREF(self);
2019 result = PyEval_CallObject(self->btCompareCallback, args);
2021 if (args == NULL || result == NULL) {
2022 /* we're in a callback within the DB code, we can't raise */
2023 PyErr_Print();
2024 res = _default_cmp(leftKey, rightKey);
2025 } else if (PyInt_Check(result)) {
2026 res = PyInt_AsLong(result);
2027 } else {
2028 PyErr_SetString(PyExc_TypeError,
2029 "DB_bt_compare callback MUST return an int.");
2030 /* we're in a callback within the DB code, we can't raise */
2031 PyErr_Print();
2032 res = _default_cmp(leftKey, rightKey);
2035 Py_XDECREF(args);
2036 Py_XDECREF(result);
2038 MYDB_END_BLOCK_THREADS;
2040 return res;
2043 static PyObject*
2044 DB_set_bt_compare(DBObject* self, PyObject* args)
2046 int err;
2047 PyObject *comparator;
2048 PyObject *tuple, *result;
2050 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2051 return NULL;
2053 CHECK_DB_NOT_CLOSED(self);
2055 if (!PyCallable_Check(comparator)) {
2056 makeTypeError("Callable", comparator);
2057 return NULL;
2061 * Perform a test call of the comparator function with two empty
2062 * string objects here. verify that it returns an int (0).
2063 * err if not.
2065 tuple = Py_BuildValue("(ss)", "", "");
2066 result = PyEval_CallObject(comparator, tuple);
2067 Py_DECREF(tuple);
2068 if (result == NULL)
2069 return NULL;
2070 if (!PyInt_Check(result)) {
2071 PyErr_SetString(PyExc_TypeError,
2072 "callback MUST return an int");
2073 return NULL;
2074 } else if (PyInt_AsLong(result) != 0) {
2075 PyErr_SetString(PyExc_TypeError,
2076 "callback failed to return 0 on two empty strings");
2077 return NULL;
2079 Py_DECREF(result);
2081 /* We don't accept multiple set_bt_compare operations, in order to
2082 * simplify the code. This would have no real use, as one cannot
2083 * change the function once the db is opened anyway */
2084 if (self->btCompareCallback != NULL) {
2085 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2086 return NULL;
2089 Py_INCREF(comparator);
2090 self->btCompareCallback = comparator;
2092 /* This is to workaround a problem with un-initialized threads (see
2093 comment in DB_associate) */
2094 #ifdef WITH_THREAD
2095 PyEval_InitThreads();
2096 #endif
2098 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2100 if (err) {
2101 /* restore the old state in case of error */
2102 Py_DECREF(comparator);
2103 self->btCompareCallback = NULL;
2106 RETURN_IF_ERR();
2107 RETURN_NONE();
2109 #endif /* DBVER >= 33 */
2112 static PyObject*
2113 DB_set_cachesize(DBObject* self, PyObject* args)
2115 int err;
2116 int gbytes = 0, bytes = 0, ncache = 0;
2118 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2119 &gbytes,&bytes,&ncache))
2120 return NULL;
2121 CHECK_DB_NOT_CLOSED(self);
2123 MYDB_BEGIN_ALLOW_THREADS;
2124 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2125 MYDB_END_ALLOW_THREADS;
2126 RETURN_IF_ERR();
2127 RETURN_NONE();
2131 static PyObject*
2132 DB_set_flags(DBObject* self, PyObject* args)
2134 int err, flags;
2136 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2137 return NULL;
2138 CHECK_DB_NOT_CLOSED(self);
2140 MYDB_BEGIN_ALLOW_THREADS;
2141 err = self->db->set_flags(self->db, flags);
2142 MYDB_END_ALLOW_THREADS;
2143 RETURN_IF_ERR();
2145 self->setflags |= flags;
2146 RETURN_NONE();
2150 static PyObject*
2151 DB_set_h_ffactor(DBObject* self, PyObject* args)
2153 int err, ffactor;
2155 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2156 return NULL;
2157 CHECK_DB_NOT_CLOSED(self);
2159 MYDB_BEGIN_ALLOW_THREADS;
2160 err = self->db->set_h_ffactor(self->db, ffactor);
2161 MYDB_END_ALLOW_THREADS;
2162 RETURN_IF_ERR();
2163 RETURN_NONE();
2167 static PyObject*
2168 DB_set_h_nelem(DBObject* self, PyObject* args)
2170 int err, nelem;
2172 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2173 return NULL;
2174 CHECK_DB_NOT_CLOSED(self);
2176 MYDB_BEGIN_ALLOW_THREADS;
2177 err = self->db->set_h_nelem(self->db, nelem);
2178 MYDB_END_ALLOW_THREADS;
2179 RETURN_IF_ERR();
2180 RETURN_NONE();
2184 static PyObject*
2185 DB_set_lorder(DBObject* self, PyObject* args)
2187 int err, lorder;
2189 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2190 return NULL;
2191 CHECK_DB_NOT_CLOSED(self);
2193 MYDB_BEGIN_ALLOW_THREADS;
2194 err = self->db->set_lorder(self->db, lorder);
2195 MYDB_END_ALLOW_THREADS;
2196 RETURN_IF_ERR();
2197 RETURN_NONE();
2201 static PyObject*
2202 DB_set_pagesize(DBObject* self, PyObject* args)
2204 int err, pagesize;
2206 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2207 return NULL;
2208 CHECK_DB_NOT_CLOSED(self);
2210 MYDB_BEGIN_ALLOW_THREADS;
2211 err = self->db->set_pagesize(self->db, pagesize);
2212 MYDB_END_ALLOW_THREADS;
2213 RETURN_IF_ERR();
2214 RETURN_NONE();
2218 static PyObject*
2219 DB_set_re_delim(DBObject* self, PyObject* args)
2221 int err;
2222 char delim;
2224 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2225 PyErr_Clear();
2226 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2227 return NULL;
2230 CHECK_DB_NOT_CLOSED(self);
2232 MYDB_BEGIN_ALLOW_THREADS;
2233 err = self->db->set_re_delim(self->db, delim);
2234 MYDB_END_ALLOW_THREADS;
2235 RETURN_IF_ERR();
2236 RETURN_NONE();
2239 static PyObject*
2240 DB_set_re_len(DBObject* self, PyObject* args)
2242 int err, len;
2244 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_re_len(self->db, len);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2252 RETURN_NONE();
2256 static PyObject*
2257 DB_set_re_pad(DBObject* self, PyObject* args)
2259 int err;
2260 char pad;
2262 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2263 PyErr_Clear();
2264 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2265 return NULL;
2267 CHECK_DB_NOT_CLOSED(self);
2269 MYDB_BEGIN_ALLOW_THREADS;
2270 err = self->db->set_re_pad(self->db, pad);
2271 MYDB_END_ALLOW_THREADS;
2272 RETURN_IF_ERR();
2273 RETURN_NONE();
2277 static PyObject*
2278 DB_set_re_source(DBObject* self, PyObject* args)
2280 int err;
2281 char *re_source;
2283 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2284 return NULL;
2285 CHECK_DB_NOT_CLOSED(self);
2287 MYDB_BEGIN_ALLOW_THREADS;
2288 err = self->db->set_re_source(self->db, re_source);
2289 MYDB_END_ALLOW_THREADS;
2290 RETURN_IF_ERR();
2291 RETURN_NONE();
2295 static PyObject*
2296 DB_set_q_extentsize(DBObject* self, PyObject* args)
2298 int err;
2299 int extentsize;
2301 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2302 return NULL;
2303 CHECK_DB_NOT_CLOSED(self);
2305 MYDB_BEGIN_ALLOW_THREADS;
2306 err = self->db->set_q_extentsize(self->db, extentsize);
2307 MYDB_END_ALLOW_THREADS;
2308 RETURN_IF_ERR();
2309 RETURN_NONE();
2312 static PyObject*
2313 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2315 int err, flags = 0, type;
2316 void* sp;
2317 PyObject* d;
2318 #if (DBVER >= 43)
2319 PyObject* txnobj = NULL;
2320 DB_TXN *txn = NULL;
2321 static char* kwnames[] = { "flags", "txn", NULL };
2322 #else
2323 static char* kwnames[] = { "flags", NULL };
2324 #endif
2326 #if (DBVER >= 43)
2327 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2328 &flags, &txnobj))
2329 return NULL;
2330 if (!checkTxnObj(txnobj, &txn))
2331 return NULL;
2332 #else
2333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2334 return NULL;
2335 #endif
2336 CHECK_DB_NOT_CLOSED(self);
2338 MYDB_BEGIN_ALLOW_THREADS;
2339 #if (DBVER >= 43)
2340 err = self->db->stat(self->db, txn, &sp, flags);
2341 #elif (DBVER >= 33)
2342 err = self->db->stat(self->db, &sp, flags);
2343 #else
2344 err = self->db->stat(self->db, &sp, NULL, flags);
2345 #endif
2346 MYDB_END_ALLOW_THREADS;
2347 RETURN_IF_ERR();
2349 self->haveStat = 1;
2351 /* Turn the stat structure into a dictionary */
2352 type = _DB_get_type(self);
2353 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2354 free(sp);
2355 return NULL;
2358 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2359 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2360 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2362 switch (type) {
2363 case DB_HASH:
2364 MAKE_HASH_ENTRY(magic);
2365 MAKE_HASH_ENTRY(version);
2366 MAKE_HASH_ENTRY(nkeys);
2367 MAKE_HASH_ENTRY(ndata);
2368 MAKE_HASH_ENTRY(pagesize);
2369 #if (DBVER < 41)
2370 MAKE_HASH_ENTRY(nelem);
2371 #endif
2372 MAKE_HASH_ENTRY(ffactor);
2373 MAKE_HASH_ENTRY(buckets);
2374 MAKE_HASH_ENTRY(free);
2375 MAKE_HASH_ENTRY(bfree);
2376 MAKE_HASH_ENTRY(bigpages);
2377 MAKE_HASH_ENTRY(big_bfree);
2378 MAKE_HASH_ENTRY(overflows);
2379 MAKE_HASH_ENTRY(ovfl_free);
2380 MAKE_HASH_ENTRY(dup);
2381 MAKE_HASH_ENTRY(dup_free);
2382 break;
2384 case DB_BTREE:
2385 case DB_RECNO:
2386 MAKE_BT_ENTRY(magic);
2387 MAKE_BT_ENTRY(version);
2388 MAKE_BT_ENTRY(nkeys);
2389 MAKE_BT_ENTRY(ndata);
2390 MAKE_BT_ENTRY(pagesize);
2391 MAKE_BT_ENTRY(minkey);
2392 MAKE_BT_ENTRY(re_len);
2393 MAKE_BT_ENTRY(re_pad);
2394 MAKE_BT_ENTRY(levels);
2395 MAKE_BT_ENTRY(int_pg);
2396 MAKE_BT_ENTRY(leaf_pg);
2397 MAKE_BT_ENTRY(dup_pg);
2398 MAKE_BT_ENTRY(over_pg);
2399 MAKE_BT_ENTRY(free);
2400 MAKE_BT_ENTRY(int_pgfree);
2401 MAKE_BT_ENTRY(leaf_pgfree);
2402 MAKE_BT_ENTRY(dup_pgfree);
2403 MAKE_BT_ENTRY(over_pgfree);
2404 break;
2406 case DB_QUEUE:
2407 MAKE_QUEUE_ENTRY(magic);
2408 MAKE_QUEUE_ENTRY(version);
2409 MAKE_QUEUE_ENTRY(nkeys);
2410 MAKE_QUEUE_ENTRY(ndata);
2411 MAKE_QUEUE_ENTRY(pagesize);
2412 MAKE_QUEUE_ENTRY(pages);
2413 MAKE_QUEUE_ENTRY(re_len);
2414 MAKE_QUEUE_ENTRY(re_pad);
2415 MAKE_QUEUE_ENTRY(pgfree);
2416 #if (DBVER == 31)
2417 MAKE_QUEUE_ENTRY(start);
2418 #endif
2419 MAKE_QUEUE_ENTRY(first_recno);
2420 MAKE_QUEUE_ENTRY(cur_recno);
2421 break;
2423 default:
2424 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2425 Py_DECREF(d);
2426 d = NULL;
2429 #undef MAKE_HASH_ENTRY
2430 #undef MAKE_BT_ENTRY
2431 #undef MAKE_QUEUE_ENTRY
2433 free(sp);
2434 return d;
2437 static PyObject*
2438 DB_sync(DBObject* self, PyObject* args)
2440 int err;
2441 int flags = 0;
2443 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2444 return NULL;
2445 CHECK_DB_NOT_CLOSED(self);
2447 MYDB_BEGIN_ALLOW_THREADS;
2448 err = self->db->sync(self->db, flags);
2449 MYDB_END_ALLOW_THREADS;
2450 RETURN_IF_ERR();
2451 RETURN_NONE();
2455 #if (DBVER >= 33)
2456 static PyObject*
2457 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2459 int err, flags=0;
2460 u_int32_t count=0;
2461 PyObject* txnobj = NULL;
2462 DB_TXN *txn = NULL;
2463 static char* kwnames[] = { "txn", "flags", NULL };
2465 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2466 &txnobj, &flags))
2467 return NULL;
2468 CHECK_DB_NOT_CLOSED(self);
2469 if (!checkTxnObj(txnobj, &txn))
2470 return NULL;
2472 MYDB_BEGIN_ALLOW_THREADS;
2473 err = self->db->truncate(self->db, txn, &count, flags);
2474 MYDB_END_ALLOW_THREADS;
2475 RETURN_IF_ERR();
2476 return PyInt_FromLong(count);
2478 #endif
2481 static PyObject*
2482 DB_upgrade(DBObject* self, PyObject* args)
2484 int err, flags=0;
2485 char *filename;
2487 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2488 return NULL;
2489 CHECK_DB_NOT_CLOSED(self);
2491 MYDB_BEGIN_ALLOW_THREADS;
2492 err = self->db->upgrade(self->db, filename, flags);
2493 MYDB_END_ALLOW_THREADS;
2494 RETURN_IF_ERR();
2495 RETURN_NONE();
2499 static PyObject*
2500 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2502 int err, flags=0;
2503 char* fileName;
2504 char* dbName=NULL;
2505 char* outFileName=NULL;
2506 FILE* outFile=NULL;
2507 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2508 NULL };
2510 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2511 &fileName, &dbName, &outFileName, &flags))
2512 return NULL;
2514 CHECK_DB_NOT_CLOSED(self);
2515 if (outFileName)
2516 outFile = fopen(outFileName, "w");
2517 /* XXX(nnorwitz): it should probably be an exception if outFile
2518 can't be opened. */
2520 MYDB_BEGIN_ALLOW_THREADS;
2521 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2522 MYDB_END_ALLOW_THREADS;
2523 if (outFile)
2524 fclose(outFile);
2526 /* DB.verify acts as a DB handle destructor (like close); this was
2527 * documented in BerkeleyDB 4.2 but had the undocumented effect
2528 * of not being safe in prior versions while still requiring an explicit
2529 * DB.close call afterwards. Lets call close for the user to emulate
2530 * the safe 4.2 behaviour. */
2531 #if (DBVER <= 41)
2532 self->db->close(self->db, 0);
2533 #endif
2534 self->db = NULL;
2536 RETURN_IF_ERR();
2537 RETURN_NONE();
2541 static PyObject*
2542 DB_set_get_returns_none(DBObject* self, PyObject* args)
2544 int flags=0;
2545 int oldValue=0;
2547 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2548 return NULL;
2549 CHECK_DB_NOT_CLOSED(self);
2551 if (self->moduleFlags.getReturnsNone)
2552 ++oldValue;
2553 if (self->moduleFlags.cursorSetReturnsNone)
2554 ++oldValue;
2555 self->moduleFlags.getReturnsNone = (flags >= 1);
2556 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2557 return PyInt_FromLong(oldValue);
2560 #if (DBVER >= 41)
2561 static PyObject*
2562 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2564 int err;
2565 u_int32_t flags=0;
2566 char *passwd = NULL;
2567 static char* kwnames[] = { "passwd", "flags", NULL };
2569 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2570 &passwd, &flags)) {
2571 return NULL;
2574 MYDB_BEGIN_ALLOW_THREADS;
2575 err = self->db->set_encrypt(self->db, passwd, flags);
2576 MYDB_END_ALLOW_THREADS;
2578 RETURN_IF_ERR();
2579 RETURN_NONE();
2581 #endif /* DBVER >= 41 */
2584 /*-------------------------------------------------------------- */
2585 /* Mapping and Dictionary-like access routines */
2587 Py_ssize_t DB_length(PyObject* _self)
2589 int err;
2590 Py_ssize_t size = 0;
2591 int flags = 0;
2592 void* sp;
2593 DBObject* self = (DBObject*)_self;
2595 if (self->db == NULL) {
2596 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2597 PyErr_SetObject(DBError, t);
2598 Py_DECREF(t);
2599 return -1;
2602 if (self->haveStat) { /* Has the stat function been called recently? If
2603 so, we can use the cached value. */
2604 flags = DB_FAST_STAT;
2607 MYDB_BEGIN_ALLOW_THREADS;
2608 redo_stat_for_length:
2609 #if (DBVER >= 43)
2610 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2611 #elif (DBVER >= 33)
2612 err = self->db->stat(self->db, &sp, flags);
2613 #else
2614 err = self->db->stat(self->db, &sp, NULL, flags);
2615 #endif
2617 /* All the stat structures have matching fields upto the ndata field,
2618 so we can use any of them for the type cast */
2619 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2621 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2622 * redo a full stat to make sure.
2623 * Fixes SF python bug 1493322, pybsddb bug 1184012
2625 if (size == 0 && (flags & DB_FAST_STAT)) {
2626 flags = 0;
2627 if (!err)
2628 free(sp);
2629 goto redo_stat_for_length;
2632 MYDB_END_ALLOW_THREADS;
2634 if (err)
2635 return -1;
2637 self->haveStat = 1;
2639 free(sp);
2640 return size;
2644 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2646 int err;
2647 PyObject* retval;
2648 DBT key;
2649 DBT data;
2651 CHECK_DB_NOT_CLOSED(self);
2652 if (!make_key_dbt(self, keyobj, &key, NULL))
2653 return NULL;
2655 CLEAR_DBT(data);
2656 if (CHECK_DBFLAG(self, DB_THREAD)) {
2657 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2658 data.flags = DB_DBT_MALLOC;
2660 MYDB_BEGIN_ALLOW_THREADS;
2661 err = self->db->get(self->db, NULL, &key, &data, 0);
2662 MYDB_END_ALLOW_THREADS;
2663 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2664 PyErr_SetObject(PyExc_KeyError, keyobj);
2665 retval = NULL;
2667 else if (makeDBError(err)) {
2668 retval = NULL;
2670 else {
2671 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2672 FREE_DBT(data);
2675 FREE_DBT(key);
2676 return retval;
2680 static int
2681 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2683 DBT key, data;
2684 int retval;
2685 int flags = 0;
2687 if (self->db == NULL) {
2688 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2689 PyErr_SetObject(DBError, t);
2690 Py_DECREF(t);
2691 return -1;
2694 if (!make_key_dbt(self, keyobj, &key, NULL))
2695 return -1;
2697 if (dataobj != NULL) {
2698 if (!make_dbt(dataobj, &data))
2699 retval = -1;
2700 else {
2701 if (self->setflags & (DB_DUP|DB_DUPSORT))
2702 /* dictionaries shouldn't have duplicate keys */
2703 flags = DB_NOOVERWRITE;
2704 retval = _DB_put(self, NULL, &key, &data, flags);
2706 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2707 /* try deleting any old record that matches and then PUT it
2708 * again... */
2709 _DB_delete(self, NULL, &key, 0);
2710 PyErr_Clear();
2711 retval = _DB_put(self, NULL, &key, &data, flags);
2715 else {
2716 /* dataobj == NULL, so delete the key */
2717 retval = _DB_delete(self, NULL, &key, 0);
2719 FREE_DBT(key);
2720 return retval;
2724 static PyObject*
2725 DB_has_key(DBObject* self, PyObject* args)
2727 int err;
2728 PyObject* keyobj;
2729 DBT key, data;
2730 PyObject* txnobj = NULL;
2731 DB_TXN *txn = NULL;
2733 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2734 return NULL;
2735 CHECK_DB_NOT_CLOSED(self);
2736 if (!make_key_dbt(self, keyobj, &key, NULL))
2737 return NULL;
2738 if (!checkTxnObj(txnobj, &txn)) {
2739 FREE_DBT(key);
2740 return NULL;
2743 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2744 it has a record but can't allocate a buffer for the data. This saves
2745 having to deal with data we won't be using.
2747 CLEAR_DBT(data);
2748 data.flags = DB_DBT_USERMEM;
2750 MYDB_BEGIN_ALLOW_THREADS;
2751 err = self->db->get(self->db, txn, &key, &data, 0);
2752 MYDB_END_ALLOW_THREADS;
2753 FREE_DBT(key);
2755 if (err == DB_BUFFER_SMALL || err == 0) {
2756 return PyInt_FromLong(1);
2757 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2758 return PyInt_FromLong(0);
2761 makeDBError(err);
2762 return NULL;
2766 #define _KEYS_LIST 1
2767 #define _VALUES_LIST 2
2768 #define _ITEMS_LIST 3
2770 static PyObject*
2771 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2773 int err, dbtype;
2774 DBT key;
2775 DBT data;
2776 DBC *cursor;
2777 PyObject* list;
2778 PyObject* item = NULL;
2780 CHECK_DB_NOT_CLOSED(self);
2781 CLEAR_DBT(key);
2782 CLEAR_DBT(data);
2784 dbtype = _DB_get_type(self);
2785 if (dbtype == -1)
2786 return NULL;
2788 list = PyList_New(0);
2789 if (list == NULL)
2790 return NULL;
2792 /* get a cursor */
2793 MYDB_BEGIN_ALLOW_THREADS;
2794 err = self->db->cursor(self->db, txn, &cursor, 0);
2795 MYDB_END_ALLOW_THREADS;
2796 if (makeDBError(err)) {
2797 Py_DECREF(list);
2798 return NULL;
2801 if (CHECK_DBFLAG(self, DB_THREAD)) {
2802 key.flags = DB_DBT_REALLOC;
2803 data.flags = DB_DBT_REALLOC;
2806 while (1) { /* use the cursor to traverse the DB, collecting items */
2807 MYDB_BEGIN_ALLOW_THREADS;
2808 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2809 MYDB_END_ALLOW_THREADS;
2811 if (err) {
2812 /* for any error, break out of the loop */
2813 break;
2816 switch (type) {
2817 case _KEYS_LIST:
2818 switch(dbtype) {
2819 case DB_BTREE:
2820 case DB_HASH:
2821 default:
2822 item = PyString_FromStringAndSize((char*)key.data, key.size);
2823 break;
2824 case DB_RECNO:
2825 case DB_QUEUE:
2826 item = PyInt_FromLong(*((db_recno_t*)key.data));
2827 break;
2829 break;
2831 case _VALUES_LIST:
2832 item = PyString_FromStringAndSize((char*)data.data, data.size);
2833 break;
2835 case _ITEMS_LIST:
2836 switch(dbtype) {
2837 case DB_BTREE:
2838 case DB_HASH:
2839 default:
2840 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2841 data.size);
2842 break;
2843 case DB_RECNO:
2844 case DB_QUEUE:
2845 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2846 data.data, data.size);
2847 break;
2849 break;
2850 default:
2851 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2852 item = NULL;
2853 break;
2855 if (item == NULL) {
2856 Py_DECREF(list);
2857 list = NULL;
2858 goto done;
2860 PyList_Append(list, item);
2861 Py_DECREF(item);
2864 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2865 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2866 Py_DECREF(list);
2867 list = NULL;
2870 done:
2871 FREE_DBT(key);
2872 FREE_DBT(data);
2873 MYDB_BEGIN_ALLOW_THREADS;
2874 cursor->c_close(cursor);
2875 MYDB_END_ALLOW_THREADS;
2876 return list;
2880 static PyObject*
2881 DB_keys(DBObject* self, PyObject* args)
2883 PyObject* txnobj = NULL;
2884 DB_TXN *txn = NULL;
2886 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2887 return NULL;
2888 if (!checkTxnObj(txnobj, &txn))
2889 return NULL;
2890 return _DB_make_list(self, txn, _KEYS_LIST);
2894 static PyObject*
2895 DB_items(DBObject* self, PyObject* args)
2897 PyObject* txnobj = NULL;
2898 DB_TXN *txn = NULL;
2900 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
2901 return NULL;
2902 if (!checkTxnObj(txnobj, &txn))
2903 return NULL;
2904 return _DB_make_list(self, txn, _ITEMS_LIST);
2908 static PyObject*
2909 DB_values(DBObject* self, PyObject* args)
2911 PyObject* txnobj = NULL;
2912 DB_TXN *txn = NULL;
2914 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
2915 return NULL;
2916 if (!checkTxnObj(txnobj, &txn))
2917 return NULL;
2918 return _DB_make_list(self, txn, _VALUES_LIST);
2921 /* --------------------------------------------------------------------- */
2922 /* DBCursor methods */
2925 static PyObject*
2926 DBC_close(DBCursorObject* self, PyObject* args)
2928 int err = 0;
2930 if (!PyArg_ParseTuple(args, ":close"))
2931 return NULL;
2933 if (self->dbc != NULL) {
2934 MYDB_BEGIN_ALLOW_THREADS;
2935 err = self->dbc->c_close(self->dbc);
2936 self->dbc = NULL;
2937 MYDB_END_ALLOW_THREADS;
2939 RETURN_IF_ERR();
2940 RETURN_NONE();
2944 static PyObject*
2945 DBC_count(DBCursorObject* self, PyObject* args)
2947 int err = 0;
2948 db_recno_t count;
2949 int flags = 0;
2951 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2952 return NULL;
2954 CHECK_CURSOR_NOT_CLOSED(self);
2956 MYDB_BEGIN_ALLOW_THREADS;
2957 err = self->dbc->c_count(self->dbc, &count, flags);
2958 MYDB_END_ALLOW_THREADS;
2959 RETURN_IF_ERR();
2961 return PyInt_FromLong(count);
2965 static PyObject*
2966 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2968 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2972 static PyObject*
2973 DBC_delete(DBCursorObject* self, PyObject* args)
2975 int err, flags=0;
2977 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2978 return NULL;
2980 CHECK_CURSOR_NOT_CLOSED(self);
2982 MYDB_BEGIN_ALLOW_THREADS;
2983 err = self->dbc->c_del(self->dbc, flags);
2984 MYDB_END_ALLOW_THREADS;
2985 RETURN_IF_ERR();
2987 self->mydb->haveStat = 0;
2988 RETURN_NONE();
2992 static PyObject*
2993 DBC_dup(DBCursorObject* self, PyObject* args)
2995 int err, flags =0;
2996 DBC* dbc = NULL;
2998 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2999 return NULL;
3001 CHECK_CURSOR_NOT_CLOSED(self);
3003 MYDB_BEGIN_ALLOW_THREADS;
3004 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3005 MYDB_END_ALLOW_THREADS;
3006 RETURN_IF_ERR();
3008 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3011 static PyObject*
3012 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3014 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3018 static PyObject*
3019 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3021 int err, flags=0;
3022 PyObject* keyobj = NULL;
3023 PyObject* dataobj = NULL;
3024 PyObject* retval = NULL;
3025 int dlen = -1;
3026 int doff = -1;
3027 DBT key, data;
3028 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3029 NULL };
3031 CLEAR_DBT(key);
3032 CLEAR_DBT(data);
3033 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3034 &flags, &dlen, &doff))
3036 PyErr_Clear();
3037 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3038 &kwnames[1],
3039 &keyobj, &flags, &dlen, &doff))
3041 PyErr_Clear();
3042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3043 kwnames, &keyobj, &dataobj,
3044 &flags, &dlen, &doff))
3046 return NULL;
3051 CHECK_CURSOR_NOT_CLOSED(self);
3053 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3054 return NULL;
3055 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3056 (!add_partial_dbt(&data, dlen, doff)) )
3058 FREE_DBT(key);
3059 return NULL;
3062 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3063 data.flags = DB_DBT_MALLOC;
3064 if (!(key.flags & DB_DBT_REALLOC)) {
3065 key.flags |= DB_DBT_MALLOC;
3069 MYDB_BEGIN_ALLOW_THREADS;
3070 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3071 MYDB_END_ALLOW_THREADS;
3073 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3074 && self->mydb->moduleFlags.getReturnsNone) {
3075 Py_INCREF(Py_None);
3076 retval = Py_None;
3078 else if (makeDBError(err)) {
3079 retval = NULL;
3081 else {
3082 switch (_DB_get_type(self->mydb)) {
3083 case -1:
3084 retval = NULL;
3085 break;
3086 case DB_BTREE:
3087 case DB_HASH:
3088 default:
3089 retval = Py_BuildValue("s#s#", key.data, key.size,
3090 data.data, data.size);
3091 break;
3092 case DB_RECNO:
3093 case DB_QUEUE:
3094 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3095 data.data, data.size);
3096 break;
3098 FREE_DBT(data);
3100 FREE_DBT(key);
3101 return retval;
3104 #if (DBVER >= 33)
3105 static PyObject*
3106 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3108 int err, flags=0;
3109 PyObject* keyobj = NULL;
3110 PyObject* dataobj = NULL;
3111 PyObject* retval = NULL;
3112 int dlen = -1;
3113 int doff = -1;
3114 DBT key, pkey, data;
3115 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3116 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3118 CLEAR_DBT(key);
3119 CLEAR_DBT(data);
3120 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3121 &flags, &dlen, &doff))
3123 PyErr_Clear();
3124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3125 kwnames_keyOnly,
3126 &keyobj, &flags, &dlen, &doff))
3128 PyErr_Clear();
3129 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3130 kwnames, &keyobj, &dataobj,
3131 &flags, &dlen, &doff))
3133 return NULL;
3138 CHECK_CURSOR_NOT_CLOSED(self);
3140 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3141 return NULL;
3142 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3143 (!add_partial_dbt(&data, dlen, doff)) ) {
3144 FREE_DBT(key);
3145 return NULL;
3148 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3149 data.flags = DB_DBT_MALLOC;
3150 if (!(key.flags & DB_DBT_REALLOC)) {
3151 key.flags |= DB_DBT_MALLOC;
3155 CLEAR_DBT(pkey);
3156 pkey.flags = DB_DBT_MALLOC;
3158 MYDB_BEGIN_ALLOW_THREADS;
3159 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3160 MYDB_END_ALLOW_THREADS;
3162 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3163 && self->mydb->moduleFlags.getReturnsNone) {
3164 Py_INCREF(Py_None);
3165 retval = Py_None;
3167 else if (makeDBError(err)) {
3168 retval = NULL;
3170 else {
3171 PyObject *pkeyObj;
3172 PyObject *dataObj;
3173 dataObj = PyString_FromStringAndSize(data.data, data.size);
3175 if (self->mydb->primaryDBType == DB_RECNO ||
3176 self->mydb->primaryDBType == DB_QUEUE)
3177 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3178 else
3179 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3181 if (key.data && key.size) /* return key, pkey and data */
3183 PyObject *keyObj;
3184 int type = _DB_get_type(self->mydb);
3185 if (type == DB_RECNO || type == DB_QUEUE)
3186 keyObj = PyInt_FromLong(*(int *)key.data);
3187 else
3188 keyObj = PyString_FromStringAndSize(key.data, key.size);
3189 #if (PY_VERSION_HEX >= 0x02040000)
3190 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3191 #else
3192 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3193 #endif
3194 Py_DECREF(keyObj);
3195 FREE_DBT(key);
3197 else /* return just the pkey and data */
3199 #if (PY_VERSION_HEX >= 0x02040000)
3200 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3201 #else
3202 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3203 #endif
3205 Py_DECREF(dataObj);
3206 Py_DECREF(pkeyObj);
3207 FREE_DBT(pkey);
3208 FREE_DBT(data);
3210 /* the only time REALLOC should be set is if we used an integer
3211 * key that make_key_dbt malloc'd for us. always free these. */
3212 if (key.flags & DB_DBT_REALLOC) {
3213 FREE_DBT(key);
3215 return retval;
3217 #endif
3220 static PyObject*
3221 DBC_get_recno(DBCursorObject* self, PyObject* args)
3223 int err;
3224 db_recno_t recno;
3225 DBT key;
3226 DBT data;
3228 if (!PyArg_ParseTuple(args, ":get_recno"))
3229 return NULL;
3231 CHECK_CURSOR_NOT_CLOSED(self);
3233 CLEAR_DBT(key);
3234 CLEAR_DBT(data);
3235 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3236 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3237 data.flags = DB_DBT_MALLOC;
3238 key.flags = DB_DBT_MALLOC;
3241 MYDB_BEGIN_ALLOW_THREADS;
3242 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3243 MYDB_END_ALLOW_THREADS;
3244 RETURN_IF_ERR();
3246 recno = *((db_recno_t*)data.data);
3247 FREE_DBT(key);
3248 FREE_DBT(data);
3249 return PyInt_FromLong(recno);
3253 static PyObject*
3254 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3256 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3260 static PyObject*
3261 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3263 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3267 static PyObject*
3268 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3270 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3274 static PyObject*
3275 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3277 int err, flags = 0;
3278 PyObject* keyobj, *dataobj;
3279 DBT key, data;
3280 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3281 NULL };
3282 int dlen = -1;
3283 int doff = -1;
3285 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3286 &keyobj, &dataobj, &flags, &dlen, &doff))
3287 return NULL;
3289 CHECK_CURSOR_NOT_CLOSED(self);
3291 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3292 return NULL;
3293 if (!make_dbt(dataobj, &data) ||
3294 !add_partial_dbt(&data, dlen, doff) )
3296 FREE_DBT(key);
3297 return NULL;
3300 MYDB_BEGIN_ALLOW_THREADS;
3301 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3302 MYDB_END_ALLOW_THREADS;
3303 FREE_DBT(key);
3304 RETURN_IF_ERR();
3305 self->mydb->haveStat = 0;
3306 RETURN_NONE();
3310 static PyObject*
3311 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3313 int err, flags = 0;
3314 DBT key, data;
3315 PyObject* retval, *keyobj;
3316 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3317 int dlen = -1;
3318 int doff = -1;
3320 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3321 &keyobj, &flags, &dlen, &doff))
3322 return NULL;
3324 CHECK_CURSOR_NOT_CLOSED(self);
3326 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3327 return NULL;
3329 CLEAR_DBT(data);
3330 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3331 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3332 data.flags = DB_DBT_MALLOC;
3334 if (!add_partial_dbt(&data, dlen, doff)) {
3335 FREE_DBT(key);
3336 return NULL;
3339 MYDB_BEGIN_ALLOW_THREADS;
3340 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3341 MYDB_END_ALLOW_THREADS;
3342 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3343 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3344 Py_INCREF(Py_None);
3345 retval = Py_None;
3347 else if (makeDBError(err)) {
3348 retval = NULL;
3350 else {
3351 switch (_DB_get_type(self->mydb)) {
3352 case -1:
3353 retval = NULL;
3354 break;
3355 case DB_BTREE:
3356 case DB_HASH:
3357 default:
3358 retval = Py_BuildValue("s#s#", key.data, key.size,
3359 data.data, data.size);
3360 break;
3361 case DB_RECNO:
3362 case DB_QUEUE:
3363 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3364 data.data, data.size);
3365 break;
3367 FREE_DBT(data);
3368 FREE_DBT(key);
3370 /* the only time REALLOC should be set is if we used an integer
3371 * key that make_key_dbt malloc'd for us. always free these. */
3372 if (key.flags & DB_DBT_REALLOC) {
3373 FREE_DBT(key);
3376 return retval;
3380 static PyObject*
3381 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3383 int err, flags = 0;
3384 DBT key, data;
3385 PyObject* retval, *keyobj;
3386 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3387 int dlen = -1;
3388 int doff = -1;
3390 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3391 &keyobj, &flags, &dlen, &doff))
3392 return NULL;
3394 CHECK_CURSOR_NOT_CLOSED(self);
3396 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3397 return NULL;
3399 CLEAR_DBT(data);
3400 if (!add_partial_dbt(&data, dlen, doff)) {
3401 FREE_DBT(key);
3402 return NULL;
3404 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3405 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3406 data.flags |= DB_DBT_MALLOC;
3407 /* only BTREE databases will return anything in the key */
3408 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3409 key.flags |= DB_DBT_MALLOC;
3412 MYDB_BEGIN_ALLOW_THREADS;
3413 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3414 MYDB_END_ALLOW_THREADS;
3415 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3416 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3417 Py_INCREF(Py_None);
3418 retval = Py_None;
3420 else if (makeDBError(err)) {
3421 retval = NULL;
3423 else {
3424 switch (_DB_get_type(self->mydb)) {
3425 case -1:
3426 retval = NULL;
3427 break;
3428 case DB_BTREE:
3429 case DB_HASH:
3430 default:
3431 retval = Py_BuildValue("s#s#", key.data, key.size,
3432 data.data, data.size);
3433 break;
3434 case DB_RECNO:
3435 case DB_QUEUE:
3436 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3437 data.data, data.size);
3438 break;
3440 FREE_DBT(key);
3441 FREE_DBT(data);
3443 /* the only time REALLOC should be set is if we used an integer
3444 * key that make_key_dbt malloc'd for us. always free these. */
3445 if (key.flags & DB_DBT_REALLOC) {
3446 FREE_DBT(key);
3449 return retval;
3452 static PyObject*
3453 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3454 int flags, unsigned int returnsNone)
3456 int err;
3457 DBT key, data;
3458 PyObject* retval;
3460 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3461 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3462 return NULL;
3463 if (!make_dbt(dataobj, &data)) {
3464 FREE_DBT(key);
3465 return NULL;
3468 MYDB_BEGIN_ALLOW_THREADS;
3469 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3470 MYDB_END_ALLOW_THREADS;
3471 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3472 Py_INCREF(Py_None);
3473 retval = Py_None;
3475 else if (makeDBError(err)) {
3476 retval = NULL;
3478 else {
3479 switch (_DB_get_type(self->mydb)) {
3480 case -1:
3481 retval = NULL;
3482 break;
3483 case DB_BTREE:
3484 case DB_HASH:
3485 default:
3486 retval = Py_BuildValue("s#s#", key.data, key.size,
3487 data.data, data.size);
3488 break;
3489 case DB_RECNO:
3490 case DB_QUEUE:
3491 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3492 data.data, data.size);
3493 break;
3497 FREE_DBT(key);
3498 return retval;
3501 static PyObject*
3502 DBC_get_both(DBCursorObject* self, PyObject* args)
3504 int flags=0;
3505 PyObject *keyobj, *dataobj;
3507 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3508 return NULL;
3510 /* if the cursor is closed, self->mydb may be invalid */
3511 CHECK_CURSOR_NOT_CLOSED(self);
3513 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3514 self->mydb->moduleFlags.getReturnsNone);
3517 /* Return size of entry */
3518 static PyObject*
3519 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3521 int err, flags=DB_CURRENT;
3522 PyObject* retval = NULL;
3523 DBT key, data;
3525 if (!PyArg_ParseTuple(args, ":get_current_size"))
3526 return NULL;
3527 CHECK_CURSOR_NOT_CLOSED(self);
3528 CLEAR_DBT(key);
3529 CLEAR_DBT(data);
3531 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3532 getting the record size. */
3533 data.flags = DB_DBT_USERMEM;
3534 data.ulen = 0;
3535 MYDB_BEGIN_ALLOW_THREADS;
3536 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3537 MYDB_END_ALLOW_THREADS;
3538 if (err == DB_BUFFER_SMALL || !err) {
3539 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3540 retval = PyInt_FromLong((long)data.size);
3541 err = 0;
3544 FREE_DBT(key);
3545 FREE_DBT(data);
3546 RETURN_IF_ERR();
3547 return retval;
3550 static PyObject*
3551 DBC_set_both(DBCursorObject* self, PyObject* args)
3553 int flags=0;
3554 PyObject *keyobj, *dataobj;
3556 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3557 return NULL;
3559 /* if the cursor is closed, self->mydb may be invalid */
3560 CHECK_CURSOR_NOT_CLOSED(self);
3562 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3563 self->mydb->moduleFlags.cursorSetReturnsNone);
3567 static PyObject*
3568 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3570 int err, irecno, flags=0;
3571 db_recno_t recno;
3572 DBT key, data;
3573 PyObject* retval;
3574 int dlen = -1;
3575 int doff = -1;
3576 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3578 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3579 &irecno, &flags, &dlen, &doff))
3580 return NULL;
3582 CHECK_CURSOR_NOT_CLOSED(self);
3584 CLEAR_DBT(key);
3585 recno = (db_recno_t) irecno;
3586 /* use allocated space so DB will be able to realloc room for the real
3587 * key */
3588 key.data = malloc(sizeof(db_recno_t));
3589 if (key.data == NULL) {
3590 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3591 return NULL;
3593 key.size = sizeof(db_recno_t);
3594 key.ulen = key.size;
3595 memcpy(key.data, &recno, sizeof(db_recno_t));
3596 key.flags = DB_DBT_REALLOC;
3598 CLEAR_DBT(data);
3599 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3600 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3601 data.flags = DB_DBT_MALLOC;
3603 if (!add_partial_dbt(&data, dlen, doff)) {
3604 FREE_DBT(key);
3605 return NULL;
3608 MYDB_BEGIN_ALLOW_THREADS;
3609 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3610 MYDB_END_ALLOW_THREADS;
3611 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3612 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3613 Py_INCREF(Py_None);
3614 retval = Py_None;
3616 else if (makeDBError(err)) {
3617 retval = NULL;
3619 else { /* Can only be used for BTrees, so no need to return int key */
3620 retval = Py_BuildValue("s#s#", key.data, key.size,
3621 data.data, data.size);
3622 FREE_DBT(data);
3624 FREE_DBT(key);
3626 return retval;
3630 static PyObject*
3631 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3633 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3637 static PyObject*
3638 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3640 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3644 static PyObject*
3645 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3647 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3651 static PyObject*
3652 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3654 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3658 static PyObject*
3659 DBC_join_item(DBCursorObject* self, PyObject* args)
3661 int err, flags=0;
3662 DBT key, data;
3663 PyObject* retval;
3665 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3666 return NULL;
3668 CHECK_CURSOR_NOT_CLOSED(self);
3670 CLEAR_DBT(key);
3671 CLEAR_DBT(data);
3672 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3673 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3674 key.flags = DB_DBT_MALLOC;
3677 MYDB_BEGIN_ALLOW_THREADS;
3678 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3679 MYDB_END_ALLOW_THREADS;
3680 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3681 && self->mydb->moduleFlags.getReturnsNone) {
3682 Py_INCREF(Py_None);
3683 retval = Py_None;
3685 else if (makeDBError(err)) {
3686 retval = NULL;
3688 else {
3689 retval = Py_BuildValue("s#", key.data, key.size);
3690 FREE_DBT(key);
3693 return retval;
3698 /* --------------------------------------------------------------------- */
3699 /* DBEnv methods */
3702 static PyObject*
3703 DBEnv_close(DBEnvObject* self, PyObject* args)
3705 int err, flags = 0;
3707 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3708 return NULL;
3709 if (!self->closed) { /* Don't close more than once */
3710 MYDB_BEGIN_ALLOW_THREADS;
3711 err = self->db_env->close(self->db_env, flags);
3712 MYDB_END_ALLOW_THREADS;
3713 /* after calling DBEnv->close, regardless of error, this DBEnv
3714 * may not be accessed again (BerkeleyDB docs). */
3715 self->closed = 1;
3716 self->db_env = NULL;
3717 RETURN_IF_ERR();
3719 RETURN_NONE();
3723 static PyObject*
3724 DBEnv_open(DBEnvObject* self, PyObject* args)
3726 int err, flags=0, mode=0660;
3727 char *db_home;
3729 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3730 return NULL;
3732 CHECK_ENV_NOT_CLOSED(self);
3734 MYDB_BEGIN_ALLOW_THREADS;
3735 err = self->db_env->open(self->db_env, db_home, flags, mode);
3736 MYDB_END_ALLOW_THREADS;
3737 RETURN_IF_ERR();
3738 self->closed = 0;
3739 self->flags = flags;
3740 RETURN_NONE();
3744 static PyObject*
3745 DBEnv_remove(DBEnvObject* self, PyObject* args)
3747 int err, flags=0;
3748 char *db_home;
3750 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3751 return NULL;
3752 CHECK_ENV_NOT_CLOSED(self);
3753 MYDB_BEGIN_ALLOW_THREADS;
3754 err = self->db_env->remove(self->db_env, db_home, flags);
3755 MYDB_END_ALLOW_THREADS;
3756 RETURN_IF_ERR();
3757 RETURN_NONE();
3760 #if (DBVER >= 41)
3761 static PyObject*
3762 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3764 int err;
3765 u_int32_t flags=0;
3766 char *file = NULL;
3767 char *database = NULL;
3768 PyObject *txnobj = NULL;
3769 DB_TXN *txn = NULL;
3770 static char* kwnames[] = { "file", "database", "txn", "flags",
3771 NULL };
3773 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
3774 &file, &database, &txnobj, &flags)) {
3775 return NULL;
3777 if (!checkTxnObj(txnobj, &txn)) {
3778 return NULL;
3780 CHECK_ENV_NOT_CLOSED(self);
3781 MYDB_BEGIN_ALLOW_THREADS;
3782 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3783 MYDB_END_ALLOW_THREADS;
3784 RETURN_IF_ERR();
3785 RETURN_NONE();
3788 static PyObject*
3789 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3791 int err;
3792 u_int32_t flags=0;
3793 char *file = NULL;
3794 char *database = NULL;
3795 char *newname = NULL;
3796 PyObject *txnobj = NULL;
3797 DB_TXN *txn = NULL;
3798 static char* kwnames[] = { "file", "database", "newname", "txn",
3799 "flags", NULL };
3801 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
3802 &file, &database, &newname, &txnobj, &flags)) {
3803 return NULL;
3805 if (!checkTxnObj(txnobj, &txn)) {
3806 return NULL;
3808 CHECK_ENV_NOT_CLOSED(self);
3809 MYDB_BEGIN_ALLOW_THREADS;
3810 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3811 flags);
3812 MYDB_END_ALLOW_THREADS;
3813 RETURN_IF_ERR();
3814 RETURN_NONE();
3817 static PyObject*
3818 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3820 int err;
3821 u_int32_t flags=0;
3822 char *passwd = NULL;
3823 static char* kwnames[] = { "passwd", "flags", NULL };
3825 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3826 &passwd, &flags)) {
3827 return NULL;
3830 MYDB_BEGIN_ALLOW_THREADS;
3831 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3832 MYDB_END_ALLOW_THREADS;
3834 RETURN_IF_ERR();
3835 RETURN_NONE();
3837 #endif /* DBVER >= 41 */
3839 #if (DBVER >= 40)
3840 static PyObject*
3841 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3843 int err;
3844 u_int32_t flags=0;
3845 u_int32_t timeout = 0;
3846 static char* kwnames[] = { "timeout", "flags", NULL };
3848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3849 &timeout, &flags)) {
3850 return NULL;
3853 MYDB_BEGIN_ALLOW_THREADS;
3854 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3855 MYDB_END_ALLOW_THREADS;
3857 RETURN_IF_ERR();
3858 RETURN_NONE();
3860 #endif /* DBVER >= 40 */
3862 static PyObject*
3863 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3865 int err;
3866 long shm_key = 0;
3868 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3869 return NULL;
3870 CHECK_ENV_NOT_CLOSED(self);
3872 err = self->db_env->set_shm_key(self->db_env, shm_key);
3873 RETURN_IF_ERR();
3874 RETURN_NONE();
3877 static PyObject*
3878 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3880 int err, gbytes=0, bytes=0, ncache=0;
3882 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3883 &gbytes, &bytes, &ncache))
3884 return NULL;
3885 CHECK_ENV_NOT_CLOSED(self);
3887 MYDB_BEGIN_ALLOW_THREADS;
3888 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3889 MYDB_END_ALLOW_THREADS;
3890 RETURN_IF_ERR();
3891 RETURN_NONE();
3895 static PyObject*
3896 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3898 int err, flags=0, onoff=0;
3900 if (!PyArg_ParseTuple(args, "ii:set_flags",
3901 &flags, &onoff))
3902 return NULL;
3903 CHECK_ENV_NOT_CLOSED(self);
3905 MYDB_BEGIN_ALLOW_THREADS;
3906 err = self->db_env->set_flags(self->db_env, flags, onoff);
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3913 static PyObject*
3914 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3916 int err;
3917 char *dir;
3919 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3920 return NULL;
3921 CHECK_ENV_NOT_CLOSED(self);
3923 MYDB_BEGIN_ALLOW_THREADS;
3924 err = self->db_env->set_data_dir(self->db_env, dir);
3925 MYDB_END_ALLOW_THREADS;
3926 RETURN_IF_ERR();
3927 RETURN_NONE();
3931 static PyObject*
3932 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3934 int err, lg_bsize;
3936 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3937 return NULL;
3938 CHECK_ENV_NOT_CLOSED(self);
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3942 MYDB_END_ALLOW_THREADS;
3943 RETURN_IF_ERR();
3944 RETURN_NONE();
3948 static PyObject*
3949 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3951 int err;
3952 char *dir;
3954 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3955 return NULL;
3956 CHECK_ENV_NOT_CLOSED(self);
3958 MYDB_BEGIN_ALLOW_THREADS;
3959 err = self->db_env->set_lg_dir(self->db_env, dir);
3960 MYDB_END_ALLOW_THREADS;
3961 RETURN_IF_ERR();
3962 RETURN_NONE();
3965 static PyObject*
3966 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3968 int err, lg_max;
3970 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3971 return NULL;
3972 CHECK_ENV_NOT_CLOSED(self);
3974 MYDB_BEGIN_ALLOW_THREADS;
3975 err = self->db_env->set_lg_max(self->db_env, lg_max);
3976 MYDB_END_ALLOW_THREADS;
3977 RETURN_IF_ERR();
3978 RETURN_NONE();
3982 #if (DBVER >= 33)
3983 static PyObject*
3984 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
3986 int err, lg_max;
3988 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
3989 return NULL;
3990 CHECK_ENV_NOT_CLOSED(self);
3992 MYDB_BEGIN_ALLOW_THREADS;
3993 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
3994 MYDB_END_ALLOW_THREADS;
3995 RETURN_IF_ERR();
3996 RETURN_NONE();
3998 #endif
4001 static PyObject*
4002 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4004 int err, lk_detect;
4006 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4007 return NULL;
4008 CHECK_ENV_NOT_CLOSED(self);
4010 MYDB_BEGIN_ALLOW_THREADS;
4011 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4012 MYDB_END_ALLOW_THREADS;
4013 RETURN_IF_ERR();
4014 RETURN_NONE();
4018 #if (DBVER < 45)
4019 static PyObject*
4020 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4022 int err, max;
4024 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4025 return NULL;
4026 CHECK_ENV_NOT_CLOSED(self);
4028 MYDB_BEGIN_ALLOW_THREADS;
4029 err = self->db_env->set_lk_max(self->db_env, max);
4030 MYDB_END_ALLOW_THREADS;
4031 RETURN_IF_ERR();
4032 RETURN_NONE();
4034 #endif
4038 static PyObject*
4039 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4041 int err, max;
4043 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4044 return NULL;
4045 CHECK_ENV_NOT_CLOSED(self);
4047 MYDB_BEGIN_ALLOW_THREADS;
4048 err = self->db_env->set_lk_max_locks(self->db_env, max);
4049 MYDB_END_ALLOW_THREADS;
4050 RETURN_IF_ERR();
4051 RETURN_NONE();
4055 static PyObject*
4056 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4058 int err, max;
4060 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4061 return NULL;
4062 CHECK_ENV_NOT_CLOSED(self);
4064 MYDB_BEGIN_ALLOW_THREADS;
4065 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4066 MYDB_END_ALLOW_THREADS;
4067 RETURN_IF_ERR();
4068 RETURN_NONE();
4072 static PyObject*
4073 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4075 int err, max;
4077 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4078 return NULL;
4079 CHECK_ENV_NOT_CLOSED(self);
4081 MYDB_BEGIN_ALLOW_THREADS;
4082 err = self->db_env->set_lk_max_objects(self->db_env, max);
4083 MYDB_END_ALLOW_THREADS;
4084 RETURN_IF_ERR();
4085 RETURN_NONE();
4089 static PyObject*
4090 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4092 int err, mp_mmapsize;
4094 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4095 return NULL;
4096 CHECK_ENV_NOT_CLOSED(self);
4098 MYDB_BEGIN_ALLOW_THREADS;
4099 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4100 MYDB_END_ALLOW_THREADS;
4101 RETURN_IF_ERR();
4102 RETURN_NONE();
4106 static PyObject*
4107 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4109 int err;
4110 char *dir;
4112 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4113 return NULL;
4114 CHECK_ENV_NOT_CLOSED(self);
4116 MYDB_BEGIN_ALLOW_THREADS;
4117 err = self->db_env->set_tmp_dir(self->db_env, dir);
4118 MYDB_END_ALLOW_THREADS;
4119 RETURN_IF_ERR();
4120 RETURN_NONE();
4124 static PyObject*
4125 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4127 int flags = 0;
4128 PyObject* txnobj = NULL;
4129 DB_TXN *txn = NULL;
4130 static char* kwnames[] = { "parent", "flags", NULL };
4132 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4133 &txnobj, &flags))
4134 return NULL;
4136 if (!checkTxnObj(txnobj, &txn))
4137 return NULL;
4138 CHECK_ENV_NOT_CLOSED(self);
4140 return (PyObject*)newDBTxnObject(self, txn, flags);
4144 static PyObject*
4145 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4147 int err, kbyte=0, min=0, flags=0;
4149 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4150 return NULL;
4151 CHECK_ENV_NOT_CLOSED(self);
4153 MYDB_BEGIN_ALLOW_THREADS;
4154 #if (DBVER >= 40)
4155 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4156 #else
4157 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4158 #endif
4159 MYDB_END_ALLOW_THREADS;
4160 RETURN_IF_ERR();
4161 RETURN_NONE();
4165 static PyObject*
4166 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4168 int err, max;
4170 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4171 return NULL;
4172 CHECK_ENV_NOT_CLOSED(self);
4174 err = self->db_env->set_tx_max(self->db_env, max);
4175 RETURN_IF_ERR();
4176 RETURN_NONE();
4180 static PyObject*
4181 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4183 int err;
4184 long stamp;
4185 time_t timestamp;
4187 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4188 return NULL;
4189 CHECK_ENV_NOT_CLOSED(self);
4190 timestamp = (time_t)stamp;
4191 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4192 RETURN_IF_ERR();
4193 RETURN_NONE();
4197 static PyObject*
4198 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4200 int err, atype, flags=0;
4201 int aborted = 0;
4203 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4204 return NULL;
4205 CHECK_ENV_NOT_CLOSED(self);
4207 MYDB_BEGIN_ALLOW_THREADS;
4208 #if (DBVER >= 40)
4209 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4210 #else
4211 err = lock_detect(self->db_env, flags, atype, &aborted);
4212 #endif
4213 MYDB_END_ALLOW_THREADS;
4214 RETURN_IF_ERR();
4215 return PyInt_FromLong(aborted);
4219 static PyObject*
4220 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4222 int flags=0;
4223 int locker, lock_mode;
4224 DBT obj;
4225 PyObject* objobj;
4227 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4228 return NULL;
4231 if (!make_dbt(objobj, &obj))
4232 return NULL;
4234 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4238 static PyObject*
4239 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4241 int err;
4242 u_int32_t theID;
4244 if (!PyArg_ParseTuple(args, ":lock_id"))
4245 return NULL;
4247 CHECK_ENV_NOT_CLOSED(self);
4248 MYDB_BEGIN_ALLOW_THREADS;
4249 #if (DBVER >= 40)
4250 err = self->db_env->lock_id(self->db_env, &theID);
4251 #else
4252 err = lock_id(self->db_env, &theID);
4253 #endif
4254 MYDB_END_ALLOW_THREADS;
4255 RETURN_IF_ERR();
4257 return PyInt_FromLong((long)theID);
4260 #if (DBVER >= 40)
4261 static PyObject*
4262 DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4264 int err;
4265 u_int32_t theID;
4267 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4268 return NULL;
4270 CHECK_ENV_NOT_CLOSED(self);
4271 MYDB_BEGIN_ALLOW_THREADS;
4272 err = self->db_env->lock_id_free(self->db_env, theID);
4273 MYDB_END_ALLOW_THREADS;
4274 RETURN_IF_ERR();
4275 RETURN_NONE();
4277 #endif
4279 static PyObject*
4280 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4282 int err;
4283 DBLockObject* dblockobj;
4285 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4286 return NULL;
4288 CHECK_ENV_NOT_CLOSED(self);
4289 MYDB_BEGIN_ALLOW_THREADS;
4290 #if (DBVER >= 40)
4291 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4292 #else
4293 err = lock_put(self->db_env, &dblockobj->lock);
4294 #endif
4295 MYDB_END_ALLOW_THREADS;
4296 RETURN_IF_ERR();
4297 RETURN_NONE();
4300 #if (DBVER >= 44)
4301 static PyObject*
4302 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4304 int err;
4305 char *file;
4306 u_int32_t flags = 0;
4307 static char* kwnames[] = { "file", "flags", NULL};
4309 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4310 &file, &flags))
4311 return NULL;
4312 CHECK_ENV_NOT_CLOSED(self);
4314 MYDB_BEGIN_ALLOW_THREADS;
4315 err = self->db_env->lsn_reset(self->db_env, file, flags);
4316 MYDB_END_ALLOW_THREADS;
4317 RETURN_IF_ERR();
4318 RETURN_NONE();
4320 #endif /* DBVER >= 4.4 */
4322 #if (DBVER >= 40)
4323 static PyObject*
4324 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4326 int err;
4327 DB_LOG_STAT* statp = NULL;
4328 PyObject* d = NULL;
4329 u_int32_t flags = 0;
4331 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4332 return NULL;
4333 CHECK_ENV_NOT_CLOSED(self);
4335 MYDB_BEGIN_ALLOW_THREADS;
4336 err = self->db_env->log_stat(self->db_env, &statp, flags);
4337 MYDB_END_ALLOW_THREADS;
4338 RETURN_IF_ERR();
4340 /* Turn the stat structure into a dictionary */
4341 d = PyDict_New();
4342 if (d == NULL) {
4343 if (statp)
4344 free(statp);
4345 return NULL;
4348 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4350 MAKE_ENTRY(magic);
4351 MAKE_ENTRY(version);
4352 MAKE_ENTRY(mode);
4353 MAKE_ENTRY(lg_bsize);
4354 #if (DBVER >= 44)
4355 MAKE_ENTRY(lg_size);
4356 MAKE_ENTRY(record);
4357 #endif
4358 #if (DBVER <= 40)
4359 MAKE_ENTRY(lg_max);
4360 #endif
4361 MAKE_ENTRY(w_mbytes);
4362 MAKE_ENTRY(w_bytes);
4363 MAKE_ENTRY(wc_mbytes);
4364 MAKE_ENTRY(wc_bytes);
4365 MAKE_ENTRY(wcount);
4366 MAKE_ENTRY(wcount_fill);
4367 #if (DBVER >= 44)
4368 MAKE_ENTRY(rcount);
4369 #endif
4370 MAKE_ENTRY(scount);
4371 MAKE_ENTRY(cur_file);
4372 MAKE_ENTRY(cur_offset);
4373 MAKE_ENTRY(disk_file);
4374 MAKE_ENTRY(disk_offset);
4375 MAKE_ENTRY(maxcommitperflush);
4376 MAKE_ENTRY(mincommitperflush);
4377 MAKE_ENTRY(regsize);
4378 MAKE_ENTRY(region_wait);
4379 MAKE_ENTRY(region_nowait);
4381 #undef MAKE_ENTRY
4382 free(statp);
4383 return d;
4384 } /* DBEnv_log_stat */
4385 #endif /* DBVER >= 4.0 for log_stat method */
4388 static PyObject*
4389 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4391 int err;
4392 DB_LOCK_STAT* sp;
4393 PyObject* d = NULL;
4394 u_int32_t flags = 0;
4396 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4397 return NULL;
4398 CHECK_ENV_NOT_CLOSED(self);
4400 MYDB_BEGIN_ALLOW_THREADS;
4401 #if (DBVER >= 40)
4402 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4403 #else
4404 #if (DBVER >= 33)
4405 err = lock_stat(self->db_env, &sp);
4406 #else
4407 err = lock_stat(self->db_env, &sp, NULL);
4408 #endif
4409 #endif
4410 MYDB_END_ALLOW_THREADS;
4411 RETURN_IF_ERR();
4413 /* Turn the stat structure into a dictionary */
4414 d = PyDict_New();
4415 if (d == NULL) {
4416 free(sp);
4417 return NULL;
4420 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4422 #if (DBVER < 41)
4423 MAKE_ENTRY(lastid);
4424 #endif
4425 MAKE_ENTRY(nmodes);
4426 MAKE_ENTRY(maxlocks);
4427 MAKE_ENTRY(maxlockers);
4428 MAKE_ENTRY(maxobjects);
4429 MAKE_ENTRY(nlocks);
4430 MAKE_ENTRY(maxnlocks);
4431 MAKE_ENTRY(nlockers);
4432 MAKE_ENTRY(maxnlockers);
4433 MAKE_ENTRY(nobjects);
4434 MAKE_ENTRY(maxnobjects);
4435 MAKE_ENTRY(nrequests);
4436 MAKE_ENTRY(nreleases);
4437 #if (DBVER < 44)
4438 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4439 MAKE_ENTRY(nconflicts);
4440 #else
4441 MAKE_ENTRY(lock_nowait);
4442 MAKE_ENTRY(lock_wait);
4443 #endif
4444 MAKE_ENTRY(ndeadlocks);
4445 MAKE_ENTRY(regsize);
4446 MAKE_ENTRY(region_wait);
4447 MAKE_ENTRY(region_nowait);
4449 #undef MAKE_ENTRY
4450 free(sp);
4451 return d;
4455 static PyObject*
4456 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4458 int flags=0;
4459 int err;
4460 char **log_list = NULL;
4461 PyObject* list;
4462 PyObject* item = NULL;
4464 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4465 return NULL;
4467 CHECK_ENV_NOT_CLOSED(self);
4468 MYDB_BEGIN_ALLOW_THREADS;
4469 #if (DBVER >= 40)
4470 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4471 #elif (DBVER == 33)
4472 err = log_archive(self->db_env, &log_list, flags);
4473 #else
4474 err = log_archive(self->db_env, &log_list, flags, NULL);
4475 #endif
4476 MYDB_END_ALLOW_THREADS;
4477 RETURN_IF_ERR();
4479 list = PyList_New(0);
4480 if (list == NULL) {
4481 if (log_list)
4482 free(log_list);
4483 return NULL;
4486 if (log_list) {
4487 char **log_list_start;
4488 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4489 item = PyString_FromString (*log_list);
4490 if (item == NULL) {
4491 Py_DECREF(list);
4492 list = NULL;
4493 break;
4495 PyList_Append(list, item);
4496 Py_DECREF(item);
4498 free(log_list_start);
4500 return list;
4504 static PyObject*
4505 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4507 int err;
4508 DB_TXN_STAT* sp;
4509 PyObject* d = NULL;
4510 u_int32_t flags=0;
4512 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4513 return NULL;
4514 CHECK_ENV_NOT_CLOSED(self);
4516 MYDB_BEGIN_ALLOW_THREADS;
4517 #if (DBVER >= 40)
4518 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4519 #elif (DBVER == 33)
4520 err = txn_stat(self->db_env, &sp);
4521 #else
4522 err = txn_stat(self->db_env, &sp, NULL);
4523 #endif
4524 MYDB_END_ALLOW_THREADS;
4525 RETURN_IF_ERR();
4527 /* Turn the stat structure into a dictionary */
4528 d = PyDict_New();
4529 if (d == NULL) {
4530 free(sp);
4531 return NULL;
4534 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4535 #define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
4537 MAKE_TIME_T_ENTRY(time_ckp);
4538 MAKE_ENTRY(last_txnid);
4539 MAKE_ENTRY(maxtxns);
4540 MAKE_ENTRY(nactive);
4541 MAKE_ENTRY(maxnactive);
4542 MAKE_ENTRY(nbegins);
4543 MAKE_ENTRY(naborts);
4544 MAKE_ENTRY(ncommits);
4545 MAKE_ENTRY(regsize);
4546 MAKE_ENTRY(region_wait);
4547 MAKE_ENTRY(region_nowait);
4549 #undef MAKE_ENTRY
4550 #undef MAKE_TIME_T_ENTRY
4551 free(sp);
4552 return d;
4556 static PyObject*
4557 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4559 int flags=0;
4560 int oldValue=0;
4562 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4563 return NULL;
4564 CHECK_ENV_NOT_CLOSED(self);
4566 if (self->moduleFlags.getReturnsNone)
4567 ++oldValue;
4568 if (self->moduleFlags.cursorSetReturnsNone)
4569 ++oldValue;
4570 self->moduleFlags.getReturnsNone = (flags >= 1);
4571 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4572 return PyInt_FromLong(oldValue);
4576 /* --------------------------------------------------------------------- */
4577 /* DBTxn methods */
4580 static PyObject*
4581 DBTxn_commit(DBTxnObject* self, PyObject* args)
4583 int flags=0, err;
4584 DB_TXN *txn;
4586 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4587 return NULL;
4589 if (!self->txn) {
4590 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4591 "after txn_commit or txn_abort");
4592 PyErr_SetObject(DBError, t);
4593 Py_DECREF(t);
4594 return NULL;
4596 txn = self->txn;
4597 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4598 MYDB_BEGIN_ALLOW_THREADS;
4599 #if (DBVER >= 40)
4600 err = txn->commit(txn, flags);
4601 #else
4602 err = txn_commit(txn, flags);
4603 #endif
4604 MYDB_END_ALLOW_THREADS;
4605 RETURN_IF_ERR();
4606 RETURN_NONE();
4609 static PyObject*
4610 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4612 #if (DBVER >= 33)
4613 int err;
4614 char* gid=NULL;
4615 int gid_size=0;
4617 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4618 return NULL;
4620 if (gid_size != DB_XIDDATASIZE) {
4621 PyErr_SetString(PyExc_TypeError,
4622 "gid must be DB_XIDDATASIZE bytes long");
4623 return NULL;
4626 if (!self->txn) {
4627 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4628 "after txn_commit or txn_abort");
4629 PyErr_SetObject(DBError, t);
4630 Py_DECREF(t);
4631 return NULL;
4633 MYDB_BEGIN_ALLOW_THREADS;
4634 #if (DBVER >= 40)
4635 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4636 #else
4637 err = txn_prepare(self->txn, (u_int8_t*)gid);
4638 #endif
4639 MYDB_END_ALLOW_THREADS;
4640 RETURN_IF_ERR();
4641 RETURN_NONE();
4642 #else
4643 int err;
4645 if (!PyArg_ParseTuple(args, ":prepare"))
4646 return NULL;
4648 if (!self->txn) {
4649 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4650 "after txn_commit or txn_abort");
4651 PyErr_SetObject(DBError, t);
4652 Py_DECREF(t);
4653 return NULL;
4655 MYDB_BEGIN_ALLOW_THREADS;
4656 err = txn_prepare(self->txn);
4657 MYDB_END_ALLOW_THREADS;
4658 RETURN_IF_ERR();
4659 RETURN_NONE();
4660 #endif
4664 static PyObject*
4665 DBTxn_abort(DBTxnObject* self, PyObject* args)
4667 int err;
4668 DB_TXN *txn;
4670 if (!PyArg_ParseTuple(args, ":abort"))
4671 return NULL;
4673 if (!self->txn) {
4674 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4675 "after txn_commit or txn_abort");
4676 PyErr_SetObject(DBError, t);
4677 Py_DECREF(t);
4678 return NULL;
4680 txn = self->txn;
4681 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4682 MYDB_BEGIN_ALLOW_THREADS;
4683 #if (DBVER >= 40)
4684 err = txn->abort(txn);
4685 #else
4686 err = txn_abort(txn);
4687 #endif
4688 MYDB_END_ALLOW_THREADS;
4689 RETURN_IF_ERR();
4690 RETURN_NONE();
4694 static PyObject*
4695 DBTxn_id(DBTxnObject* self, PyObject* args)
4697 int id;
4699 if (!PyArg_ParseTuple(args, ":id"))
4700 return NULL;
4702 if (!self->txn) {
4703 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4704 "after txn_commit or txn_abort");
4705 PyErr_SetObject(DBError, t);
4706 Py_DECREF(t);
4707 return NULL;
4709 MYDB_BEGIN_ALLOW_THREADS;
4710 #if (DBVER >= 40)
4711 id = self->txn->id(self->txn);
4712 #else
4713 id = txn_id(self->txn);
4714 #endif
4715 MYDB_END_ALLOW_THREADS;
4716 return PyInt_FromLong(id);
4719 #if (DBVER >= 43)
4720 /* --------------------------------------------------------------------- */
4721 /* DBSequence methods */
4724 static PyObject*
4725 DBSequence_close(DBSequenceObject* self, PyObject* args)
4727 int err, flags=0;
4728 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4729 return NULL;
4730 CHECK_SEQUENCE_NOT_CLOSED(self)
4732 MYDB_BEGIN_ALLOW_THREADS
4733 err = self->sequence->close(self->sequence, flags);
4734 self->sequence = NULL;
4735 MYDB_END_ALLOW_THREADS
4737 RETURN_IF_ERR();
4739 RETURN_NONE();
4742 static PyObject*
4743 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4745 int err, flags = 0;
4746 int delta = 1;
4747 db_seq_t value;
4748 PyObject *txnobj = NULL;
4749 DB_TXN *txn = NULL;
4750 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4751 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4752 return NULL;
4753 CHECK_SEQUENCE_NOT_CLOSED(self)
4755 if (!checkTxnObj(txnobj, &txn))
4756 return NULL;
4758 MYDB_BEGIN_ALLOW_THREADS
4759 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4760 MYDB_END_ALLOW_THREADS
4762 RETURN_IF_ERR();
4763 return PyLong_FromLongLong(value);
4767 static PyObject*
4768 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4770 if (!PyArg_ParseTuple(args,":get_dbp"))
4771 return NULL;
4772 CHECK_SEQUENCE_NOT_CLOSED(self)
4773 Py_INCREF(self->mydb);
4774 return (PyObject* )self->mydb;
4777 static PyObject*
4778 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4780 int err;
4781 DBT key;
4782 PyObject *retval = NULL;
4783 key.flags = DB_DBT_MALLOC;
4784 CHECK_SEQUENCE_NOT_CLOSED(self)
4785 MYDB_BEGIN_ALLOW_THREADS
4786 err = self->sequence->get_key(self->sequence, &key);
4787 MYDB_END_ALLOW_THREADS
4789 if (!err)
4790 retval = PyString_FromStringAndSize(key.data, key.size);
4792 FREE_DBT(key);
4793 RETURN_IF_ERR();
4795 return retval;
4798 static PyObject*
4799 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4801 int err;
4802 db_seq_t value;
4803 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4804 return NULL;
4805 CHECK_SEQUENCE_NOT_CLOSED(self)
4807 MYDB_BEGIN_ALLOW_THREADS
4808 err = self->sequence->initial_value(self->sequence, value);
4809 MYDB_END_ALLOW_THREADS
4811 RETURN_IF_ERR();
4813 RETURN_NONE();
4816 static PyObject*
4817 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4819 int err, flags = 0;
4820 PyObject* keyobj;
4821 PyObject *txnobj = NULL;
4822 DB_TXN *txn = NULL;
4823 DBT key;
4825 static char* kwnames[] = {"key", "txn", "flags", NULL };
4826 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4827 return NULL;
4829 if (!checkTxnObj(txnobj, &txn))
4830 return NULL;
4832 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4833 return NULL;
4835 MYDB_BEGIN_ALLOW_THREADS
4836 err = self->sequence->open(self->sequence, txn, &key, flags);
4837 MYDB_END_ALLOW_THREADS
4839 CLEAR_DBT(key);
4840 RETURN_IF_ERR();
4842 RETURN_NONE();
4845 static PyObject*
4846 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4848 int err, flags = 0;
4849 PyObject *txnobj = NULL;
4850 DB_TXN *txn = NULL;
4852 static char* kwnames[] = {"txn", "flags", NULL };
4853 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4854 return NULL;
4856 if (!checkTxnObj(txnobj, &txn))
4857 return NULL;
4859 CHECK_SEQUENCE_NOT_CLOSED(self)
4861 MYDB_BEGIN_ALLOW_THREADS
4862 err = self->sequence->remove(self->sequence, txn, flags);
4863 MYDB_END_ALLOW_THREADS
4865 RETURN_IF_ERR();
4866 RETURN_NONE();
4869 static PyObject*
4870 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4872 int err, size;
4873 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4874 return NULL;
4875 CHECK_SEQUENCE_NOT_CLOSED(self)
4877 MYDB_BEGIN_ALLOW_THREADS
4878 err = self->sequence->set_cachesize(self->sequence, size);
4879 MYDB_END_ALLOW_THREADS
4881 RETURN_IF_ERR();
4882 RETURN_NONE();
4885 static PyObject*
4886 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4888 int err, size;
4889 if (!PyArg_ParseTuple(args,":get_cachesize"))
4890 return NULL;
4891 CHECK_SEQUENCE_NOT_CLOSED(self)
4893 MYDB_BEGIN_ALLOW_THREADS
4894 err = self->sequence->get_cachesize(self->sequence, &size);
4895 MYDB_END_ALLOW_THREADS
4897 RETURN_IF_ERR();
4898 return PyInt_FromLong(size);
4901 static PyObject*
4902 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4904 int err, flags = 0;
4905 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4906 return NULL;
4907 CHECK_SEQUENCE_NOT_CLOSED(self)
4909 MYDB_BEGIN_ALLOW_THREADS
4910 err = self->sequence->set_flags(self->sequence, flags);
4911 MYDB_END_ALLOW_THREADS
4913 RETURN_IF_ERR();
4914 RETURN_NONE();
4918 static PyObject*
4919 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4921 unsigned int flags;
4922 int err;
4923 if (!PyArg_ParseTuple(args,":get_flags"))
4924 return NULL;
4925 CHECK_SEQUENCE_NOT_CLOSED(self)
4927 MYDB_BEGIN_ALLOW_THREADS
4928 err = self->sequence->get_flags(self->sequence, &flags);
4929 MYDB_END_ALLOW_THREADS
4931 RETURN_IF_ERR();
4932 return PyInt_FromLong((int)flags);
4935 static PyObject*
4936 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
4938 int err;
4939 db_seq_t min, max;
4940 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
4941 return NULL;
4942 CHECK_SEQUENCE_NOT_CLOSED(self)
4944 MYDB_BEGIN_ALLOW_THREADS
4945 err = self->sequence->set_range(self->sequence, min, max);
4946 MYDB_END_ALLOW_THREADS
4948 RETURN_IF_ERR();
4949 RETURN_NONE();
4952 static PyObject*
4953 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
4955 int err;
4956 db_seq_t min, max;
4957 if (!PyArg_ParseTuple(args,":get_range"))
4958 return NULL;
4959 CHECK_SEQUENCE_NOT_CLOSED(self)
4961 MYDB_BEGIN_ALLOW_THREADS
4962 err = self->sequence->get_range(self->sequence, &min, &max);
4963 MYDB_END_ALLOW_THREADS
4965 RETURN_IF_ERR();
4966 return Py_BuildValue("(LL)", min, max);
4969 static PyObject*
4970 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4972 int err, flags = 0;
4973 DB_SEQUENCE_STAT* sp = NULL;
4974 PyObject* dict_stat;
4975 static char* kwnames[] = {"flags", NULL };
4976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
4977 return NULL;
4978 CHECK_SEQUENCE_NOT_CLOSED(self);
4980 MYDB_BEGIN_ALLOW_THREADS;
4981 err = self->sequence->stat(self->sequence, &sp, flags);
4982 MYDB_END_ALLOW_THREADS;
4983 RETURN_IF_ERR();
4985 if ((dict_stat = PyDict_New()) == NULL) {
4986 free(sp);
4987 return NULL;
4991 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4992 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4994 MAKE_INT_ENTRY(wait);
4995 MAKE_INT_ENTRY(nowait);
4996 MAKE_LONG_LONG_ENTRY(current);
4997 MAKE_LONG_LONG_ENTRY(value);
4998 MAKE_LONG_LONG_ENTRY(last_value);
4999 MAKE_LONG_LONG_ENTRY(min);
5000 MAKE_LONG_LONG_ENTRY(max);
5001 MAKE_INT_ENTRY(cache_size);
5002 MAKE_INT_ENTRY(flags);
5004 #undef MAKE_INT_ENTRY
5005 #undef MAKE_LONG_LONG_ENTRY
5007 free(sp);
5008 return dict_stat;
5010 #endif
5013 /* --------------------------------------------------------------------- */
5014 /* Method definition tables and type objects */
5016 static PyMethodDef DB_methods[] = {
5017 {"append", (PyCFunction)DB_append, METH_VARARGS},
5018 #if (DBVER >= 33)
5019 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5020 #endif
5021 {"close", (PyCFunction)DB_close, METH_VARARGS},
5022 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5023 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5024 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5025 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5026 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5027 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5028 #if (DBVER >= 33)
5029 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5030 #endif
5031 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5032 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5033 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5034 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5035 {"join", (PyCFunction)DB_join, METH_VARARGS},
5036 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5037 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5038 {"items", (PyCFunction)DB_items, METH_VARARGS},
5039 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5040 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5041 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5042 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5043 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5044 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5045 #if (DBVER >= 33)
5046 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5047 #endif
5048 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5049 #if (DBVER >= 41)
5050 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5051 #endif
5052 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5053 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5054 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5055 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5056 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5057 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5058 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5059 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5060 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5061 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5062 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5063 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5064 #if (DBVER >= 33)
5065 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5066 #endif
5067 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5068 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5069 {"values", (PyCFunction)DB_values, METH_VARARGS},
5070 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5071 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5072 {NULL, NULL} /* sentinel */
5076 static PyMappingMethods DB_mapping = {
5077 DB_length, /*mp_length*/
5078 (binaryfunc)DB_subscript, /*mp_subscript*/
5079 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5083 static PyMethodDef DBCursor_methods[] = {
5084 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5085 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5086 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5087 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5088 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5089 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5090 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5091 #if (DBVER >= 33)
5092 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5093 #endif
5094 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5095 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5096 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5097 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5098 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5099 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5100 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5101 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5102 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5103 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5104 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5105 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5106 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5107 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5108 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5109 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5110 {NULL, NULL} /* sentinel */
5114 static PyMethodDef DBEnv_methods[] = {
5115 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5116 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5117 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5118 #if (DBVER >= 41)
5119 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5120 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5121 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5122 #endif
5123 #if (DBVER >= 40)
5124 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5125 #endif
5126 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5127 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5128 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5129 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5130 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5131 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5132 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5133 #if (DBVER >= 33)
5134 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5135 #endif
5136 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5137 #if (DBVER < 45)
5138 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5139 #endif
5140 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5141 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5142 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5143 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5144 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5145 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5146 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5147 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5148 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5149 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5150 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5151 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5152 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5153 #if (DBVER >= 40)
5154 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
5155 #endif
5156 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5157 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5158 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5159 #if (DBVER >= 40)
5160 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5161 #endif
5162 #if (DBVER >= 44)
5163 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5164 #endif
5165 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5166 {NULL, NULL} /* sentinel */
5170 static PyMethodDef DBTxn_methods[] = {
5171 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5172 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5173 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5174 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5175 {NULL, NULL} /* sentinel */
5179 #if (DBVER >= 43)
5180 static PyMethodDef DBSequence_methods[] = {
5181 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5182 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5183 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5184 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5185 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5186 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5187 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5188 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5189 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5190 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5191 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5192 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5193 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5194 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5195 {NULL, NULL} /* sentinel */
5197 #endif
5200 static PyObject*
5201 DB_getattr(DBObject* self, char *name)
5203 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5207 static PyObject*
5208 DBEnv_getattr(DBEnvObject* self, char *name)
5210 if (!strcmp(name, "db_home")) {
5211 CHECK_ENV_NOT_CLOSED(self);
5212 if (self->db_env->db_home == NULL) {
5213 RETURN_NONE();
5215 return PyString_FromString(self->db_env->db_home);
5218 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5222 static PyObject*
5223 DBCursor_getattr(DBCursorObject* self, char *name)
5225 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5228 static PyObject*
5229 DBTxn_getattr(DBTxnObject* self, char *name)
5231 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5234 static PyObject*
5235 DBLock_getattr(DBLockObject* self, char *name)
5237 return NULL;
5240 #if (DBVER >= 43)
5241 static PyObject*
5242 DBSequence_getattr(DBSequenceObject* self, char *name)
5244 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5246 #endif
5248 statichere PyTypeObject DB_Type = {
5249 PyObject_HEAD_INIT(NULL)
5250 0, /*ob_size*/
5251 "DB", /*tp_name*/
5252 sizeof(DBObject), /*tp_basicsize*/
5253 0, /*tp_itemsize*/
5254 /* methods */
5255 (destructor)DB_dealloc, /*tp_dealloc*/
5256 0, /*tp_print*/
5257 (getattrfunc)DB_getattr, /*tp_getattr*/
5258 0, /*tp_setattr*/
5259 0, /*tp_compare*/
5260 0, /*tp_repr*/
5261 0, /*tp_as_number*/
5262 0, /*tp_as_sequence*/
5263 &DB_mapping,/*tp_as_mapping*/
5264 0, /*tp_hash*/
5265 0, /* tp_call */
5266 0, /* tp_str */
5267 0, /* tp_getattro */
5268 0, /* tp_setattro */
5269 0, /* tp_as_buffer */
5270 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5271 0, /* tp_doc */
5272 0, /* tp_traverse */
5273 0, /* tp_clear */
5274 0, /* tp_richcompare */
5275 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5279 statichere PyTypeObject DBCursor_Type = {
5280 PyObject_HEAD_INIT(NULL)
5281 0, /*ob_size*/
5282 "DBCursor", /*tp_name*/
5283 sizeof(DBCursorObject), /*tp_basicsize*/
5284 0, /*tp_itemsize*/
5285 /* methods */
5286 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5287 0, /*tp_print*/
5288 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5289 0, /*tp_setattr*/
5290 0, /*tp_compare*/
5291 0, /*tp_repr*/
5292 0, /*tp_as_number*/
5293 0, /*tp_as_sequence*/
5294 0, /*tp_as_mapping*/
5295 0, /*tp_hash*/
5296 0, /* tp_call */
5297 0, /* tp_str */
5298 0, /* tp_getattro */
5299 0, /* tp_setattro */
5300 0, /* tp_as_buffer */
5301 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5302 0, /* tp_doc */
5303 0, /* tp_traverse */
5304 0, /* tp_clear */
5305 0, /* tp_richcompare */
5306 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5310 statichere PyTypeObject DBEnv_Type = {
5311 PyObject_HEAD_INIT(NULL)
5312 0, /*ob_size*/
5313 "DBEnv", /*tp_name*/
5314 sizeof(DBEnvObject), /*tp_basicsize*/
5315 0, /*tp_itemsize*/
5316 /* methods */
5317 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5318 0, /*tp_print*/
5319 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5320 0, /*tp_setattr*/
5321 0, /*tp_compare*/
5322 0, /*tp_repr*/
5323 0, /*tp_as_number*/
5324 0, /*tp_as_sequence*/
5325 0, /*tp_as_mapping*/
5326 0, /*tp_hash*/
5327 0, /* tp_call */
5328 0, /* tp_str */
5329 0, /* tp_getattro */
5330 0, /* tp_setattro */
5331 0, /* tp_as_buffer */
5332 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5333 0, /* tp_doc */
5334 0, /* tp_traverse */
5335 0, /* tp_clear */
5336 0, /* tp_richcompare */
5337 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5340 statichere PyTypeObject DBTxn_Type = {
5341 PyObject_HEAD_INIT(NULL)
5342 0, /*ob_size*/
5343 "DBTxn", /*tp_name*/
5344 sizeof(DBTxnObject), /*tp_basicsize*/
5345 0, /*tp_itemsize*/
5346 /* methods */
5347 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5348 0, /*tp_print*/
5349 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5350 0, /*tp_setattr*/
5351 0, /*tp_compare*/
5352 0, /*tp_repr*/
5353 0, /*tp_as_number*/
5354 0, /*tp_as_sequence*/
5355 0, /*tp_as_mapping*/
5356 0, /*tp_hash*/
5357 0, /* tp_call */
5358 0, /* tp_str */
5359 0, /* tp_getattro */
5360 0, /* tp_setattro */
5361 0, /* tp_as_buffer */
5362 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5363 0, /* tp_doc */
5364 0, /* tp_traverse */
5365 0, /* tp_clear */
5366 0, /* tp_richcompare */
5367 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5371 statichere PyTypeObject DBLock_Type = {
5372 PyObject_HEAD_INIT(NULL)
5373 0, /*ob_size*/
5374 "DBLock", /*tp_name*/
5375 sizeof(DBLockObject), /*tp_basicsize*/
5376 0, /*tp_itemsize*/
5377 /* methods */
5378 (destructor)DBLock_dealloc, /*tp_dealloc*/
5379 0, /*tp_print*/
5380 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5381 0, /*tp_setattr*/
5382 0, /*tp_compare*/
5383 0, /*tp_repr*/
5384 0, /*tp_as_number*/
5385 0, /*tp_as_sequence*/
5386 0, /*tp_as_mapping*/
5387 0, /*tp_hash*/
5388 0, /* tp_call */
5389 0, /* tp_str */
5390 0, /* tp_getattro */
5391 0, /* tp_setattro */
5392 0, /* tp_as_buffer */
5393 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5394 0, /* tp_doc */
5395 0, /* tp_traverse */
5396 0, /* tp_clear */
5397 0, /* tp_richcompare */
5398 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5401 #if (DBVER >= 43)
5402 statichere PyTypeObject DBSequence_Type = {
5403 PyObject_HEAD_INIT(NULL)
5404 0, /*ob_size*/
5405 "DBSequence", /*tp_name*/
5406 sizeof(DBSequenceObject), /*tp_basicsize*/
5407 0, /*tp_itemsize*/
5408 /* methods */
5409 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5410 0, /*tp_print*/
5411 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5412 0, /*tp_setattr*/
5413 0, /*tp_compare*/
5414 0, /*tp_repr*/
5415 0, /*tp_as_number*/
5416 0, /*tp_as_sequence*/
5417 0, /*tp_as_mapping*/
5418 0, /*tp_hash*/
5419 0, /* tp_call */
5420 0, /* tp_str */
5421 0, /* tp_getattro */
5422 0, /* tp_setattro */
5423 0, /* tp_as_buffer */
5424 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5425 0, /* tp_doc */
5426 0, /* tp_traverse */
5427 0, /* tp_clear */
5428 0, /* tp_richcompare */
5429 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5431 #endif
5433 /* --------------------------------------------------------------------- */
5434 /* Module-level functions */
5436 static PyObject*
5437 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5439 PyObject* dbenvobj = NULL;
5440 int flags = 0;
5441 static char* kwnames[] = { "dbEnv", "flags", NULL};
5443 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5444 &dbenvobj, &flags))
5445 return NULL;
5446 if (dbenvobj == Py_None)
5447 dbenvobj = NULL;
5448 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5449 makeTypeError("DBEnv", dbenvobj);
5450 return NULL;
5453 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5457 static PyObject*
5458 DBEnv_construct(PyObject* self, PyObject* args)
5460 int flags = 0;
5461 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5462 return (PyObject* )newDBEnvObject(flags);
5465 #if (DBVER >= 43)
5466 static PyObject*
5467 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5469 PyObject* dbobj;
5470 int flags = 0;
5471 static char* kwnames[] = { "db", "flags", NULL};
5473 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5474 return NULL;
5475 if (!DBObject_Check(dbobj)) {
5476 makeTypeError("DB", dbobj);
5477 return NULL;
5479 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5481 #endif
5483 static char bsddb_version_doc[] =
5484 "Returns a tuple of major, minor, and patch release numbers of the\n\
5485 underlying DB library.";
5487 static PyObject*
5488 bsddb_version(PyObject* self, PyObject* args)
5490 int major, minor, patch;
5492 if (!PyArg_ParseTuple(args, ":version"))
5493 return NULL;
5494 db_version(&major, &minor, &patch);
5495 return Py_BuildValue("(iii)", major, minor, patch);
5499 /* List of functions defined in the module */
5501 static PyMethodDef bsddb_methods[] = {
5502 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5503 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5504 #if (DBVER >= 43)
5505 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5506 #endif
5507 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5508 {NULL, NULL} /* sentinel */
5511 /* API structure */
5512 static BSDDB_api bsddb_api;
5515 /* --------------------------------------------------------------------- */
5516 /* Module initialization */
5519 /* Convenience routine to export an integer value.
5520 * Errors are silently ignored, for better or for worse...
5522 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5524 #define MODULE_NAME_MAX_LEN 11
5525 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5527 DL_EXPORT(void) init_bsddb(void)
5529 PyObject* m;
5530 PyObject* d;
5531 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5532 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5533 PyObject* cvsid_s = PyString_FromString( rcs_id );
5534 PyObject* py_api;
5536 /* Initialize the type of the new type objects here; doing it here
5537 is required for portability to Windows without requiring C++. */
5538 Py_TYPE(&DB_Type) = &PyType_Type;
5539 Py_TYPE(&DBCursor_Type) = &PyType_Type;
5540 Py_TYPE(&DBEnv_Type) = &PyType_Type;
5541 Py_TYPE(&DBTxn_Type) = &PyType_Type;
5542 Py_TYPE(&DBLock_Type) = &PyType_Type;
5543 #if (DBVER >= 43)
5544 Py_TYPE(&DBSequence_Type) = &PyType_Type;
5545 #endif
5548 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5549 /* Save the current interpreter, so callbacks can do the right thing. */
5550 _db_interpreterState = PyThreadState_GET()->interp;
5551 #endif
5553 /* Create the module and add the functions */
5554 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5555 if (m == NULL)
5556 return;
5558 /* Add some symbolic constants to the module */
5559 d = PyModule_GetDict(m);
5560 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5561 PyDict_SetItemString(d, "cvsid", cvsid_s);
5562 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5563 Py_DECREF(pybsddb_version_s);
5564 pybsddb_version_s = NULL;
5565 Py_DECREF(cvsid_s);
5566 cvsid_s = NULL;
5567 Py_DECREF(db_version_s);
5568 db_version_s = NULL;
5570 ADD_INT(d, DB_VERSION_MAJOR);
5571 ADD_INT(d, DB_VERSION_MINOR);
5572 ADD_INT(d, DB_VERSION_PATCH);
5574 ADD_INT(d, DB_MAX_PAGES);
5575 ADD_INT(d, DB_MAX_RECORDS);
5577 #if (DBVER >= 42)
5578 ADD_INT(d, DB_RPCCLIENT);
5579 #else
5580 ADD_INT(d, DB_CLIENT);
5581 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5582 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5583 #endif
5584 ADD_INT(d, DB_XA_CREATE);
5586 ADD_INT(d, DB_CREATE);
5587 ADD_INT(d, DB_NOMMAP);
5588 ADD_INT(d, DB_THREAD);
5590 ADD_INT(d, DB_FORCE);
5591 ADD_INT(d, DB_INIT_CDB);
5592 ADD_INT(d, DB_INIT_LOCK);
5593 ADD_INT(d, DB_INIT_LOG);
5594 ADD_INT(d, DB_INIT_MPOOL);
5595 ADD_INT(d, DB_INIT_TXN);
5596 ADD_INT(d, DB_JOINENV);
5598 ADD_INT(d, DB_RECOVER);
5599 ADD_INT(d, DB_RECOVER_FATAL);
5600 ADD_INT(d, DB_TXN_NOSYNC);
5601 ADD_INT(d, DB_USE_ENVIRON);
5602 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5604 ADD_INT(d, DB_LOCKDOWN);
5605 ADD_INT(d, DB_PRIVATE);
5606 ADD_INT(d, DB_SYSTEM_MEM);
5608 ADD_INT(d, DB_TXN_SYNC);
5609 ADD_INT(d, DB_TXN_NOWAIT);
5611 ADD_INT(d, DB_EXCL);
5612 ADD_INT(d, DB_FCNTL_LOCKING);
5613 ADD_INT(d, DB_ODDFILESIZE);
5614 ADD_INT(d, DB_RDWRMASTER);
5615 ADD_INT(d, DB_RDONLY);
5616 ADD_INT(d, DB_TRUNCATE);
5617 ADD_INT(d, DB_EXTENT);
5618 ADD_INT(d, DB_CDB_ALLDB);
5619 ADD_INT(d, DB_VERIFY);
5620 ADD_INT(d, DB_UPGRADE);
5622 ADD_INT(d, DB_AGGRESSIVE);
5623 ADD_INT(d, DB_NOORDERCHK);
5624 ADD_INT(d, DB_ORDERCHKONLY);
5625 ADD_INT(d, DB_PR_PAGE);
5626 #if ! (DBVER >= 33)
5627 ADD_INT(d, DB_VRFY_FLAGMASK);
5628 ADD_INT(d, DB_PR_HEADERS);
5629 #endif
5630 ADD_INT(d, DB_PR_RECOVERYTEST);
5631 ADD_INT(d, DB_SALVAGE);
5633 ADD_INT(d, DB_LOCK_NORUN);
5634 ADD_INT(d, DB_LOCK_DEFAULT);
5635 ADD_INT(d, DB_LOCK_OLDEST);
5636 ADD_INT(d, DB_LOCK_RANDOM);
5637 ADD_INT(d, DB_LOCK_YOUNGEST);
5638 #if (DBVER >= 33)
5639 ADD_INT(d, DB_LOCK_MAXLOCKS);
5640 ADD_INT(d, DB_LOCK_MINLOCKS);
5641 ADD_INT(d, DB_LOCK_MINWRITE);
5642 #endif
5645 #if (DBVER >= 33)
5646 /* docs say to use zero instead */
5647 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5648 #else
5649 ADD_INT(d, DB_LOCK_CONFLICT);
5650 #endif
5652 ADD_INT(d, DB_LOCK_DUMP);
5653 ADD_INT(d, DB_LOCK_GET);
5654 ADD_INT(d, DB_LOCK_INHERIT);
5655 ADD_INT(d, DB_LOCK_PUT);
5656 ADD_INT(d, DB_LOCK_PUT_ALL);
5657 ADD_INT(d, DB_LOCK_PUT_OBJ);
5659 ADD_INT(d, DB_LOCK_NG);
5660 ADD_INT(d, DB_LOCK_READ);
5661 ADD_INT(d, DB_LOCK_WRITE);
5662 ADD_INT(d, DB_LOCK_NOWAIT);
5663 ADD_INT(d, DB_LOCK_WAIT);
5664 ADD_INT(d, DB_LOCK_IWRITE);
5665 ADD_INT(d, DB_LOCK_IREAD);
5666 ADD_INT(d, DB_LOCK_IWR);
5667 #if (DBVER >= 33)
5668 #if (DBVER < 44)
5669 ADD_INT(d, DB_LOCK_DIRTY);
5670 #else
5671 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5672 #endif
5673 ADD_INT(d, DB_LOCK_WWRITE);
5674 #endif
5676 ADD_INT(d, DB_LOCK_RECORD);
5677 ADD_INT(d, DB_LOCK_UPGRADE);
5678 ADD_INT(d, DB_LOCK_SWITCH);
5679 #if (DBVER >= 33)
5680 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5681 #endif
5683 ADD_INT(d, DB_LOCK_NOWAIT);
5684 ADD_INT(d, DB_LOCK_RECORD);
5685 ADD_INT(d, DB_LOCK_UPGRADE);
5687 #if (DBVER >= 33)
5688 ADD_INT(d, DB_LSTAT_ABORTED);
5689 #if (DBVER < 43)
5690 ADD_INT(d, DB_LSTAT_ERR);
5691 #endif
5692 ADD_INT(d, DB_LSTAT_FREE);
5693 ADD_INT(d, DB_LSTAT_HELD);
5694 #if (DBVER == 33)
5695 ADD_INT(d, DB_LSTAT_NOGRANT);
5696 #endif
5697 ADD_INT(d, DB_LSTAT_PENDING);
5698 ADD_INT(d, DB_LSTAT_WAITING);
5699 #endif
5701 ADD_INT(d, DB_ARCH_ABS);
5702 ADD_INT(d, DB_ARCH_DATA);
5703 ADD_INT(d, DB_ARCH_LOG);
5704 #if (DBVER >= 42)
5705 ADD_INT(d, DB_ARCH_REMOVE);
5706 #endif
5708 ADD_INT(d, DB_BTREE);
5709 ADD_INT(d, DB_HASH);
5710 ADD_INT(d, DB_RECNO);
5711 ADD_INT(d, DB_QUEUE);
5712 ADD_INT(d, DB_UNKNOWN);
5714 ADD_INT(d, DB_DUP);
5715 ADD_INT(d, DB_DUPSORT);
5716 ADD_INT(d, DB_RECNUM);
5717 ADD_INT(d, DB_RENUMBER);
5718 ADD_INT(d, DB_REVSPLITOFF);
5719 ADD_INT(d, DB_SNAPSHOT);
5721 ADD_INT(d, DB_JOIN_NOSORT);
5723 ADD_INT(d, DB_AFTER);
5724 ADD_INT(d, DB_APPEND);
5725 ADD_INT(d, DB_BEFORE);
5726 #if (DBVER < 45)
5727 ADD_INT(d, DB_CACHED_COUNTS);
5728 #endif
5729 #if (DBVER >= 41)
5730 _addIntToDict(d, "DB_CHECKPOINT", 0);
5731 #else
5732 ADD_INT(d, DB_CHECKPOINT);
5733 ADD_INT(d, DB_CURLSN);
5734 #endif
5735 #if ((DBVER >= 33) && (DBVER <= 41))
5736 ADD_INT(d, DB_COMMIT);
5737 #endif
5738 ADD_INT(d, DB_CONSUME);
5739 ADD_INT(d, DB_CONSUME_WAIT);
5740 ADD_INT(d, DB_CURRENT);
5741 #if (DBVER >= 33)
5742 ADD_INT(d, DB_FAST_STAT);
5743 #endif
5744 ADD_INT(d, DB_FIRST);
5745 ADD_INT(d, DB_FLUSH);
5746 ADD_INT(d, DB_GET_BOTH);
5747 ADD_INT(d, DB_GET_RECNO);
5748 ADD_INT(d, DB_JOIN_ITEM);
5749 ADD_INT(d, DB_KEYFIRST);
5750 ADD_INT(d, DB_KEYLAST);
5751 ADD_INT(d, DB_LAST);
5752 ADD_INT(d, DB_NEXT);
5753 ADD_INT(d, DB_NEXT_DUP);
5754 ADD_INT(d, DB_NEXT_NODUP);
5755 ADD_INT(d, DB_NODUPDATA);
5756 ADD_INT(d, DB_NOOVERWRITE);
5757 ADD_INT(d, DB_NOSYNC);
5758 ADD_INT(d, DB_POSITION);
5759 ADD_INT(d, DB_PREV);
5760 ADD_INT(d, DB_PREV_NODUP);
5761 #if (DBVER < 45)
5762 ADD_INT(d, DB_RECORDCOUNT);
5763 #endif
5764 ADD_INT(d, DB_SET);
5765 ADD_INT(d, DB_SET_RANGE);
5766 ADD_INT(d, DB_SET_RECNO);
5767 ADD_INT(d, DB_WRITECURSOR);
5769 ADD_INT(d, DB_OPFLAGS_MASK);
5770 ADD_INT(d, DB_RMW);
5771 #if (DBVER >= 33)
5772 ADD_INT(d, DB_DIRTY_READ);
5773 ADD_INT(d, DB_MULTIPLE);
5774 ADD_INT(d, DB_MULTIPLE_KEY);
5775 #endif
5777 #if (DBVER >= 44)
5778 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5779 ADD_INT(d, DB_READ_COMMITTED);
5780 #endif
5782 #if (DBVER >= 33)
5783 ADD_INT(d, DB_DONOTINDEX);
5784 #endif
5786 #if (DBVER >= 41)
5787 _addIntToDict(d, "DB_INCOMPLETE", 0);
5788 #else
5789 ADD_INT(d, DB_INCOMPLETE);
5790 #endif
5791 ADD_INT(d, DB_KEYEMPTY);
5792 ADD_INT(d, DB_KEYEXIST);
5793 ADD_INT(d, DB_LOCK_DEADLOCK);
5794 ADD_INT(d, DB_LOCK_NOTGRANTED);
5795 ADD_INT(d, DB_NOSERVER);
5796 ADD_INT(d, DB_NOSERVER_HOME);
5797 ADD_INT(d, DB_NOSERVER_ID);
5798 ADD_INT(d, DB_NOTFOUND);
5799 ADD_INT(d, DB_OLD_VERSION);
5800 ADD_INT(d, DB_RUNRECOVERY);
5801 ADD_INT(d, DB_VERIFY_BAD);
5802 #if (DBVER >= 33)
5803 ADD_INT(d, DB_PAGE_NOTFOUND);
5804 ADD_INT(d, DB_SECONDARY_BAD);
5805 #endif
5806 #if (DBVER >= 40)
5807 ADD_INT(d, DB_STAT_CLEAR);
5808 ADD_INT(d, DB_REGION_INIT);
5809 ADD_INT(d, DB_NOLOCKING);
5810 ADD_INT(d, DB_YIELDCPU);
5811 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5812 ADD_INT(d, DB_NOPANIC);
5813 #endif
5815 #ifdef DB_REGISTER
5816 ADD_INT(d, DB_REGISTER);
5817 #endif
5819 #if (DBVER >= 42)
5820 ADD_INT(d, DB_TIME_NOTGRANTED);
5821 ADD_INT(d, DB_TXN_NOT_DURABLE);
5822 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5823 ADD_INT(d, DB_LOG_AUTOREMOVE);
5824 ADD_INT(d, DB_DIRECT_LOG);
5825 ADD_INT(d, DB_DIRECT_DB);
5826 ADD_INT(d, DB_INIT_REP);
5827 ADD_INT(d, DB_ENCRYPT);
5828 ADD_INT(d, DB_CHKSUM);
5829 #endif
5831 #if (DBVER >= 43)
5832 ADD_INT(d, DB_LOG_INMEMORY);
5833 ADD_INT(d, DB_BUFFER_SMALL);
5834 ADD_INT(d, DB_SEQ_DEC);
5835 ADD_INT(d, DB_SEQ_INC);
5836 ADD_INT(d, DB_SEQ_WRAP);
5837 #endif
5839 #if (DBVER >= 41)
5840 ADD_INT(d, DB_ENCRYPT_AES);
5841 ADD_INT(d, DB_AUTO_COMMIT);
5842 #else
5843 /* allow berkeleydb 4.1 aware apps to run on older versions */
5844 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5845 #endif
5847 ADD_INT(d, EINVAL);
5848 ADD_INT(d, EACCES);
5849 ADD_INT(d, ENOSPC);
5850 ADD_INT(d, ENOMEM);
5851 ADD_INT(d, EAGAIN);
5852 ADD_INT(d, EBUSY);
5853 ADD_INT(d, EEXIST);
5854 ADD_INT(d, ENOENT);
5855 ADD_INT(d, EPERM);
5857 #if (DBVER >= 40)
5858 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5859 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5860 #endif
5862 /* The exception name must be correct for pickled exception *
5863 * objects to unpickle properly. */
5864 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5865 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5866 #else
5867 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5868 #endif
5870 /* All the rest of the exceptions derive only from DBError */
5871 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5872 PyDict_SetItemString(d, #name, name)
5874 /* The base exception class is DBError */
5875 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5876 MAKE_EX(DBError);
5878 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5879 * from both DBError and KeyError, since the API only supports
5880 * using one base class. */
5881 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5882 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5883 "class DBKeyEmptyError(DBError, KeyError): pass",
5884 Py_file_input, d, d);
5885 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5886 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5887 PyDict_DelItemString(d, "KeyError");
5890 #if !INCOMPLETE_IS_WARNING
5891 MAKE_EX(DBIncompleteError);
5892 #endif
5893 MAKE_EX(DBCursorClosedError);
5894 MAKE_EX(DBKeyEmptyError);
5895 MAKE_EX(DBKeyExistError);
5896 MAKE_EX(DBLockDeadlockError);
5897 MAKE_EX(DBLockNotGrantedError);
5898 MAKE_EX(DBOldVersionError);
5899 MAKE_EX(DBRunRecoveryError);
5900 MAKE_EX(DBVerifyBadError);
5901 MAKE_EX(DBNoServerError);
5902 MAKE_EX(DBNoServerHomeError);
5903 MAKE_EX(DBNoServerIDError);
5904 #if (DBVER >= 33)
5905 MAKE_EX(DBPageNotFoundError);
5906 MAKE_EX(DBSecondaryBadError);
5907 #endif
5909 MAKE_EX(DBInvalidArgError);
5910 MAKE_EX(DBAccessError);
5911 MAKE_EX(DBNoSpaceError);
5912 MAKE_EX(DBNoMemoryError);
5913 MAKE_EX(DBAgainError);
5914 MAKE_EX(DBBusyError);
5915 MAKE_EX(DBFileExistsError);
5916 MAKE_EX(DBNoSuchFileError);
5917 MAKE_EX(DBPermissionsError);
5919 #undef MAKE_EX
5921 /* Initiliase the C API structure and add it to the module */
5922 bsddb_api.db_type = &DB_Type;
5923 bsddb_api.dbcursor_type = &DBCursor_Type;
5924 bsddb_api.dbenv_type = &DBEnv_Type;
5925 bsddb_api.dbtxn_type = &DBTxn_Type;
5926 bsddb_api.dblock_type = &DBLock_Type;
5927 #if (DBVER >= 43)
5928 bsddb_api.dbsequence_type = &DBSequence_Type;
5929 #endif
5930 bsddb_api.makeDBError = makeDBError;
5932 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
5933 PyDict_SetItemString(d, "api", py_api);
5934 Py_DECREF(py_api);
5936 /* Check for errors */
5937 if (PyErr_Occurred()) {
5938 PyErr_Print();
5939 Py_FatalError("can't initialize module _bsddb");
5943 /* allow this module to be named _pybsddb so that it can be installed
5944 * and imported on top of python >= 2.3 that includes its own older
5945 * copy of the library named _bsddb without importing the old version. */
5946 DL_EXPORT(void) init_pybsddb(void)
5948 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
5949 init_bsddb();