Updated documentation for findCaller() to indicate that a 3-tuple is now returned...
[python.git] / Modules / _bsddb.c
blobe6046e723109dbfed349422358dcc4ea9731be5a
1 /*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
17 o Neither the name of Digital Creations nor the names of its
18 contributors may be used to endorse or promote products derived
19 from this software without specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33 ------------------------------------------------------------------------*/
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
38 * written to replace a SWIG-generated file. It has since been updated
39 * to compile with BerkeleyDB versions 3.2 through 4.2.
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith <greg@electricrain.com> who
43 * based his work on a similar package by Robin Dunn <robin@alldunn.com>
44 * which wrapped Berkeley DB 2.7.x.
46 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
51 * Gregory P. Smith <greg@electricrain.com> is once again the maintainer.
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
54 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
57 * http://pybsddb.sf.net
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
62 * http://www.python.org/peps/pep-0291.html
64 * This module contains 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>
90 #include <db.h>
92 /* --------------------------------------------------------------------- */
93 /* Various macro definitions */
95 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
96 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
97 #if DB_VERSION_MINOR > 9
98 #error "eek! DBVER can't handle minor versions > 9"
99 #endif
101 #define PY_BSDDB_VERSION "4.4.6"
102 static char *rcs_id = "$Id$";
105 #if (PY_VERSION_HEX < 0x02050000)
106 typedef int Py_ssize_t;
107 #endif
109 #ifdef WITH_THREAD
111 /* These are for when calling Python --> C */
112 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
113 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
115 /* For 2.3, use the PyGILState_ calls */
116 #if (PY_VERSION_HEX >= 0x02030000)
117 #define MYDB_USE_GILSTATE
118 #endif
120 /* and these are for calling C --> Python */
121 #if defined(MYDB_USE_GILSTATE)
122 #define MYDB_BEGIN_BLOCK_THREADS \
123 PyGILState_STATE __savestate = PyGILState_Ensure();
124 #define MYDB_END_BLOCK_THREADS \
125 PyGILState_Release(__savestate);
126 #else /* MYDB_USE_GILSTATE */
127 /* Pre GILState API - do it the long old way */
128 static PyInterpreterState* _db_interpreterState = NULL;
129 #define MYDB_BEGIN_BLOCK_THREADS { \
130 PyThreadState* prevState; \
131 PyThreadState* newState; \
132 PyEval_AcquireLock(); \
133 newState = PyThreadState_New(_db_interpreterState); \
134 prevState = PyThreadState_Swap(newState);
136 #define MYDB_END_BLOCK_THREADS \
137 newState = PyThreadState_Swap(prevState); \
138 PyThreadState_Clear(newState); \
139 PyEval_ReleaseLock(); \
140 PyThreadState_Delete(newState); \
142 #endif /* MYDB_USE_GILSTATE */
144 #else
145 /* Compiled without threads - avoid all this cruft */
146 #define MYDB_BEGIN_ALLOW_THREADS
147 #define MYDB_END_ALLOW_THREADS
148 #define MYDB_BEGIN_BLOCK_THREADS
149 #define MYDB_END_BLOCK_THREADS
151 #endif
153 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
154 #define INCOMPLETE_IS_WARNING 1
156 /* --------------------------------------------------------------------- */
157 /* Exceptions */
159 static PyObject* DBError; /* Base class, all others derive from this */
160 static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
161 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
162 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
163 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
164 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
165 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
166 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
167 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
168 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
169 static PyObject* DBNoServerError; /* DB_NOSERVER */
170 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
171 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
172 #if (DBVER >= 33)
173 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
174 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
175 #endif
177 #if !INCOMPLETE_IS_WARNING
178 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
179 #endif
181 static PyObject* DBInvalidArgError; /* EINVAL */
182 static PyObject* DBAccessError; /* EACCES */
183 static PyObject* DBNoSpaceError; /* ENOSPC */
184 static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
185 static PyObject* DBAgainError; /* EAGAIN */
186 static PyObject* DBBusyError; /* EBUSY */
187 static PyObject* DBFileExistsError; /* EEXIST */
188 static PyObject* DBNoSuchFileError; /* ENOENT */
189 static PyObject* DBPermissionsError; /* EPERM */
191 #if (DBVER < 43)
192 #define DB_BUFFER_SMALL ENOMEM
193 #endif
196 /* --------------------------------------------------------------------- */
197 /* Structure definitions */
199 #if PYTHON_API_VERSION >= 1010 /* python >= 2.1 support weak references */
200 #define HAVE_WEAKREF
201 #else
202 #undef HAVE_WEAKREF
203 #endif
205 /* if Python >= 2.1 better support warnings */
206 #if PYTHON_API_VERSION >= 1010
207 #define HAVE_WARNINGS
208 #else
209 #undef HAVE_WARNINGS
210 #endif
212 #if PYTHON_API_VERSION <= 1007
213 /* 1.5 compatibility */
214 #define PyObject_New PyObject_NEW
215 #define PyObject_Del PyMem_DEL
216 #endif
218 struct behaviourFlags {
219 /* What is the default behaviour when DB->get or DBCursor->get returns a
220 DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise an exception? */
221 unsigned int getReturnsNone : 1;
222 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
223 * returns a DB_NOTFOUND || DB_KEYEMPTY error? Return None or raise? */
224 unsigned int cursorSetReturnsNone : 1;
227 #define DEFAULT_GET_RETURNS_NONE 1
228 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
230 typedef struct {
231 PyObject_HEAD
232 DB_ENV* db_env;
233 u_int32_t flags; /* saved flags from open() */
234 int closed;
235 struct behaviourFlags moduleFlags;
236 #ifdef HAVE_WEAKREF
237 PyObject *in_weakreflist; /* List of weak references */
238 #endif
239 } DBEnvObject;
242 typedef struct {
243 PyObject_HEAD
244 DB* db;
245 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
246 u_int32_t flags; /* saved flags from open() */
247 u_int32_t setflags; /* saved flags from set_flags() */
248 int haveStat;
249 struct behaviourFlags moduleFlags;
250 #if (DBVER >= 33)
251 PyObject* associateCallback;
252 PyObject* btCompareCallback;
253 int primaryDBType;
254 #endif
255 #ifdef HAVE_WEAKREF
256 PyObject *in_weakreflist; /* List of weak references */
257 #endif
258 } DBObject;
261 typedef struct {
262 PyObject_HEAD
263 DBC* dbc;
264 DBObject* mydb;
265 #ifdef HAVE_WEAKREF
266 PyObject *in_weakreflist; /* List of weak references */
267 #endif
268 } DBCursorObject;
271 typedef struct {
272 PyObject_HEAD
273 DB_TXN* txn;
274 PyObject *env;
275 #ifdef HAVE_WEAKREF
276 PyObject *in_weakreflist; /* List of weak references */
277 #endif
278 } DBTxnObject;
281 typedef struct {
282 PyObject_HEAD
283 DB_LOCK lock;
284 #ifdef HAVE_WEAKREF
285 PyObject *in_weakreflist; /* List of weak references */
286 #endif
287 } DBLockObject;
289 #if (DBVER >= 43)
290 typedef struct {
291 PyObject_HEAD
292 DB_SEQUENCE* sequence;
293 DBObject* mydb;
294 #ifdef HAVE_WEAKREF
295 PyObject *in_weakreflist; /* List of weak references */
296 #endif
297 } DBSequenceObject;
298 staticforward PyTypeObject DBSequence_Type;
299 #endif
301 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
303 #define DBObject_Check(v) ((v)->ob_type == &DB_Type)
304 #define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
305 #define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
306 #define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
307 #define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
308 #if (DBVER >= 43)
309 #define DBSequenceObject_Check(v) ((v)->ob_type == &DBSequence_Type)
310 #endif
313 /* --------------------------------------------------------------------- */
314 /* Utility macros and functions */
316 #define RETURN_IF_ERR() \
317 if (makeDBError(err)) { \
318 return NULL; \
321 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
323 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
324 if ((nonNull) == NULL) { \
325 PyObject *errTuple = NULL; \
326 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
327 PyErr_SetObject((pyErrObj), errTuple); \
328 Py_DECREF(errTuple); \
329 return NULL; \
332 #define CHECK_DB_NOT_CLOSED(dbobj) \
333 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
335 #define CHECK_ENV_NOT_CLOSED(env) \
336 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
338 #define CHECK_CURSOR_NOT_CLOSED(curs) \
339 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
341 #if (DBVER >= 43)
342 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
343 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
344 #endif
346 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
347 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
349 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
351 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
352 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
355 static int makeDBError(int err);
358 /* Return the access method type of the DBObject */
359 static int _DB_get_type(DBObject* self)
361 #if (DBVER >= 33)
362 DBTYPE type;
363 int err;
364 err = self->db->get_type(self->db, &type);
365 if (makeDBError(err)) {
366 return -1;
368 return type;
369 #else
370 return self->db->get_type(self->db);
371 #endif
375 /* Create a DBT structure (containing key and data values) from Python
376 strings. Returns 1 on success, 0 on an error. */
377 static int make_dbt(PyObject* obj, DBT* dbt)
379 CLEAR_DBT(*dbt);
380 if (obj == Py_None) {
381 /* no need to do anything, the structure has already been zeroed */
383 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
384 PyErr_SetString(PyExc_TypeError,
385 "Data values must be of type string or None.");
386 return 0;
388 return 1;
392 /* Recno and Queue DBs can have integer keys. This function figures out
393 what's been given, verifies that it's allowed, and then makes the DBT.
395 Caller MUST call FREE_DBT(key) when done. */
396 static int
397 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
399 db_recno_t recno;
400 int type;
402 CLEAR_DBT(*key);
403 if (keyobj == Py_None) {
404 type = _DB_get_type(self);
405 if (type == -1)
406 return 0;
407 if (type == DB_RECNO || type == DB_QUEUE) {
408 PyErr_SetString(
409 PyExc_TypeError,
410 "None keys not allowed for Recno and Queue DB's");
411 return 0;
413 /* no need to do anything, the structure has already been zeroed */
416 else if (PyString_Check(keyobj)) {
417 /* verify access method type */
418 type = _DB_get_type(self);
419 if (type == -1)
420 return 0;
421 if (type == DB_RECNO || type == DB_QUEUE) {
422 PyErr_SetString(
423 PyExc_TypeError,
424 "String keys not allowed for Recno and Queue DB's");
425 return 0;
428 key->data = PyString_AS_STRING(keyobj);
429 key->size = PyString_GET_SIZE(keyobj);
432 else if (PyInt_Check(keyobj)) {
433 /* verify access method type */
434 type = _DB_get_type(self);
435 if (type == -1)
436 return 0;
437 if (type == DB_BTREE && pflags != NULL) {
438 /* if BTREE then an Integer key is allowed with the
439 * DB_SET_RECNO flag */
440 *pflags |= DB_SET_RECNO;
442 else if (type != DB_RECNO && type != DB_QUEUE) {
443 PyErr_SetString(
444 PyExc_TypeError,
445 "Integer keys only allowed for Recno and Queue DB's");
446 return 0;
449 /* Make a key out of the requested recno, use allocated space so DB
450 * will be able to realloc room for the real key if needed. */
451 recno = PyInt_AS_LONG(keyobj);
452 key->data = malloc(sizeof(db_recno_t));
453 if (key->data == NULL) {
454 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
455 return 0;
457 key->ulen = key->size = sizeof(db_recno_t);
458 memcpy(key->data, &recno, sizeof(db_recno_t));
459 key->flags = DB_DBT_REALLOC;
461 else {
462 PyErr_Format(PyExc_TypeError,
463 "String or Integer object expected for key, %s found",
464 keyobj->ob_type->tp_name);
465 return 0;
468 return 1;
472 /* Add partial record access to an existing DBT data struct.
473 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
474 and the data storage/retrieval will be done using dlen and doff. */
475 static int add_partial_dbt(DBT* d, int dlen, int doff) {
476 /* if neither were set we do nothing (-1 is the default value) */
477 if ((dlen == -1) && (doff == -1)) {
478 return 1;
481 if ((dlen < 0) || (doff < 0)) {
482 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
483 return 0;
486 d->flags = d->flags | DB_DBT_PARTIAL;
487 d->dlen = (unsigned int) dlen;
488 d->doff = (unsigned int) doff;
489 return 1;
492 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
493 /* TODO: make this use the native libc strlcpy() when available (BSD) */
494 unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
496 unsigned int srclen, copylen;
498 srclen = strlen(src);
499 if (n <= 0)
500 return srclen;
501 copylen = (srclen > n-1) ? n-1 : srclen;
502 /* populate dest[0] thru dest[copylen-1] */
503 memcpy(dest, src, copylen);
504 /* guarantee null termination */
505 dest[copylen] = 0;
507 return srclen;
510 /* Callback used to save away more information about errors from the DB
511 * library. */
512 static char _db_errmsg[1024];
513 #if (DBVER <= 42)
514 static void _db_errorCallback(const char* prefix, char* msg)
515 #else
516 static void _db_errorCallback(const DB_ENV *db_env,
517 const char* prefix, const char* msg)
518 #endif
520 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
524 /* make a nice exception object to raise for errors. */
525 static int makeDBError(int err)
527 char errTxt[2048]; /* really big, just in case... */
528 PyObject *errObj = NULL;
529 PyObject *errTuple = NULL;
530 int exceptionRaised = 0;
531 unsigned int bytes_left;
533 switch (err) {
534 case 0: /* successful, no error */ break;
536 #if (DBVER < 41)
537 case DB_INCOMPLETE:
538 #if INCOMPLETE_IS_WARNING
539 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
540 /* Ensure that bytes_left never goes negative */
541 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
542 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
543 assert(bytes_left >= 0);
544 strcat(errTxt, " -- ");
545 strncat(errTxt, _db_errmsg, bytes_left);
547 _db_errmsg[0] = 0;
548 #ifdef HAVE_WARNINGS
549 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
550 #else
551 fprintf(stderr, errTxt);
552 fprintf(stderr, "\n");
553 #endif
555 #else /* do an exception instead */
556 errObj = DBIncompleteError;
557 #endif
558 break;
559 #endif /* DBVER < 41 */
561 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
562 case DB_KEYEXIST: errObj = DBKeyExistError; break;
563 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
564 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
565 case DB_NOTFOUND: errObj = DBNotFoundError; break;
566 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
567 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
568 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
569 case DB_NOSERVER: errObj = DBNoServerError; break;
570 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
571 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
572 #if (DBVER >= 33)
573 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
574 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
575 #endif
576 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
578 #if (DBVER >= 43)
579 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
580 case ENOMEM: errObj = PyExc_MemoryError; break;
581 #endif
582 case EINVAL: errObj = DBInvalidArgError; break;
583 case EACCES: errObj = DBAccessError; break;
584 case ENOSPC: errObj = DBNoSpaceError; break;
585 case EAGAIN: errObj = DBAgainError; break;
586 case EBUSY : errObj = DBBusyError; break;
587 case EEXIST: errObj = DBFileExistsError; break;
588 case ENOENT: errObj = DBNoSuchFileError; break;
589 case EPERM : errObj = DBPermissionsError; break;
591 default: errObj = DBError; break;
594 if (errObj != NULL) {
595 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
596 /* Ensure that bytes_left never goes negative */
597 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
598 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
599 assert(bytes_left >= 0);
600 strcat(errTxt, " -- ");
601 strncat(errTxt, _db_errmsg, bytes_left);
603 _db_errmsg[0] = 0;
605 errTuple = Py_BuildValue("(is)", err, errTxt);
606 PyErr_SetObject(errObj, errTuple);
607 Py_DECREF(errTuple);
610 return ((errObj != NULL) || exceptionRaised);
615 /* set a type exception */
616 static void makeTypeError(char* expected, PyObject* found)
618 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
619 expected, found->ob_type->tp_name);
623 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
624 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
626 if (txnobj == Py_None || txnobj == NULL) {
627 *txn = NULL;
628 return 1;
630 if (DBTxnObject_Check(txnobj)) {
631 *txn = ((DBTxnObject*)txnobj)->txn;
632 return 1;
634 else
635 makeTypeError("DBTxn", txnobj);
636 return 0;
640 /* Delete a key from a database
641 Returns 0 on success, -1 on an error. */
642 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
644 int err;
646 MYDB_BEGIN_ALLOW_THREADS;
647 err = self->db->del(self->db, txn, key, 0);
648 MYDB_END_ALLOW_THREADS;
649 if (makeDBError(err)) {
650 return -1;
652 self->haveStat = 0;
653 return 0;
657 /* Store a key into a database
658 Returns 0 on success, -1 on an error. */
659 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
661 int err;
663 MYDB_BEGIN_ALLOW_THREADS;
664 err = self->db->put(self->db, txn, key, data, flags);
665 MYDB_END_ALLOW_THREADS;
666 if (makeDBError(err)) {
667 return -1;
669 self->haveStat = 0;
670 return 0;
673 /* Get a key/data pair from a cursor */
674 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
675 PyObject *args, PyObject *kwargs, char *format)
677 int err;
678 PyObject* retval = NULL;
679 DBT key, data;
680 int dlen = -1;
681 int doff = -1;
682 int flags = 0;
683 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
685 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
686 &flags, &dlen, &doff))
687 return NULL;
689 CHECK_CURSOR_NOT_CLOSED(self);
691 flags |= extra_flags;
692 CLEAR_DBT(key);
693 CLEAR_DBT(data);
694 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
695 /* Tell BerkeleyDB to malloc the return value (thread safe) */
696 data.flags = DB_DBT_MALLOC;
697 key.flags = DB_DBT_MALLOC;
699 if (!add_partial_dbt(&data, dlen, doff))
700 return NULL;
702 MYDB_BEGIN_ALLOW_THREADS;
703 err = self->dbc->c_get(self->dbc, &key, &data, flags);
704 MYDB_END_ALLOW_THREADS;
706 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
707 && self->mydb->moduleFlags.getReturnsNone) {
708 Py_INCREF(Py_None);
709 retval = Py_None;
711 else if (makeDBError(err)) {
712 retval = NULL;
714 else { /* otherwise, success! */
716 /* if Recno or Queue, return the key as an Int */
717 switch (_DB_get_type(self->mydb)) {
718 case -1:
719 retval = NULL;
720 break;
722 case DB_RECNO:
723 case DB_QUEUE:
724 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
725 data.data, data.size);
726 break;
727 case DB_HASH:
728 case DB_BTREE:
729 default:
730 retval = Py_BuildValue("s#s#", key.data, key.size,
731 data.data, data.size);
732 break;
735 if (!err) {
736 FREE_DBT(key);
737 FREE_DBT(data);
739 return retval;
743 /* add an integer to a dictionary using the given name as a key */
744 static void _addIntToDict(PyObject* dict, char *name, int value)
746 PyObject* v = PyInt_FromLong((long) value);
747 if (!v || PyDict_SetItemString(dict, name, v))
748 PyErr_Clear();
750 Py_XDECREF(v);
752 #if (DBVER >= 43)
753 /* add an db_seq_t to a dictionary using the given name as a key */
754 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
756 PyObject* v = PyLong_FromLongLong(value);
757 if (!v || PyDict_SetItemString(dict, name, v))
758 PyErr_Clear();
760 Py_XDECREF(v);
762 #endif
766 /* --------------------------------------------------------------------- */
767 /* Allocators and deallocators */
769 static DBObject*
770 newDBObject(DBEnvObject* arg, int flags)
772 DBObject* self;
773 DB_ENV* db_env = NULL;
774 int err;
776 self = PyObject_New(DBObject, &DB_Type);
777 if (self == NULL)
778 return NULL;
780 self->haveStat = 0;
781 self->flags = 0;
782 self->setflags = 0;
783 self->myenvobj = NULL;
784 #if (DBVER >= 33)
785 self->associateCallback = NULL;
786 self->btCompareCallback = NULL;
787 self->primaryDBType = 0;
788 #endif
789 #ifdef HAVE_WEAKREF
790 self->in_weakreflist = NULL;
791 #endif
793 /* keep a reference to our python DBEnv object */
794 if (arg) {
795 Py_INCREF(arg);
796 self->myenvobj = arg;
797 db_env = arg->db_env;
800 if (self->myenvobj)
801 self->moduleFlags = self->myenvobj->moduleFlags;
802 else
803 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
804 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
806 MYDB_BEGIN_ALLOW_THREADS;
807 err = db_create(&self->db, db_env, flags);
808 if (self->db != NULL) {
809 self->db->set_errcall(self->db, _db_errorCallback);
810 #if (DBVER >= 33)
811 self->db->app_private = (void*)self;
812 #endif
814 MYDB_END_ALLOW_THREADS;
815 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
816 * list so that a DBEnv can refuse to close without aborting any open
817 * DBTxns and closing any open DBs first. */
818 if (makeDBError(err)) {
819 if (self->myenvobj) {
820 Py_DECREF(self->myenvobj);
821 self->myenvobj = NULL;
823 PyObject_Del(self);
824 self = NULL;
826 return self;
830 static void
831 DB_dealloc(DBObject* self)
833 if (self->db != NULL) {
834 /* avoid closing a DB when its DBEnv has been closed out from under
835 * it */
836 if (!self->myenvobj ||
837 (self->myenvobj && self->myenvobj->db_env))
839 MYDB_BEGIN_ALLOW_THREADS;
840 self->db->close(self->db, 0);
841 MYDB_END_ALLOW_THREADS;
842 #ifdef HAVE_WARNINGS
843 } else {
844 PyErr_Warn(PyExc_RuntimeWarning,
845 "DB could not be closed in destructor: DBEnv already closed");
846 #endif
848 self->db = NULL;
850 #ifdef HAVE_WEAKREF
851 if (self->in_weakreflist != NULL) {
852 PyObject_ClearWeakRefs((PyObject *) self);
854 #endif
855 if (self->myenvobj) {
856 Py_DECREF(self->myenvobj);
857 self->myenvobj = NULL;
859 #if (DBVER >= 33)
860 if (self->associateCallback != NULL) {
861 Py_DECREF(self->associateCallback);
862 self->associateCallback = NULL;
864 if (self->btCompareCallback != NULL) {
865 Py_DECREF(self->btCompareCallback);
866 self->btCompareCallback = NULL;
868 #endif
869 PyObject_Del(self);
873 static DBCursorObject*
874 newDBCursorObject(DBC* dbc, DBObject* db)
876 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
877 if (self == NULL)
878 return NULL;
880 self->dbc = dbc;
881 self->mydb = db;
882 #ifdef HAVE_WEAKREF
883 self->in_weakreflist = NULL;
884 #endif
885 Py_INCREF(self->mydb);
886 return self;
890 static void
891 DBCursor_dealloc(DBCursorObject* self)
893 int err;
895 #ifdef HAVE_WEAKREF
896 if (self->in_weakreflist != NULL) {
897 PyObject_ClearWeakRefs((PyObject *) self);
899 #endif
901 if (self->dbc != NULL) {
902 MYDB_BEGIN_ALLOW_THREADS;
903 /* If the underlying database has been closed, we don't
904 need to do anything. If the environment has been closed
905 we need to leak, as BerkeleyDB will crash trying to access
906 the environment. There was an exception when the
907 user closed the environment even though there still was
908 a database open. */
909 if (self->mydb->db && self->mydb->myenvobj &&
910 !self->mydb->myenvobj->closed)
911 err = self->dbc->c_close(self->dbc);
912 self->dbc = NULL;
913 MYDB_END_ALLOW_THREADS;
915 Py_XDECREF( self->mydb );
916 PyObject_Del(self);
920 static DBEnvObject*
921 newDBEnvObject(int flags)
923 int err;
924 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
925 if (self == NULL)
926 return NULL;
928 self->closed = 1;
929 self->flags = flags;
930 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
931 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
932 #ifdef HAVE_WEAKREF
933 self->in_weakreflist = NULL;
934 #endif
936 MYDB_BEGIN_ALLOW_THREADS;
937 err = db_env_create(&self->db_env, flags);
938 MYDB_END_ALLOW_THREADS;
939 if (makeDBError(err)) {
940 PyObject_Del(self);
941 self = NULL;
943 else {
944 self->db_env->set_errcall(self->db_env, _db_errorCallback);
946 return self;
950 static void
951 DBEnv_dealloc(DBEnvObject* self)
953 #ifdef HAVE_WEAKREF
954 if (self->in_weakreflist != NULL) {
955 PyObject_ClearWeakRefs((PyObject *) self);
957 #endif
959 if (self->db_env && !self->closed) {
960 MYDB_BEGIN_ALLOW_THREADS;
961 self->db_env->close(self->db_env, 0);
962 MYDB_END_ALLOW_THREADS;
964 PyObject_Del(self);
968 static DBTxnObject*
969 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
971 int err;
972 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
973 if (self == NULL)
974 return NULL;
975 Py_INCREF(myenv);
976 self->env = (PyObject*)myenv;
977 #ifdef HAVE_WEAKREF
978 self->in_weakreflist = NULL;
979 #endif
981 MYDB_BEGIN_ALLOW_THREADS;
982 #if (DBVER >= 40)
983 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
984 #else
985 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
986 #endif
987 MYDB_END_ALLOW_THREADS;
988 if (makeDBError(err)) {
989 Py_DECREF(self->env);
990 PyObject_Del(self);
991 self = NULL;
993 return self;
997 static void
998 DBTxn_dealloc(DBTxnObject* self)
1000 #ifdef HAVE_WEAKREF
1001 if (self->in_weakreflist != NULL) {
1002 PyObject_ClearWeakRefs((PyObject *) self);
1004 #endif
1006 #ifdef HAVE_WARNINGS
1007 if (self->txn) {
1008 /* it hasn't been finalized, abort it! */
1009 MYDB_BEGIN_ALLOW_THREADS;
1010 #if (DBVER >= 40)
1011 self->txn->abort(self->txn);
1012 #else
1013 txn_abort(self->txn);
1014 #endif
1015 MYDB_END_ALLOW_THREADS;
1016 PyErr_Warn(PyExc_RuntimeWarning,
1017 "DBTxn aborted in destructor. No prior commit() or abort().");
1019 #endif
1021 Py_DECREF(self->env);
1022 PyObject_Del(self);
1026 static DBLockObject*
1027 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1028 db_lockmode_t lock_mode, int flags)
1030 int err;
1031 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1032 if (self == NULL)
1033 return NULL;
1034 #ifdef HAVE_WEAKREF
1035 self->in_weakreflist = NULL;
1036 #endif
1038 MYDB_BEGIN_ALLOW_THREADS;
1039 #if (DBVER >= 40)
1040 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1041 &self->lock);
1042 #else
1043 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1044 #endif
1045 MYDB_END_ALLOW_THREADS;
1046 if (makeDBError(err)) {
1047 PyObject_Del(self);
1048 self = NULL;
1051 return self;
1055 static void
1056 DBLock_dealloc(DBLockObject* self)
1058 #ifdef HAVE_WEAKREF
1059 if (self->in_weakreflist != NULL) {
1060 PyObject_ClearWeakRefs((PyObject *) self);
1062 #endif
1063 /* TODO: is this lock held? should we release it? */
1065 PyObject_Del(self);
1069 #if (DBVER >= 43)
1070 static DBSequenceObject*
1071 newDBSequenceObject(DBObject* mydb, int flags)
1073 int err;
1074 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1075 if (self == NULL)
1076 return NULL;
1077 Py_INCREF(mydb);
1078 self->mydb = mydb;
1079 #ifdef HAVE_WEAKREF
1080 self->in_weakreflist = NULL;
1081 #endif
1084 MYDB_BEGIN_ALLOW_THREADS;
1085 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1086 MYDB_END_ALLOW_THREADS;
1087 if (makeDBError(err)) {
1088 Py_DECREF(self->mydb);
1089 PyObject_Del(self);
1090 self = NULL;
1093 return self;
1097 static void
1098 DBSequence_dealloc(DBSequenceObject* self)
1100 #ifdef HAVE_WEAKREF
1101 if (self->in_weakreflist != NULL) {
1102 PyObject_ClearWeakRefs((PyObject *) self);
1104 #endif
1106 Py_DECREF(self->mydb);
1107 PyObject_Del(self);
1109 #endif
1111 /* --------------------------------------------------------------------- */
1112 /* DB methods */
1114 static PyObject*
1115 DB_append(DBObject* self, PyObject* args)
1117 PyObject* txnobj = NULL;
1118 PyObject* dataobj;
1119 db_recno_t recno;
1120 DBT key, data;
1121 DB_TXN *txn = NULL;
1123 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1124 return NULL;
1126 CHECK_DB_NOT_CLOSED(self);
1128 /* make a dummy key out of a recno */
1129 recno = 0;
1130 CLEAR_DBT(key);
1131 key.data = &recno;
1132 key.size = sizeof(recno);
1133 key.ulen = key.size;
1134 key.flags = DB_DBT_USERMEM;
1136 if (!make_dbt(dataobj, &data)) return NULL;
1137 if (!checkTxnObj(txnobj, &txn)) return NULL;
1139 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1140 return NULL;
1142 return PyInt_FromLong(recno);
1146 #if (DBVER >= 33)
1148 static int
1149 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1150 DBT* secKey)
1152 int retval = DB_DONOTINDEX;
1153 DBObject* secondaryDB = (DBObject*)db->app_private;
1154 PyObject* callback = secondaryDB->associateCallback;
1155 int type = secondaryDB->primaryDBType;
1156 PyObject* args;
1157 PyObject* result = NULL;
1160 if (callback != NULL) {
1161 MYDB_BEGIN_BLOCK_THREADS;
1163 if (type == DB_RECNO || type == DB_QUEUE)
1164 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1165 priData->data, priData->size);
1166 else
1167 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1168 priData->data, priData->size);
1169 if (args != NULL) {
1170 result = PyEval_CallObject(callback, args);
1172 if (args == NULL || result == NULL) {
1173 PyErr_Print();
1175 else if (result == Py_None) {
1176 retval = DB_DONOTINDEX;
1178 else if (PyInt_Check(result)) {
1179 retval = PyInt_AsLong(result);
1181 else if (PyString_Check(result)) {
1182 char* data;
1183 Py_ssize_t size;
1185 CLEAR_DBT(*secKey);
1186 #if PYTHON_API_VERSION <= 1007
1187 /* 1.5 compatibility */
1188 size = PyString_Size(result);
1189 data = PyString_AsString(result);
1190 #else
1191 PyString_AsStringAndSize(result, &data, &size);
1192 #endif
1193 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1194 secKey->data = malloc(size); /* TODO, check this */
1195 if (secKey->data) {
1196 memcpy(secKey->data, data, size);
1197 secKey->size = size;
1198 retval = 0;
1200 else {
1201 PyErr_SetString(PyExc_MemoryError,
1202 "malloc failed in _db_associateCallback");
1203 PyErr_Print();
1206 else {
1207 PyErr_SetString(
1208 PyExc_TypeError,
1209 "DB associate callback should return DB_DONOTINDEX or string.");
1210 PyErr_Print();
1213 Py_XDECREF(args);
1214 Py_XDECREF(result);
1216 MYDB_END_BLOCK_THREADS;
1218 return retval;
1222 static PyObject*
1223 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1225 int err, flags=0;
1226 DBObject* secondaryDB;
1227 PyObject* callback;
1228 #if (DBVER >= 41)
1229 PyObject *txnobj = NULL;
1230 DB_TXN *txn = NULL;
1231 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1232 NULL};
1233 #else
1234 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1235 #endif
1237 #if (DBVER >= 41)
1238 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1239 &secondaryDB, &callback, &flags,
1240 &txnobj)) {
1241 #else
1242 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1243 &secondaryDB, &callback, &flags)) {
1244 #endif
1245 return NULL;
1248 #if (DBVER >= 41)
1249 if (!checkTxnObj(txnobj, &txn)) return NULL;
1250 #endif
1252 CHECK_DB_NOT_CLOSED(self);
1253 if (!DBObject_Check(secondaryDB)) {
1254 makeTypeError("DB", (PyObject*)secondaryDB);
1255 return NULL;
1257 CHECK_DB_NOT_CLOSED(secondaryDB);
1258 if (callback == Py_None) {
1259 callback = NULL;
1261 else if (!PyCallable_Check(callback)) {
1262 makeTypeError("Callable", callback);
1263 return NULL;
1266 /* Save a reference to the callback in the secondary DB. */
1267 Py_XDECREF(secondaryDB->associateCallback);
1268 Py_XINCREF(callback);
1269 secondaryDB->associateCallback = callback;
1270 secondaryDB->primaryDBType = _DB_get_type(self);
1272 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1273 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1274 * The global interepreter lock is not initialized until the first
1275 * thread is created using thread.start_new_thread() or fork() is
1276 * called. that would cause the ALLOW_THREADS here to segfault due
1277 * to a null pointer reference if no threads or child processes
1278 * have been created. This works around that and is a no-op if
1279 * threads have already been initialized.
1280 * (see pybsddb-users mailing list post on 2002-08-07)
1282 #ifdef WITH_THREAD
1283 PyEval_InitThreads();
1284 #endif
1285 MYDB_BEGIN_ALLOW_THREADS;
1286 #if (DBVER >= 41)
1287 err = self->db->associate(self->db,
1288 txn,
1289 secondaryDB->db,
1290 _db_associateCallback,
1291 flags);
1292 #else
1293 err = self->db->associate(self->db,
1294 secondaryDB->db,
1295 _db_associateCallback,
1296 flags);
1297 #endif
1298 MYDB_END_ALLOW_THREADS;
1300 if (err) {
1301 Py_XDECREF(secondaryDB->associateCallback);
1302 secondaryDB->associateCallback = NULL;
1303 secondaryDB->primaryDBType = 0;
1306 RETURN_IF_ERR();
1307 RETURN_NONE();
1311 #endif
1314 static PyObject*
1315 DB_close(DBObject* self, PyObject* args)
1317 int err, flags=0;
1318 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1319 return NULL;
1320 if (self->db != NULL) {
1321 if (self->myenvobj)
1322 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1323 err = self->db->close(self->db, flags);
1324 self->db = NULL;
1325 RETURN_IF_ERR();
1327 RETURN_NONE();
1331 #if (DBVER >= 32)
1332 static PyObject*
1333 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1335 int err, flags=0, type;
1336 PyObject* txnobj = NULL;
1337 PyObject* retval = NULL;
1338 DBT key, data;
1339 DB_TXN *txn = NULL;
1340 static char* kwnames[] = { "txn", "flags", NULL };
1342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1343 &txnobj, &flags))
1344 return NULL;
1346 CHECK_DB_NOT_CLOSED(self);
1347 type = _DB_get_type(self);
1348 if (type == -1)
1349 return NULL;
1350 if (type != DB_QUEUE) {
1351 PyErr_SetString(PyExc_TypeError,
1352 "Consume methods only allowed for Queue DB's");
1353 return NULL;
1355 if (!checkTxnObj(txnobj, &txn))
1356 return NULL;
1358 CLEAR_DBT(key);
1359 CLEAR_DBT(data);
1360 if (CHECK_DBFLAG(self, DB_THREAD)) {
1361 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1362 data.flags = DB_DBT_MALLOC;
1363 key.flags = DB_DBT_MALLOC;
1366 MYDB_BEGIN_ALLOW_THREADS;
1367 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1368 MYDB_END_ALLOW_THREADS;
1370 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1371 && self->moduleFlags.getReturnsNone) {
1372 err = 0;
1373 Py_INCREF(Py_None);
1374 retval = Py_None;
1376 else if (!err) {
1377 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1378 data.size);
1379 FREE_DBT(key);
1380 FREE_DBT(data);
1383 RETURN_IF_ERR();
1384 return retval;
1387 static PyObject*
1388 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1390 return _DB_consume(self, args, kwargs, DB_CONSUME);
1393 static PyObject*
1394 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1395 int consume_flag)
1397 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1399 #endif
1403 static PyObject*
1404 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1406 int err, flags=0;
1407 DBC* dbc;
1408 PyObject* txnobj = NULL;
1409 DB_TXN *txn = NULL;
1410 static char* kwnames[] = { "txn", "flags", NULL };
1412 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1413 &txnobj, &flags))
1414 return NULL;
1415 CHECK_DB_NOT_CLOSED(self);
1416 if (!checkTxnObj(txnobj, &txn))
1417 return NULL;
1419 MYDB_BEGIN_ALLOW_THREADS;
1420 err = self->db->cursor(self->db, txn, &dbc, flags);
1421 MYDB_END_ALLOW_THREADS;
1422 RETURN_IF_ERR();
1423 return (PyObject*) newDBCursorObject(dbc, self);
1427 static PyObject*
1428 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1430 PyObject* txnobj = NULL;
1431 int flags = 0;
1432 PyObject* keyobj;
1433 DBT key;
1434 DB_TXN *txn = NULL;
1435 static char* kwnames[] = { "key", "txn", "flags", NULL };
1437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1438 &keyobj, &txnobj, &flags))
1439 return NULL;
1440 CHECK_DB_NOT_CLOSED(self);
1441 if (!make_key_dbt(self, keyobj, &key, NULL))
1442 return NULL;
1443 if (!checkTxnObj(txnobj, &txn)) {
1444 FREE_DBT(key);
1445 return NULL;
1448 if (-1 == _DB_delete(self, txn, &key, 0)) {
1449 FREE_DBT(key);
1450 return NULL;
1453 FREE_DBT(key);
1454 RETURN_NONE();
1458 static PyObject*
1459 DB_fd(DBObject* self, PyObject* args)
1461 int err, the_fd;
1463 if (!PyArg_ParseTuple(args,":fd"))
1464 return NULL;
1465 CHECK_DB_NOT_CLOSED(self);
1467 MYDB_BEGIN_ALLOW_THREADS;
1468 err = self->db->fd(self->db, &the_fd);
1469 MYDB_END_ALLOW_THREADS;
1470 RETURN_IF_ERR();
1471 return PyInt_FromLong(the_fd);
1475 static PyObject*
1476 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1478 int err, flags=0;
1479 PyObject* txnobj = NULL;
1480 PyObject* keyobj;
1481 PyObject* dfltobj = NULL;
1482 PyObject* retval = NULL;
1483 int dlen = -1;
1484 int doff = -1;
1485 DBT key, data;
1486 DB_TXN *txn = NULL;
1487 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1488 "doff", NULL};
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1491 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1492 &doff))
1493 return NULL;
1495 CHECK_DB_NOT_CLOSED(self);
1496 if (!make_key_dbt(self, keyobj, &key, &flags))
1497 return NULL;
1498 if (!checkTxnObj(txnobj, &txn)) {
1499 FREE_DBT(key);
1500 return NULL;
1503 CLEAR_DBT(data);
1504 if (CHECK_DBFLAG(self, DB_THREAD)) {
1505 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1506 data.flags = DB_DBT_MALLOC;
1508 if (!add_partial_dbt(&data, dlen, doff)) {
1509 FREE_DBT(key);
1510 return NULL;
1513 MYDB_BEGIN_ALLOW_THREADS;
1514 err = self->db->get(self->db, txn, &key, &data, flags);
1515 MYDB_END_ALLOW_THREADS;
1517 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1518 err = 0;
1519 Py_INCREF(dfltobj);
1520 retval = dfltobj;
1522 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1523 && self->moduleFlags.getReturnsNone) {
1524 err = 0;
1525 Py_INCREF(Py_None);
1526 retval = Py_None;
1528 else if (!err) {
1529 if (flags & DB_SET_RECNO) /* return both key and data */
1530 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1531 data.size);
1532 else /* return just the data */
1533 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1534 FREE_DBT(data);
1536 FREE_DBT(key);
1538 RETURN_IF_ERR();
1539 return retval;
1542 #if (DBVER >= 33)
1543 static PyObject*
1544 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1546 int err, flags=0;
1547 PyObject* txnobj = NULL;
1548 PyObject* keyobj;
1549 PyObject* dfltobj = NULL;
1550 PyObject* retval = NULL;
1551 int dlen = -1;
1552 int doff = -1;
1553 DBT key, pkey, data;
1554 DB_TXN *txn = NULL;
1555 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1556 "doff", NULL};
1558 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1559 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1560 &doff))
1561 return NULL;
1563 CHECK_DB_NOT_CLOSED(self);
1564 if (!make_key_dbt(self, keyobj, &key, &flags))
1565 return NULL;
1566 if (!checkTxnObj(txnobj, &txn)) {
1567 FREE_DBT(key);
1568 return NULL;
1571 CLEAR_DBT(data);
1572 if (CHECK_DBFLAG(self, DB_THREAD)) {
1573 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1574 data.flags = DB_DBT_MALLOC;
1576 if (!add_partial_dbt(&data, dlen, doff)) {
1577 FREE_DBT(key);
1578 return NULL;
1581 CLEAR_DBT(pkey);
1582 pkey.flags = DB_DBT_MALLOC;
1584 MYDB_BEGIN_ALLOW_THREADS;
1585 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1586 MYDB_END_ALLOW_THREADS;
1588 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1589 err = 0;
1590 Py_INCREF(dfltobj);
1591 retval = dfltobj;
1593 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1594 && self->moduleFlags.getReturnsNone) {
1595 err = 0;
1596 Py_INCREF(Py_None);
1597 retval = Py_None;
1599 else if (!err) {
1600 PyObject *pkeyObj;
1601 PyObject *dataObj;
1602 dataObj = PyString_FromStringAndSize(data.data, data.size);
1604 if (self->primaryDBType == DB_RECNO ||
1605 self->primaryDBType == DB_QUEUE)
1606 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1607 else
1608 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1610 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1612 PyObject *keyObj;
1613 int type = _DB_get_type(self);
1614 if (type == DB_RECNO || type == DB_QUEUE)
1615 keyObj = PyInt_FromLong(*(int *)key.data);
1616 else
1617 keyObj = PyString_FromStringAndSize(key.data, key.size);
1618 #if (PY_VERSION_HEX >= 0x02040000)
1619 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1620 #else
1621 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1622 #endif
1623 Py_DECREF(keyObj);
1625 else /* return just the pkey and data */
1627 #if (PY_VERSION_HEX >= 0x02040000)
1628 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1629 #else
1630 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1631 #endif
1633 Py_DECREF(dataObj);
1634 Py_DECREF(pkeyObj);
1635 FREE_DBT(pkey);
1636 FREE_DBT(data);
1638 FREE_DBT(key);
1640 RETURN_IF_ERR();
1641 return retval;
1643 #endif
1646 /* Return size of entry */
1647 static PyObject*
1648 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1650 int err, flags=0;
1651 PyObject* txnobj = NULL;
1652 PyObject* keyobj;
1653 PyObject* retval = NULL;
1654 DBT key, data;
1655 DB_TXN *txn = NULL;
1656 static char* kwnames[] = { "key", "txn", NULL };
1658 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1659 &keyobj, &txnobj))
1660 return NULL;
1661 CHECK_DB_NOT_CLOSED(self);
1662 if (!make_key_dbt(self, keyobj, &key, &flags))
1663 return NULL;
1664 if (!checkTxnObj(txnobj, &txn)) {
1665 FREE_DBT(key);
1666 return NULL;
1668 CLEAR_DBT(data);
1670 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1671 thus getting the record size. */
1672 data.flags = DB_DBT_USERMEM;
1673 data.ulen = 0;
1674 MYDB_BEGIN_ALLOW_THREADS;
1675 err = self->db->get(self->db, txn, &key, &data, flags);
1676 MYDB_END_ALLOW_THREADS;
1677 if (err == DB_BUFFER_SMALL) {
1678 retval = PyInt_FromLong((long)data.size);
1679 err = 0;
1682 FREE_DBT(key);
1683 FREE_DBT(data);
1684 RETURN_IF_ERR();
1685 return retval;
1689 static PyObject*
1690 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1692 int err, flags=0;
1693 PyObject* txnobj = NULL;
1694 PyObject* keyobj;
1695 PyObject* dataobj;
1696 PyObject* retval = NULL;
1697 DBT key, data;
1698 DB_TXN *txn = NULL;
1699 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1702 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1703 &keyobj, &dataobj, &txnobj, &flags))
1704 return NULL;
1706 CHECK_DB_NOT_CLOSED(self);
1707 if (!make_key_dbt(self, keyobj, &key, NULL))
1708 return NULL;
1709 if ( !make_dbt(dataobj, &data) ||
1710 !checkTxnObj(txnobj, &txn) )
1712 FREE_DBT(key);
1713 return NULL;
1716 flags |= DB_GET_BOTH;
1718 if (CHECK_DBFLAG(self, DB_THREAD)) {
1719 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1720 data.flags = DB_DBT_MALLOC;
1721 /* TODO: Is this flag needed? We're passing a data object that should
1722 match what's in the DB, so there should be no need to malloc.
1723 We run the risk of freeing something twice! Check this. */
1726 MYDB_BEGIN_ALLOW_THREADS;
1727 err = self->db->get(self->db, txn, &key, &data, flags);
1728 MYDB_END_ALLOW_THREADS;
1730 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1731 && self->moduleFlags.getReturnsNone) {
1732 err = 0;
1733 Py_INCREF(Py_None);
1734 retval = Py_None;
1736 else if (!err) {
1737 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1738 FREE_DBT(data); /* Only if retrieval was successful */
1741 FREE_DBT(key);
1742 RETURN_IF_ERR();
1743 return retval;
1747 static PyObject*
1748 DB_get_byteswapped(DBObject* self, PyObject* args)
1750 #if (DBVER >= 33)
1751 int err = 0;
1752 #endif
1753 int retval = -1;
1755 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1756 return NULL;
1757 CHECK_DB_NOT_CLOSED(self);
1759 #if (DBVER >= 33)
1760 MYDB_BEGIN_ALLOW_THREADS;
1761 err = self->db->get_byteswapped(self->db, &retval);
1762 MYDB_END_ALLOW_THREADS;
1763 RETURN_IF_ERR();
1764 #else
1765 MYDB_BEGIN_ALLOW_THREADS;
1766 retval = self->db->get_byteswapped(self->db);
1767 MYDB_END_ALLOW_THREADS;
1768 #endif
1769 return PyInt_FromLong(retval);
1773 static PyObject*
1774 DB_get_type(DBObject* self, PyObject* args)
1776 int type;
1778 if (!PyArg_ParseTuple(args,":get_type"))
1779 return NULL;
1780 CHECK_DB_NOT_CLOSED(self);
1782 type = _DB_get_type(self);
1783 if (type == -1)
1784 return NULL;
1785 return PyInt_FromLong(type);
1789 static PyObject*
1790 DB_join(DBObject* self, PyObject* args)
1792 int err, flags=0;
1793 int length, x;
1794 PyObject* cursorsObj;
1795 DBC** cursors;
1796 DBC* dbc;
1798 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1799 return NULL;
1801 CHECK_DB_NOT_CLOSED(self);
1803 if (!PySequence_Check(cursorsObj)) {
1804 PyErr_SetString(PyExc_TypeError,
1805 "Sequence of DBCursor objects expected");
1806 return NULL;
1809 length = PyObject_Length(cursorsObj);
1810 cursors = malloc((length+1) * sizeof(DBC*));
1811 if (!cursors) {
1812 PyErr_NoMemory();
1813 return NULL;
1816 cursors[length] = NULL;
1817 for (x=0; x<length; x++) {
1818 PyObject* item = PySequence_GetItem(cursorsObj, x);
1819 if (item == NULL) {
1820 free(cursors);
1821 return NULL;
1823 if (!DBCursorObject_Check(item)) {
1824 PyErr_SetString(PyExc_TypeError,
1825 "Sequence of DBCursor objects expected");
1826 free(cursors);
1827 return NULL;
1829 cursors[x] = ((DBCursorObject*)item)->dbc;
1830 Py_DECREF(item);
1833 MYDB_BEGIN_ALLOW_THREADS;
1834 err = self->db->join(self->db, cursors, &dbc, flags);
1835 MYDB_END_ALLOW_THREADS;
1836 free(cursors);
1837 RETURN_IF_ERR();
1839 /* FIXME: this is a buggy interface. The returned cursor
1840 contains internal references to the passed in cursors
1841 but does not hold python references to them or prevent
1842 them from being closed prematurely. This can cause
1843 python to crash when things are done in the wrong order. */
1844 return (PyObject*) newDBCursorObject(dbc, self);
1848 static PyObject*
1849 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1851 int err, flags=0;
1852 PyObject* txnobj = NULL;
1853 PyObject* keyobj;
1854 DBT key;
1855 DB_TXN *txn = NULL;
1856 DB_KEY_RANGE range;
1857 static char* kwnames[] = { "key", "txn", "flags", NULL };
1859 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1860 &keyobj, &txnobj, &flags))
1861 return NULL;
1862 CHECK_DB_NOT_CLOSED(self);
1863 if (!make_dbt(keyobj, &key))
1864 /* BTree only, don't need to allow for an int key */
1865 return NULL;
1866 if (!checkTxnObj(txnobj, &txn))
1867 return NULL;
1869 MYDB_BEGIN_ALLOW_THREADS;
1870 err = self->db->key_range(self->db, txn, &key, &range, flags);
1871 MYDB_END_ALLOW_THREADS;
1873 RETURN_IF_ERR();
1874 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1878 static PyObject*
1879 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1881 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1882 char* filename = NULL;
1883 char* dbname = NULL;
1884 #if (DBVER >= 41)
1885 PyObject *txnobj = NULL;
1886 DB_TXN *txn = NULL;
1887 /* with dbname */
1888 static char* kwnames[] = {
1889 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1890 /* without dbname */
1891 static char* kwnames_basic[] = {
1892 "filename", "dbtype", "flags", "mode", "txn", NULL};
1893 #else
1894 /* with dbname */
1895 static char* kwnames[] = {
1896 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1897 /* without dbname */
1898 static char* kwnames_basic[] = {
1899 "filename", "dbtype", "flags", "mode", NULL};
1900 #endif
1902 #if (DBVER >= 41)
1903 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1904 &filename, &dbname, &type, &flags, &mode,
1905 &txnobj))
1906 #else
1907 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1908 &filename, &dbname, &type, &flags,
1909 &mode))
1910 #endif
1912 PyErr_Clear();
1913 type = DB_UNKNOWN; flags = 0; mode = 0660;
1914 filename = NULL; dbname = NULL;
1915 #if (DBVER >= 41)
1916 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1917 kwnames_basic,
1918 &filename, &type, &flags, &mode,
1919 &txnobj))
1920 return NULL;
1921 #else
1922 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1923 kwnames_basic,
1924 &filename, &type, &flags, &mode))
1925 return NULL;
1926 #endif
1929 #if (DBVER >= 41)
1930 if (!checkTxnObj(txnobj, &txn)) return NULL;
1931 #endif
1933 if (NULL == self->db) {
1934 PyObject *t = Py_BuildValue("(is)", 0,
1935 "Cannot call open() twice for DB object");
1936 PyErr_SetObject(DBError, t);
1937 Py_DECREF(t);
1938 return NULL;
1941 #if 0 && (DBVER >= 41)
1942 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1943 && (self->myenvobj->flags & DB_INIT_TXN))
1945 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1946 * explicitly passed) but we are in a transaction ready environment:
1947 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1948 * to work on BerkeleyDB 4.1 without needing to modify their
1949 * DBEnv or DB open calls.
1950 * TODO make this behaviour of the library configurable.
1952 flags |= DB_AUTO_COMMIT;
1954 #endif
1956 MYDB_BEGIN_ALLOW_THREADS;
1957 #if (DBVER >= 41)
1958 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1959 #else
1960 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1961 #endif
1962 MYDB_END_ALLOW_THREADS;
1963 if (makeDBError(err)) {
1964 self->db->close(self->db, 0);
1965 self->db = NULL;
1966 return NULL;
1969 self->flags = flags;
1970 RETURN_NONE();
1974 static PyObject*
1975 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1977 int flags=0;
1978 PyObject* txnobj = NULL;
1979 int dlen = -1;
1980 int doff = -1;
1981 PyObject* keyobj, *dataobj, *retval;
1982 DBT key, data;
1983 DB_TXN *txn = NULL;
1984 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1985 "doff", NULL };
1987 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1988 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1989 return NULL;
1991 CHECK_DB_NOT_CLOSED(self);
1992 if (!make_key_dbt(self, keyobj, &key, NULL))
1993 return NULL;
1994 if ( !make_dbt(dataobj, &data) ||
1995 !add_partial_dbt(&data, dlen, doff) ||
1996 !checkTxnObj(txnobj, &txn) )
1998 FREE_DBT(key);
1999 return NULL;
2002 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2003 FREE_DBT(key);
2004 return NULL;
2007 if (flags & DB_APPEND)
2008 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2009 else {
2010 retval = Py_None;
2011 Py_INCREF(retval);
2013 FREE_DBT(key);
2014 return retval;
2019 static PyObject*
2020 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2022 char* filename;
2023 char* database = NULL;
2024 int err, flags=0;
2025 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2027 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2028 &filename, &database, &flags))
2029 return NULL;
2030 CHECK_DB_NOT_CLOSED(self);
2032 err = self->db->remove(self->db, filename, database, flags);
2033 self->db = NULL;
2034 RETURN_IF_ERR();
2035 RETURN_NONE();
2040 static PyObject*
2041 DB_rename(DBObject* self, PyObject* args)
2043 char* filename;
2044 char* database;
2045 char* newname;
2046 int err, flags=0;
2048 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2049 &flags))
2050 return NULL;
2051 CHECK_DB_NOT_CLOSED(self);
2053 MYDB_BEGIN_ALLOW_THREADS;
2054 err = self->db->rename(self->db, filename, database, newname, flags);
2055 MYDB_END_ALLOW_THREADS;
2056 RETURN_IF_ERR();
2057 RETURN_NONE();
2061 static PyObject*
2062 DB_set_bt_minkey(DBObject* self, PyObject* args)
2064 int err, minkey;
2066 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2067 return NULL;
2068 CHECK_DB_NOT_CLOSED(self);
2070 MYDB_BEGIN_ALLOW_THREADS;
2071 err = self->db->set_bt_minkey(self->db, minkey);
2072 MYDB_END_ALLOW_THREADS;
2073 RETURN_IF_ERR();
2074 RETURN_NONE();
2077 #if (DBVER >= 33)
2078 static int
2079 _default_cmp(const DBT *leftKey,
2080 const DBT *rightKey)
2082 int res;
2083 int lsize = leftKey->size, rsize = rightKey->size;
2085 res = memcmp(leftKey->data, rightKey->data,
2086 lsize < rsize ? lsize : rsize);
2088 if (res == 0) {
2089 if (lsize < rsize) {
2090 res = -1;
2092 else if (lsize > rsize) {
2093 res = 1;
2096 return res;
2099 static int
2100 _db_compareCallback(DB* db,
2101 const DBT *leftKey,
2102 const DBT *rightKey)
2104 int res = 0;
2105 PyObject *args;
2106 PyObject *result = NULL;
2107 DBObject *self = (DBObject *)db->app_private;
2109 if (self == NULL || self->btCompareCallback == NULL) {
2110 MYDB_BEGIN_BLOCK_THREADS;
2111 PyErr_SetString(PyExc_TypeError,
2112 (self == 0
2113 ? "DB_bt_compare db is NULL."
2114 : "DB_bt_compare callback is NULL."));
2115 /* we're in a callback within the DB code, we can't raise */
2116 PyErr_Print();
2117 res = _default_cmp(leftKey, rightKey);
2118 MYDB_END_BLOCK_THREADS;
2119 } else {
2120 MYDB_BEGIN_BLOCK_THREADS;
2122 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2123 rightKey->data, rightKey->size);
2124 if (args != NULL) {
2125 /* XXX(twouters) I highly doubt this INCREF is correct */
2126 Py_INCREF(self);
2127 result = PyEval_CallObject(self->btCompareCallback, args);
2129 if (args == NULL || result == NULL) {
2130 /* we're in a callback within the DB code, we can't raise */
2131 PyErr_Print();
2132 res = _default_cmp(leftKey, rightKey);
2133 } else if (PyInt_Check(result)) {
2134 res = PyInt_AsLong(result);
2135 } else {
2136 PyErr_SetString(PyExc_TypeError,
2137 "DB_bt_compare callback MUST return an int.");
2138 /* we're in a callback within the DB code, we can't raise */
2139 PyErr_Print();
2140 res = _default_cmp(leftKey, rightKey);
2143 Py_XDECREF(args);
2144 Py_XDECREF(result);
2146 MYDB_END_BLOCK_THREADS;
2148 return res;
2151 static PyObject*
2152 DB_set_bt_compare(DBObject* self, PyObject* args)
2154 int err;
2155 PyObject *comparator;
2156 PyObject *tuple, *result;
2158 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2159 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2163 if (!PyCallable_Check(comparator)) {
2164 makeTypeError("Callable", comparator);
2165 return NULL;
2169 * Perform a test call of the comparator function with two empty
2170 * string objects here. verify that it returns an int (0).
2171 * err if not.
2173 tuple = Py_BuildValue("(ss)", "", "");
2174 result = PyEval_CallObject(comparator, tuple);
2175 Py_DECREF(tuple);
2176 if (result == NULL)
2177 return NULL;
2178 if (!PyInt_Check(result)) {
2179 PyErr_SetString(PyExc_TypeError,
2180 "callback MUST return an int");
2181 return NULL;
2182 } else if (PyInt_AsLong(result) != 0) {
2183 PyErr_SetString(PyExc_TypeError,
2184 "callback failed to return 0 on two empty strings");
2185 return NULL;
2187 Py_DECREF(result);
2189 /* We don't accept multiple set_bt_compare operations, in order to
2190 * simplify the code. This would have no real use, as one cannot
2191 * change the function once the db is opened anyway */
2192 if (self->btCompareCallback != NULL) {
2193 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2194 return NULL;
2197 Py_INCREF(comparator);
2198 self->btCompareCallback = comparator;
2200 /* This is to workaround a problem with un-initialized threads (see
2201 comment in DB_associate) */
2202 #ifdef WITH_THREAD
2203 PyEval_InitThreads();
2204 #endif
2206 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2208 if (err) {
2209 /* restore the old state in case of error */
2210 Py_DECREF(comparator);
2211 self->btCompareCallback = NULL;
2214 RETURN_IF_ERR();
2215 RETURN_NONE();
2217 #endif /* DBVER >= 33 */
2220 static PyObject*
2221 DB_set_cachesize(DBObject* self, PyObject* args)
2223 int err;
2224 int gbytes = 0, bytes = 0, ncache = 0;
2226 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2227 &gbytes,&bytes,&ncache))
2228 return NULL;
2229 CHECK_DB_NOT_CLOSED(self);
2231 MYDB_BEGIN_ALLOW_THREADS;
2232 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2233 MYDB_END_ALLOW_THREADS;
2234 RETURN_IF_ERR();
2235 RETURN_NONE();
2239 static PyObject*
2240 DB_set_flags(DBObject* self, PyObject* args)
2242 int err, flags;
2244 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2245 return NULL;
2246 CHECK_DB_NOT_CLOSED(self);
2248 MYDB_BEGIN_ALLOW_THREADS;
2249 err = self->db->set_flags(self->db, flags);
2250 MYDB_END_ALLOW_THREADS;
2251 RETURN_IF_ERR();
2253 self->setflags |= flags;
2254 RETURN_NONE();
2258 static PyObject*
2259 DB_set_h_ffactor(DBObject* self, PyObject* args)
2261 int err, ffactor;
2263 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2264 return NULL;
2265 CHECK_DB_NOT_CLOSED(self);
2267 MYDB_BEGIN_ALLOW_THREADS;
2268 err = self->db->set_h_ffactor(self->db, ffactor);
2269 MYDB_END_ALLOW_THREADS;
2270 RETURN_IF_ERR();
2271 RETURN_NONE();
2275 static PyObject*
2276 DB_set_h_nelem(DBObject* self, PyObject* args)
2278 int err, nelem;
2280 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2281 return NULL;
2282 CHECK_DB_NOT_CLOSED(self);
2284 MYDB_BEGIN_ALLOW_THREADS;
2285 err = self->db->set_h_nelem(self->db, nelem);
2286 MYDB_END_ALLOW_THREADS;
2287 RETURN_IF_ERR();
2288 RETURN_NONE();
2292 static PyObject*
2293 DB_set_lorder(DBObject* self, PyObject* args)
2295 int err, lorder;
2297 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2298 return NULL;
2299 CHECK_DB_NOT_CLOSED(self);
2301 MYDB_BEGIN_ALLOW_THREADS;
2302 err = self->db->set_lorder(self->db, lorder);
2303 MYDB_END_ALLOW_THREADS;
2304 RETURN_IF_ERR();
2305 RETURN_NONE();
2309 static PyObject*
2310 DB_set_pagesize(DBObject* self, PyObject* args)
2312 int err, pagesize;
2314 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2315 return NULL;
2316 CHECK_DB_NOT_CLOSED(self);
2318 MYDB_BEGIN_ALLOW_THREADS;
2319 err = self->db->set_pagesize(self->db, pagesize);
2320 MYDB_END_ALLOW_THREADS;
2321 RETURN_IF_ERR();
2322 RETURN_NONE();
2326 static PyObject*
2327 DB_set_re_delim(DBObject* self, PyObject* args)
2329 int err;
2330 char delim;
2332 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2333 PyErr_Clear();
2334 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2335 return NULL;
2338 CHECK_DB_NOT_CLOSED(self);
2340 MYDB_BEGIN_ALLOW_THREADS;
2341 err = self->db->set_re_delim(self->db, delim);
2342 MYDB_END_ALLOW_THREADS;
2343 RETURN_IF_ERR();
2344 RETURN_NONE();
2347 static PyObject*
2348 DB_set_re_len(DBObject* self, PyObject* args)
2350 int err, len;
2352 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2353 return NULL;
2354 CHECK_DB_NOT_CLOSED(self);
2356 MYDB_BEGIN_ALLOW_THREADS;
2357 err = self->db->set_re_len(self->db, len);
2358 MYDB_END_ALLOW_THREADS;
2359 RETURN_IF_ERR();
2360 RETURN_NONE();
2364 static PyObject*
2365 DB_set_re_pad(DBObject* self, PyObject* args)
2367 int err;
2368 char pad;
2370 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2371 PyErr_Clear();
2372 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2373 return NULL;
2375 CHECK_DB_NOT_CLOSED(self);
2377 MYDB_BEGIN_ALLOW_THREADS;
2378 err = self->db->set_re_pad(self->db, pad);
2379 MYDB_END_ALLOW_THREADS;
2380 RETURN_IF_ERR();
2381 RETURN_NONE();
2385 static PyObject*
2386 DB_set_re_source(DBObject* self, PyObject* args)
2388 int err;
2389 char *re_source;
2391 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2392 return NULL;
2393 CHECK_DB_NOT_CLOSED(self);
2395 MYDB_BEGIN_ALLOW_THREADS;
2396 err = self->db->set_re_source(self->db, re_source);
2397 MYDB_END_ALLOW_THREADS;
2398 RETURN_IF_ERR();
2399 RETURN_NONE();
2403 #if (DBVER >= 32)
2404 static PyObject*
2405 DB_set_q_extentsize(DBObject* self, PyObject* args)
2407 int err;
2408 int extentsize;
2410 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2411 return NULL;
2412 CHECK_DB_NOT_CLOSED(self);
2414 MYDB_BEGIN_ALLOW_THREADS;
2415 err = self->db->set_q_extentsize(self->db, extentsize);
2416 MYDB_END_ALLOW_THREADS;
2417 RETURN_IF_ERR();
2418 RETURN_NONE();
2420 #endif
2422 static PyObject*
2423 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2425 int err, flags = 0, type;
2426 void* sp;
2427 PyObject* d;
2428 #if (DBVER >= 43)
2429 PyObject* txnobj = NULL;
2430 DB_TXN *txn = NULL;
2431 static char* kwnames[] = { "flags", "txn", NULL };
2432 #else
2433 static char* kwnames[] = { "flags", NULL };
2434 #endif
2436 #if (DBVER >= 43)
2437 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2438 &flags, &txnobj))
2439 return NULL;
2440 if (!checkTxnObj(txnobj, &txn))
2441 return NULL;
2442 #else
2443 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2444 return NULL;
2445 #endif
2446 CHECK_DB_NOT_CLOSED(self);
2448 MYDB_BEGIN_ALLOW_THREADS;
2449 #if (DBVER >= 43)
2450 err = self->db->stat(self->db, txn, &sp, flags);
2451 #elif (DBVER >= 33)
2452 err = self->db->stat(self->db, &sp, flags);
2453 #else
2454 err = self->db->stat(self->db, &sp, NULL, flags);
2455 #endif
2456 MYDB_END_ALLOW_THREADS;
2457 RETURN_IF_ERR();
2459 self->haveStat = 1;
2461 /* Turn the stat structure into a dictionary */
2462 type = _DB_get_type(self);
2463 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2464 free(sp);
2465 return NULL;
2468 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2469 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2470 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2472 switch (type) {
2473 case DB_HASH:
2474 MAKE_HASH_ENTRY(magic);
2475 MAKE_HASH_ENTRY(version);
2476 MAKE_HASH_ENTRY(nkeys);
2477 MAKE_HASH_ENTRY(ndata);
2478 MAKE_HASH_ENTRY(pagesize);
2479 #if (DBVER < 41)
2480 MAKE_HASH_ENTRY(nelem);
2481 #endif
2482 MAKE_HASH_ENTRY(ffactor);
2483 MAKE_HASH_ENTRY(buckets);
2484 MAKE_HASH_ENTRY(free);
2485 MAKE_HASH_ENTRY(bfree);
2486 MAKE_HASH_ENTRY(bigpages);
2487 MAKE_HASH_ENTRY(big_bfree);
2488 MAKE_HASH_ENTRY(overflows);
2489 MAKE_HASH_ENTRY(ovfl_free);
2490 MAKE_HASH_ENTRY(dup);
2491 MAKE_HASH_ENTRY(dup_free);
2492 break;
2494 case DB_BTREE:
2495 case DB_RECNO:
2496 MAKE_BT_ENTRY(magic);
2497 MAKE_BT_ENTRY(version);
2498 MAKE_BT_ENTRY(nkeys);
2499 MAKE_BT_ENTRY(ndata);
2500 MAKE_BT_ENTRY(pagesize);
2501 MAKE_BT_ENTRY(minkey);
2502 MAKE_BT_ENTRY(re_len);
2503 MAKE_BT_ENTRY(re_pad);
2504 MAKE_BT_ENTRY(levels);
2505 MAKE_BT_ENTRY(int_pg);
2506 MAKE_BT_ENTRY(leaf_pg);
2507 MAKE_BT_ENTRY(dup_pg);
2508 MAKE_BT_ENTRY(over_pg);
2509 MAKE_BT_ENTRY(free);
2510 MAKE_BT_ENTRY(int_pgfree);
2511 MAKE_BT_ENTRY(leaf_pgfree);
2512 MAKE_BT_ENTRY(dup_pgfree);
2513 MAKE_BT_ENTRY(over_pgfree);
2514 break;
2516 case DB_QUEUE:
2517 MAKE_QUEUE_ENTRY(magic);
2518 MAKE_QUEUE_ENTRY(version);
2519 MAKE_QUEUE_ENTRY(nkeys);
2520 MAKE_QUEUE_ENTRY(ndata);
2521 MAKE_QUEUE_ENTRY(pagesize);
2522 MAKE_QUEUE_ENTRY(pages);
2523 MAKE_QUEUE_ENTRY(re_len);
2524 MAKE_QUEUE_ENTRY(re_pad);
2525 MAKE_QUEUE_ENTRY(pgfree);
2526 #if (DBVER == 31)
2527 MAKE_QUEUE_ENTRY(start);
2528 #endif
2529 MAKE_QUEUE_ENTRY(first_recno);
2530 MAKE_QUEUE_ENTRY(cur_recno);
2531 break;
2533 default:
2534 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2535 Py_DECREF(d);
2536 d = NULL;
2539 #undef MAKE_HASH_ENTRY
2540 #undef MAKE_BT_ENTRY
2541 #undef MAKE_QUEUE_ENTRY
2543 free(sp);
2544 return d;
2547 static PyObject*
2548 DB_sync(DBObject* self, PyObject* args)
2550 int err;
2551 int flags = 0;
2553 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2554 return NULL;
2555 CHECK_DB_NOT_CLOSED(self);
2557 MYDB_BEGIN_ALLOW_THREADS;
2558 err = self->db->sync(self->db, flags);
2559 MYDB_END_ALLOW_THREADS;
2560 RETURN_IF_ERR();
2561 RETURN_NONE();
2565 #if (DBVER >= 33)
2566 static PyObject*
2567 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2569 int err, flags=0;
2570 u_int32_t count=0;
2571 PyObject* txnobj = NULL;
2572 DB_TXN *txn = NULL;
2573 static char* kwnames[] = { "txn", "flags", NULL };
2575 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2576 &txnobj, &flags))
2577 return NULL;
2578 CHECK_DB_NOT_CLOSED(self);
2579 if (!checkTxnObj(txnobj, &txn))
2580 return NULL;
2582 MYDB_BEGIN_ALLOW_THREADS;
2583 err = self->db->truncate(self->db, txn, &count, flags);
2584 MYDB_END_ALLOW_THREADS;
2585 RETURN_IF_ERR();
2586 return PyInt_FromLong(count);
2588 #endif
2591 static PyObject*
2592 DB_upgrade(DBObject* self, PyObject* args)
2594 int err, flags=0;
2595 char *filename;
2597 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2598 return NULL;
2599 CHECK_DB_NOT_CLOSED(self);
2601 MYDB_BEGIN_ALLOW_THREADS;
2602 err = self->db->upgrade(self->db, filename, flags);
2603 MYDB_END_ALLOW_THREADS;
2604 RETURN_IF_ERR();
2605 RETURN_NONE();
2609 static PyObject*
2610 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2612 int err, flags=0;
2613 char* fileName;
2614 char* dbName=NULL;
2615 char* outFileName=NULL;
2616 FILE* outFile=NULL;
2617 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2618 NULL };
2620 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2621 &fileName, &dbName, &outFileName, &flags))
2622 return NULL;
2624 CHECK_DB_NOT_CLOSED(self);
2625 if (outFileName)
2626 outFile = fopen(outFileName, "w");
2627 /* XXX(nnorwitz): it should probably be an exception if outFile
2628 can't be opened. */
2630 MYDB_BEGIN_ALLOW_THREADS;
2631 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2632 MYDB_END_ALLOW_THREADS;
2633 if (outFile)
2634 fclose(outFile);
2636 /* DB.verify acts as a DB handle destructor (like close); this was
2637 * documented in BerkeleyDB 4.2 but had the undocumented effect
2638 * of not being safe in prior versions while still requiring an explicit
2639 * DB.close call afterwards. Lets call close for the user to emulate
2640 * the safe 4.2 behaviour. */
2641 #if (DBVER <= 41)
2642 self->db->close(self->db, 0);
2643 #endif
2644 self->db = NULL;
2646 RETURN_IF_ERR();
2647 RETURN_NONE();
2651 static PyObject*
2652 DB_set_get_returns_none(DBObject* self, PyObject* args)
2654 int flags=0;
2655 int oldValue=0;
2657 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2658 return NULL;
2659 CHECK_DB_NOT_CLOSED(self);
2661 if (self->moduleFlags.getReturnsNone)
2662 ++oldValue;
2663 if (self->moduleFlags.cursorSetReturnsNone)
2664 ++oldValue;
2665 self->moduleFlags.getReturnsNone = (flags >= 1);
2666 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2667 return PyInt_FromLong(oldValue);
2670 #if (DBVER >= 41)
2671 static PyObject*
2672 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2674 int err;
2675 u_int32_t flags=0;
2676 char *passwd = NULL;
2677 static char* kwnames[] = { "passwd", "flags", NULL };
2679 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2680 &passwd, &flags)) {
2681 return NULL;
2684 MYDB_BEGIN_ALLOW_THREADS;
2685 err = self->db->set_encrypt(self->db, passwd, flags);
2686 MYDB_END_ALLOW_THREADS;
2688 RETURN_IF_ERR();
2689 RETURN_NONE();
2691 #endif /* DBVER >= 41 */
2694 /*-------------------------------------------------------------- */
2695 /* Mapping and Dictionary-like access routines */
2697 Py_ssize_t DB_length(PyObject* _self)
2699 int err;
2700 Py_ssize_t size = 0;
2701 int flags = 0;
2702 void* sp;
2703 DBObject* self = (DBObject*)_self;
2705 if (self->db == NULL) {
2706 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2707 PyErr_SetObject(DBError, t);
2708 Py_DECREF(t);
2709 return -1;
2712 if (self->haveStat) { /* Has the stat function been called recently? If
2713 so, we can use the cached value. */
2714 flags = DB_FAST_STAT;
2717 MYDB_BEGIN_ALLOW_THREADS;
2718 redo_stat_for_length:
2719 #if (DBVER >= 43)
2720 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2721 #elif (DBVER >= 33)
2722 err = self->db->stat(self->db, &sp, flags);
2723 #else
2724 err = self->db->stat(self->db, &sp, NULL, flags);
2725 #endif
2727 /* All the stat structures have matching fields upto the ndata field,
2728 so we can use any of them for the type cast */
2729 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2731 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2732 * redo a full stat to make sure.
2733 * Fixes SF python bug 1493322, pybsddb bug 1184012
2735 if (size == 0 && (flags & DB_FAST_STAT)) {
2736 flags = 0;
2737 if (!err)
2738 free(sp);
2739 goto redo_stat_for_length;
2742 MYDB_END_ALLOW_THREADS;
2744 if (err)
2745 return -1;
2747 self->haveStat = 1;
2749 free(sp);
2750 return size;
2754 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2756 int err;
2757 PyObject* retval;
2758 DBT key;
2759 DBT data;
2761 CHECK_DB_NOT_CLOSED(self);
2762 if (!make_key_dbt(self, keyobj, &key, NULL))
2763 return NULL;
2765 CLEAR_DBT(data);
2766 if (CHECK_DBFLAG(self, DB_THREAD)) {
2767 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2768 data.flags = DB_DBT_MALLOC;
2770 MYDB_BEGIN_ALLOW_THREADS;
2771 err = self->db->get(self->db, NULL, &key, &data, 0);
2772 MYDB_END_ALLOW_THREADS;
2773 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2774 PyErr_SetObject(PyExc_KeyError, keyobj);
2775 retval = NULL;
2777 else if (makeDBError(err)) {
2778 retval = NULL;
2780 else {
2781 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2782 FREE_DBT(data);
2785 FREE_DBT(key);
2786 return retval;
2790 static int
2791 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2793 DBT key, data;
2794 int retval;
2795 int flags = 0;
2797 if (self->db == NULL) {
2798 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2799 PyErr_SetObject(DBError, t);
2800 Py_DECREF(t);
2801 return -1;
2804 if (!make_key_dbt(self, keyobj, &key, NULL))
2805 return -1;
2807 if (dataobj != NULL) {
2808 if (!make_dbt(dataobj, &data))
2809 retval = -1;
2810 else {
2811 if (self->setflags & (DB_DUP|DB_DUPSORT))
2812 /* dictionaries shouldn't have duplicate keys */
2813 flags = DB_NOOVERWRITE;
2814 retval = _DB_put(self, NULL, &key, &data, flags);
2816 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2817 /* try deleting any old record that matches and then PUT it
2818 * again... */
2819 _DB_delete(self, NULL, &key, 0);
2820 PyErr_Clear();
2821 retval = _DB_put(self, NULL, &key, &data, flags);
2825 else {
2826 /* dataobj == NULL, so delete the key */
2827 retval = _DB_delete(self, NULL, &key, 0);
2829 FREE_DBT(key);
2830 return retval;
2834 static PyObject*
2835 DB_has_key(DBObject* self, PyObject* args)
2837 int err;
2838 PyObject* keyobj;
2839 DBT key, data;
2840 PyObject* txnobj = NULL;
2841 DB_TXN *txn = NULL;
2843 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2844 return NULL;
2845 CHECK_DB_NOT_CLOSED(self);
2846 if (!make_key_dbt(self, keyobj, &key, NULL))
2847 return NULL;
2848 if (!checkTxnObj(txnobj, &txn)) {
2849 FREE_DBT(key);
2850 return NULL;
2853 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2854 it has a record but can't allocate a buffer for the data. This saves
2855 having to deal with data we won't be using.
2857 CLEAR_DBT(data);
2858 data.flags = DB_DBT_USERMEM;
2860 MYDB_BEGIN_ALLOW_THREADS;
2861 err = self->db->get(self->db, txn, &key, &data, 0);
2862 MYDB_END_ALLOW_THREADS;
2863 FREE_DBT(key);
2865 if (err == DB_BUFFER_SMALL || err == 0) {
2866 return PyInt_FromLong(1);
2867 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2868 return PyInt_FromLong(0);
2871 makeDBError(err);
2872 return NULL;
2876 #define _KEYS_LIST 1
2877 #define _VALUES_LIST 2
2878 #define _ITEMS_LIST 3
2880 static PyObject*
2881 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2883 int err, dbtype;
2884 DBT key;
2885 DBT data;
2886 DBC *cursor;
2887 PyObject* list;
2888 PyObject* item = NULL;
2890 CHECK_DB_NOT_CLOSED(self);
2891 CLEAR_DBT(key);
2892 CLEAR_DBT(data);
2894 dbtype = _DB_get_type(self);
2895 if (dbtype == -1)
2896 return NULL;
2898 list = PyList_New(0);
2899 if (list == NULL)
2900 return NULL;
2902 /* get a cursor */
2903 MYDB_BEGIN_ALLOW_THREADS;
2904 err = self->db->cursor(self->db, txn, &cursor, 0);
2905 MYDB_END_ALLOW_THREADS;
2906 if (makeDBError(err)) {
2907 Py_DECREF(list);
2908 return NULL;
2911 if (CHECK_DBFLAG(self, DB_THREAD)) {
2912 key.flags = DB_DBT_REALLOC;
2913 data.flags = DB_DBT_REALLOC;
2916 while (1) { /* use the cursor to traverse the DB, collecting items */
2917 MYDB_BEGIN_ALLOW_THREADS;
2918 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2919 MYDB_END_ALLOW_THREADS;
2921 if (err) {
2922 /* for any error, break out of the loop */
2923 break;
2926 switch (type) {
2927 case _KEYS_LIST:
2928 switch(dbtype) {
2929 case DB_BTREE:
2930 case DB_HASH:
2931 default:
2932 item = PyString_FromStringAndSize((char*)key.data, key.size);
2933 break;
2934 case DB_RECNO:
2935 case DB_QUEUE:
2936 item = PyInt_FromLong(*((db_recno_t*)key.data));
2937 break;
2939 break;
2941 case _VALUES_LIST:
2942 item = PyString_FromStringAndSize((char*)data.data, data.size);
2943 break;
2945 case _ITEMS_LIST:
2946 switch(dbtype) {
2947 case DB_BTREE:
2948 case DB_HASH:
2949 default:
2950 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2951 data.size);
2952 break;
2953 case DB_RECNO:
2954 case DB_QUEUE:
2955 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2956 data.data, data.size);
2957 break;
2959 break;
2960 default:
2961 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2962 item = NULL;
2963 break;
2965 if (item == NULL) {
2966 Py_DECREF(list);
2967 list = NULL;
2968 goto done;
2970 PyList_Append(list, item);
2971 Py_DECREF(item);
2974 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2975 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2976 Py_DECREF(list);
2977 list = NULL;
2980 done:
2981 FREE_DBT(key);
2982 FREE_DBT(data);
2983 MYDB_BEGIN_ALLOW_THREADS;
2984 cursor->c_close(cursor);
2985 MYDB_END_ALLOW_THREADS;
2986 return list;
2990 static PyObject*
2991 DB_keys(DBObject* self, PyObject* args)
2993 PyObject* txnobj = NULL;
2994 DB_TXN *txn = NULL;
2996 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2997 return NULL;
2998 if (!checkTxnObj(txnobj, &txn))
2999 return NULL;
3000 return _DB_make_list(self, txn, _KEYS_LIST);
3004 static PyObject*
3005 DB_items(DBObject* self, PyObject* args)
3007 PyObject* txnobj = NULL;
3008 DB_TXN *txn = NULL;
3010 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
3011 return NULL;
3012 if (!checkTxnObj(txnobj, &txn))
3013 return NULL;
3014 return _DB_make_list(self, txn, _ITEMS_LIST);
3018 static PyObject*
3019 DB_values(DBObject* self, PyObject* args)
3021 PyObject* txnobj = NULL;
3022 DB_TXN *txn = NULL;
3024 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3025 return NULL;
3026 if (!checkTxnObj(txnobj, &txn))
3027 return NULL;
3028 return _DB_make_list(self, txn, _VALUES_LIST);
3031 /* --------------------------------------------------------------------- */
3032 /* DBCursor methods */
3035 static PyObject*
3036 DBC_close(DBCursorObject* self, PyObject* args)
3038 int err = 0;
3040 if (!PyArg_ParseTuple(args, ":close"))
3041 return NULL;
3043 if (self->dbc != NULL) {
3044 MYDB_BEGIN_ALLOW_THREADS;
3045 err = self->dbc->c_close(self->dbc);
3046 self->dbc = NULL;
3047 MYDB_END_ALLOW_THREADS;
3049 RETURN_IF_ERR();
3050 RETURN_NONE();
3054 static PyObject*
3055 DBC_count(DBCursorObject* self, PyObject* args)
3057 int err = 0;
3058 db_recno_t count;
3059 int flags = 0;
3061 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3062 return NULL;
3064 CHECK_CURSOR_NOT_CLOSED(self);
3066 MYDB_BEGIN_ALLOW_THREADS;
3067 err = self->dbc->c_count(self->dbc, &count, flags);
3068 MYDB_END_ALLOW_THREADS;
3069 RETURN_IF_ERR();
3071 return PyInt_FromLong(count);
3075 static PyObject*
3076 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3078 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3082 static PyObject*
3083 DBC_delete(DBCursorObject* self, PyObject* args)
3085 int err, flags=0;
3087 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3088 return NULL;
3090 CHECK_CURSOR_NOT_CLOSED(self);
3092 MYDB_BEGIN_ALLOW_THREADS;
3093 err = self->dbc->c_del(self->dbc, flags);
3094 MYDB_END_ALLOW_THREADS;
3095 RETURN_IF_ERR();
3097 self->mydb->haveStat = 0;
3098 RETURN_NONE();
3102 static PyObject*
3103 DBC_dup(DBCursorObject* self, PyObject* args)
3105 int err, flags =0;
3106 DBC* dbc = NULL;
3108 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3109 return NULL;
3111 CHECK_CURSOR_NOT_CLOSED(self);
3113 MYDB_BEGIN_ALLOW_THREADS;
3114 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3115 MYDB_END_ALLOW_THREADS;
3116 RETURN_IF_ERR();
3118 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3121 static PyObject*
3122 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3124 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3128 static PyObject*
3129 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3131 int err, flags=0;
3132 PyObject* keyobj = NULL;
3133 PyObject* dataobj = NULL;
3134 PyObject* retval = NULL;
3135 int dlen = -1;
3136 int doff = -1;
3137 DBT key, data;
3138 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3139 NULL };
3141 CLEAR_DBT(key);
3142 CLEAR_DBT(data);
3143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3144 &flags, &dlen, &doff))
3146 PyErr_Clear();
3147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3148 &kwnames[1],
3149 &keyobj, &flags, &dlen, &doff))
3151 PyErr_Clear();
3152 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3153 kwnames, &keyobj, &dataobj,
3154 &flags, &dlen, &doff))
3156 return NULL;
3161 CHECK_CURSOR_NOT_CLOSED(self);
3163 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3164 return NULL;
3165 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3166 (!add_partial_dbt(&data, dlen, doff)) )
3168 FREE_DBT(key);
3169 return NULL;
3172 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3173 data.flags = DB_DBT_MALLOC;
3174 if (!(key.flags & DB_DBT_REALLOC)) {
3175 key.flags |= DB_DBT_MALLOC;
3179 MYDB_BEGIN_ALLOW_THREADS;
3180 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3181 MYDB_END_ALLOW_THREADS;
3183 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3184 && self->mydb->moduleFlags.getReturnsNone) {
3185 Py_INCREF(Py_None);
3186 retval = Py_None;
3188 else if (makeDBError(err)) {
3189 retval = NULL;
3191 else {
3192 switch (_DB_get_type(self->mydb)) {
3193 case -1:
3194 retval = NULL;
3195 break;
3196 case DB_BTREE:
3197 case DB_HASH:
3198 default:
3199 retval = Py_BuildValue("s#s#", key.data, key.size,
3200 data.data, data.size);
3201 break;
3202 case DB_RECNO:
3203 case DB_QUEUE:
3204 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3205 data.data, data.size);
3206 break;
3208 FREE_DBT(data);
3210 FREE_DBT(key);
3211 return retval;
3214 #if (DBVER >= 33)
3215 static PyObject*
3216 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3218 int err, flags=0;
3219 PyObject* keyobj = NULL;
3220 PyObject* dataobj = NULL;
3221 PyObject* retval = NULL;
3222 int dlen = -1;
3223 int doff = -1;
3224 DBT key, pkey, data;
3225 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3226 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3228 CLEAR_DBT(key);
3229 CLEAR_DBT(data);
3230 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3231 &flags, &dlen, &doff))
3233 PyErr_Clear();
3234 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3235 kwnames_keyOnly,
3236 &keyobj, &flags, &dlen, &doff))
3238 PyErr_Clear();
3239 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3240 kwnames, &keyobj, &dataobj,
3241 &flags, &dlen, &doff))
3243 return NULL;
3248 CHECK_CURSOR_NOT_CLOSED(self);
3250 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3251 return NULL;
3252 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3253 (!add_partial_dbt(&data, dlen, doff)) ) {
3254 FREE_DBT(key);
3255 return NULL;
3258 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3259 data.flags = DB_DBT_MALLOC;
3260 if (!(key.flags & DB_DBT_REALLOC)) {
3261 key.flags |= DB_DBT_MALLOC;
3265 CLEAR_DBT(pkey);
3266 pkey.flags = DB_DBT_MALLOC;
3268 MYDB_BEGIN_ALLOW_THREADS;
3269 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3270 MYDB_END_ALLOW_THREADS;
3272 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3273 && self->mydb->moduleFlags.getReturnsNone) {
3274 Py_INCREF(Py_None);
3275 retval = Py_None;
3277 else if (makeDBError(err)) {
3278 retval = NULL;
3280 else {
3281 PyObject *pkeyObj;
3282 PyObject *dataObj;
3283 dataObj = PyString_FromStringAndSize(data.data, data.size);
3285 if (self->mydb->primaryDBType == DB_RECNO ||
3286 self->mydb->primaryDBType == DB_QUEUE)
3287 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3288 else
3289 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3291 if (key.data && key.size) /* return key, pkey and data */
3293 PyObject *keyObj;
3294 int type = _DB_get_type(self->mydb);
3295 if (type == DB_RECNO || type == DB_QUEUE)
3296 keyObj = PyInt_FromLong(*(int *)key.data);
3297 else
3298 keyObj = PyString_FromStringAndSize(key.data, key.size);
3299 #if (PY_VERSION_HEX >= 0x02040000)
3300 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3301 #else
3302 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3303 #endif
3304 Py_DECREF(keyObj);
3305 FREE_DBT(key);
3307 else /* return just the pkey and data */
3309 #if (PY_VERSION_HEX >= 0x02040000)
3310 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3311 #else
3312 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3313 #endif
3315 Py_DECREF(dataObj);
3316 Py_DECREF(pkeyObj);
3317 FREE_DBT(pkey);
3318 FREE_DBT(data);
3320 /* the only time REALLOC should be set is if we used an integer
3321 * key that make_key_dbt malloc'd for us. always free these. */
3322 if (key.flags & DB_DBT_REALLOC) {
3323 FREE_DBT(key);
3325 return retval;
3327 #endif
3330 static PyObject*
3331 DBC_get_recno(DBCursorObject* self, PyObject* args)
3333 int err;
3334 db_recno_t recno;
3335 DBT key;
3336 DBT data;
3338 if (!PyArg_ParseTuple(args, ":get_recno"))
3339 return NULL;
3341 CHECK_CURSOR_NOT_CLOSED(self);
3343 CLEAR_DBT(key);
3344 CLEAR_DBT(data);
3345 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3346 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3347 data.flags = DB_DBT_MALLOC;
3348 key.flags = DB_DBT_MALLOC;
3351 MYDB_BEGIN_ALLOW_THREADS;
3352 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3353 MYDB_END_ALLOW_THREADS;
3354 RETURN_IF_ERR();
3356 recno = *((db_recno_t*)data.data);
3357 FREE_DBT(key);
3358 FREE_DBT(data);
3359 return PyInt_FromLong(recno);
3363 static PyObject*
3364 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3366 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3370 static PyObject*
3371 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3373 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3377 static PyObject*
3378 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3380 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3384 static PyObject*
3385 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3387 int err, flags = 0;
3388 PyObject* keyobj, *dataobj;
3389 DBT key, data;
3390 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3391 NULL };
3392 int dlen = -1;
3393 int doff = -1;
3395 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3396 &keyobj, &dataobj, &flags, &dlen, &doff))
3397 return NULL;
3399 CHECK_CURSOR_NOT_CLOSED(self);
3401 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3402 return NULL;
3403 if (!make_dbt(dataobj, &data) ||
3404 !add_partial_dbt(&data, dlen, doff) )
3406 FREE_DBT(key);
3407 return NULL;
3410 MYDB_BEGIN_ALLOW_THREADS;
3411 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3412 MYDB_END_ALLOW_THREADS;
3413 FREE_DBT(key);
3414 RETURN_IF_ERR();
3415 self->mydb->haveStat = 0;
3416 RETURN_NONE();
3420 static PyObject*
3421 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3423 int err, flags = 0;
3424 DBT key, data;
3425 PyObject* retval, *keyobj;
3426 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3427 int dlen = -1;
3428 int doff = -1;
3430 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3431 &keyobj, &flags, &dlen, &doff))
3432 return NULL;
3434 CHECK_CURSOR_NOT_CLOSED(self);
3436 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3437 return NULL;
3439 CLEAR_DBT(data);
3440 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3441 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3442 data.flags = DB_DBT_MALLOC;
3444 if (!add_partial_dbt(&data, dlen, doff)) {
3445 FREE_DBT(key);
3446 return NULL;
3449 MYDB_BEGIN_ALLOW_THREADS;
3450 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3451 MYDB_END_ALLOW_THREADS;
3452 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3453 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3454 Py_INCREF(Py_None);
3455 retval = Py_None;
3457 else if (makeDBError(err)) {
3458 retval = NULL;
3460 else {
3461 switch (_DB_get_type(self->mydb)) {
3462 case -1:
3463 retval = NULL;
3464 break;
3465 case DB_BTREE:
3466 case DB_HASH:
3467 default:
3468 retval = Py_BuildValue("s#s#", key.data, key.size,
3469 data.data, data.size);
3470 break;
3471 case DB_RECNO:
3472 case DB_QUEUE:
3473 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3474 data.data, data.size);
3475 break;
3477 FREE_DBT(data);
3478 FREE_DBT(key);
3480 /* the only time REALLOC should be set is if we used an integer
3481 * key that make_key_dbt malloc'd for us. always free these. */
3482 if (key.flags & DB_DBT_REALLOC) {
3483 FREE_DBT(key);
3486 return retval;
3490 static PyObject*
3491 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3493 int err, flags = 0;
3494 DBT key, data;
3495 PyObject* retval, *keyobj;
3496 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3497 int dlen = -1;
3498 int doff = -1;
3500 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3501 &keyobj, &flags, &dlen, &doff))
3502 return NULL;
3504 CHECK_CURSOR_NOT_CLOSED(self);
3506 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3507 return NULL;
3509 CLEAR_DBT(data);
3510 if (!add_partial_dbt(&data, dlen, doff)) {
3511 FREE_DBT(key);
3512 return NULL;
3514 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3515 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3516 data.flags |= DB_DBT_MALLOC;
3517 /* only BTREE databases will return anything in the key */
3518 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3519 key.flags |= DB_DBT_MALLOC;
3522 MYDB_BEGIN_ALLOW_THREADS;
3523 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3524 MYDB_END_ALLOW_THREADS;
3525 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3526 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3527 Py_INCREF(Py_None);
3528 retval = Py_None;
3530 else if (makeDBError(err)) {
3531 retval = NULL;
3533 else {
3534 switch (_DB_get_type(self->mydb)) {
3535 case -1:
3536 retval = NULL;
3537 break;
3538 case DB_BTREE:
3539 case DB_HASH:
3540 default:
3541 retval = Py_BuildValue("s#s#", key.data, key.size,
3542 data.data, data.size);
3543 break;
3544 case DB_RECNO:
3545 case DB_QUEUE:
3546 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3547 data.data, data.size);
3548 break;
3550 FREE_DBT(key);
3551 FREE_DBT(data);
3553 /* the only time REALLOC should be set is if we used an integer
3554 * key that make_key_dbt malloc'd for us. always free these. */
3555 if (key.flags & DB_DBT_REALLOC) {
3556 FREE_DBT(key);
3559 return retval;
3562 static PyObject*
3563 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3564 int flags, unsigned int returnsNone)
3566 int err;
3567 DBT key, data;
3568 PyObject* retval;
3570 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3571 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3572 return NULL;
3573 if (!make_dbt(dataobj, &data)) {
3574 FREE_DBT(key);
3575 return NULL;
3578 MYDB_BEGIN_ALLOW_THREADS;
3579 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3580 MYDB_END_ALLOW_THREADS;
3581 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3582 Py_INCREF(Py_None);
3583 retval = Py_None;
3585 else if (makeDBError(err)) {
3586 retval = NULL;
3588 else {
3589 switch (_DB_get_type(self->mydb)) {
3590 case -1:
3591 retval = NULL;
3592 break;
3593 case DB_BTREE:
3594 case DB_HASH:
3595 default:
3596 retval = Py_BuildValue("s#s#", key.data, key.size,
3597 data.data, data.size);
3598 break;
3599 case DB_RECNO:
3600 case DB_QUEUE:
3601 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3602 data.data, data.size);
3603 break;
3607 FREE_DBT(key);
3608 return retval;
3611 static PyObject*
3612 DBC_get_both(DBCursorObject* self, PyObject* args)
3614 int flags=0;
3615 PyObject *keyobj, *dataobj;
3617 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3618 return NULL;
3620 /* if the cursor is closed, self->mydb may be invalid */
3621 CHECK_CURSOR_NOT_CLOSED(self);
3623 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3624 self->mydb->moduleFlags.getReturnsNone);
3627 /* Return size of entry */
3628 static PyObject*
3629 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3631 int err, flags=DB_CURRENT;
3632 PyObject* retval = NULL;
3633 DBT key, data;
3635 if (!PyArg_ParseTuple(args, ":get_current_size"))
3636 return NULL;
3637 CHECK_CURSOR_NOT_CLOSED(self);
3638 CLEAR_DBT(key);
3639 CLEAR_DBT(data);
3641 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3642 getting the record size. */
3643 data.flags = DB_DBT_USERMEM;
3644 data.ulen = 0;
3645 MYDB_BEGIN_ALLOW_THREADS;
3646 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3647 MYDB_END_ALLOW_THREADS;
3648 if (err == DB_BUFFER_SMALL || !err) {
3649 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3650 retval = PyInt_FromLong((long)data.size);
3651 err = 0;
3654 FREE_DBT(key);
3655 FREE_DBT(data);
3656 RETURN_IF_ERR();
3657 return retval;
3660 static PyObject*
3661 DBC_set_both(DBCursorObject* self, PyObject* args)
3663 int flags=0;
3664 PyObject *keyobj, *dataobj;
3666 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3667 return NULL;
3669 /* if the cursor is closed, self->mydb may be invalid */
3670 CHECK_CURSOR_NOT_CLOSED(self);
3672 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3673 self->mydb->moduleFlags.cursorSetReturnsNone);
3677 static PyObject*
3678 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3680 int err, irecno, flags=0;
3681 db_recno_t recno;
3682 DBT key, data;
3683 PyObject* retval;
3684 int dlen = -1;
3685 int doff = -1;
3686 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3689 &irecno, &flags, &dlen, &doff))
3690 return NULL;
3692 CHECK_CURSOR_NOT_CLOSED(self);
3694 CLEAR_DBT(key);
3695 recno = (db_recno_t) irecno;
3696 /* use allocated space so DB will be able to realloc room for the real
3697 * key */
3698 key.data = malloc(sizeof(db_recno_t));
3699 if (key.data == NULL) {
3700 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3701 return NULL;
3703 key.size = sizeof(db_recno_t);
3704 key.ulen = key.size;
3705 memcpy(key.data, &recno, sizeof(db_recno_t));
3706 key.flags = DB_DBT_REALLOC;
3708 CLEAR_DBT(data);
3709 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3711 data.flags = DB_DBT_MALLOC;
3713 if (!add_partial_dbt(&data, dlen, doff)) {
3714 FREE_DBT(key);
3715 return NULL;
3718 MYDB_BEGIN_ALLOW_THREADS;
3719 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3720 MYDB_END_ALLOW_THREADS;
3721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3722 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3723 Py_INCREF(Py_None);
3724 retval = Py_None;
3726 else if (makeDBError(err)) {
3727 retval = NULL;
3729 else { /* Can only be used for BTrees, so no need to return int key */
3730 retval = Py_BuildValue("s#s#", key.data, key.size,
3731 data.data, data.size);
3732 FREE_DBT(data);
3734 FREE_DBT(key);
3736 return retval;
3740 static PyObject*
3741 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3743 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3747 static PyObject*
3748 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3750 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3754 static PyObject*
3755 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3757 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3761 static PyObject*
3762 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3764 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3768 static PyObject*
3769 DBC_join_item(DBCursorObject* self, PyObject* args)
3771 int err, flags=0;
3772 DBT key, data;
3773 PyObject* retval;
3775 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3776 return NULL;
3778 CHECK_CURSOR_NOT_CLOSED(self);
3780 CLEAR_DBT(key);
3781 CLEAR_DBT(data);
3782 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3783 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3784 key.flags = DB_DBT_MALLOC;
3787 MYDB_BEGIN_ALLOW_THREADS;
3788 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3789 MYDB_END_ALLOW_THREADS;
3790 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3791 && self->mydb->moduleFlags.getReturnsNone) {
3792 Py_INCREF(Py_None);
3793 retval = Py_None;
3795 else if (makeDBError(err)) {
3796 retval = NULL;
3798 else {
3799 retval = Py_BuildValue("s#", key.data, key.size);
3800 FREE_DBT(key);
3803 return retval;
3808 /* --------------------------------------------------------------------- */
3809 /* DBEnv methods */
3812 static PyObject*
3813 DBEnv_close(DBEnvObject* self, PyObject* args)
3815 int err, flags = 0;
3817 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3818 return NULL;
3819 if (!self->closed) { /* Don't close more than once */
3820 MYDB_BEGIN_ALLOW_THREADS;
3821 err = self->db_env->close(self->db_env, flags);
3822 MYDB_END_ALLOW_THREADS;
3823 /* after calling DBEnv->close, regardless of error, this DBEnv
3824 * may not be accessed again (BerkeleyDB docs). */
3825 self->closed = 1;
3826 self->db_env = NULL;
3827 RETURN_IF_ERR();
3829 RETURN_NONE();
3833 static PyObject*
3834 DBEnv_open(DBEnvObject* self, PyObject* args)
3836 int err, flags=0, mode=0660;
3837 char *db_home;
3839 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3840 return NULL;
3842 CHECK_ENV_NOT_CLOSED(self);
3844 MYDB_BEGIN_ALLOW_THREADS;
3845 err = self->db_env->open(self->db_env, db_home, flags, mode);
3846 MYDB_END_ALLOW_THREADS;
3847 RETURN_IF_ERR();
3848 self->closed = 0;
3849 self->flags = flags;
3850 RETURN_NONE();
3854 static PyObject*
3855 DBEnv_remove(DBEnvObject* self, PyObject* args)
3857 int err, flags=0;
3858 char *db_home;
3860 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3861 return NULL;
3862 CHECK_ENV_NOT_CLOSED(self);
3863 MYDB_BEGIN_ALLOW_THREADS;
3864 err = self->db_env->remove(self->db_env, db_home, flags);
3865 MYDB_END_ALLOW_THREADS;
3866 RETURN_IF_ERR();
3867 RETURN_NONE();
3870 #if (DBVER >= 41)
3871 static PyObject*
3872 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3874 int err;
3875 u_int32_t flags=0;
3876 char *file = NULL;
3877 char *database = NULL;
3878 PyObject *txnobj = NULL;
3879 DB_TXN *txn = NULL;
3880 static char* kwnames[] = { "file", "database", "txn", "flags",
3881 NULL };
3883 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
3884 &file, &database, &txnobj, &flags)) {
3885 return NULL;
3887 if (!checkTxnObj(txnobj, &txn)) {
3888 return NULL;
3890 CHECK_ENV_NOT_CLOSED(self);
3891 MYDB_BEGIN_ALLOW_THREADS;
3892 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3893 MYDB_END_ALLOW_THREADS;
3894 RETURN_IF_ERR();
3895 RETURN_NONE();
3898 static PyObject*
3899 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3901 int err;
3902 u_int32_t flags=0;
3903 char *file = NULL;
3904 char *database = NULL;
3905 char *newname = NULL;
3906 PyObject *txnobj = NULL;
3907 DB_TXN *txn = NULL;
3908 static char* kwnames[] = { "file", "database", "newname", "txn",
3909 "flags", NULL };
3911 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
3912 &file, &database, &newname, &txnobj, &flags)) {
3913 return NULL;
3915 if (!checkTxnObj(txnobj, &txn)) {
3916 return NULL;
3918 CHECK_ENV_NOT_CLOSED(self);
3919 MYDB_BEGIN_ALLOW_THREADS;
3920 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3921 flags);
3922 MYDB_END_ALLOW_THREADS;
3923 RETURN_IF_ERR();
3924 RETURN_NONE();
3927 static PyObject*
3928 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3930 int err;
3931 u_int32_t flags=0;
3932 char *passwd = NULL;
3933 static char* kwnames[] = { "passwd", "flags", NULL };
3935 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3936 &passwd, &flags)) {
3937 return NULL;
3940 MYDB_BEGIN_ALLOW_THREADS;
3941 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3942 MYDB_END_ALLOW_THREADS;
3944 RETURN_IF_ERR();
3945 RETURN_NONE();
3947 #endif /* DBVER >= 41 */
3949 #if (DBVER >= 40)
3950 static PyObject*
3951 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3953 int err;
3954 u_int32_t flags=0;
3955 u_int32_t timeout = 0;
3956 static char* kwnames[] = { "timeout", "flags", NULL };
3958 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3959 &timeout, &flags)) {
3960 return NULL;
3963 MYDB_BEGIN_ALLOW_THREADS;
3964 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3965 MYDB_END_ALLOW_THREADS;
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3970 #endif /* DBVER >= 40 */
3972 static PyObject*
3973 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3975 int err;
3976 long shm_key = 0;
3978 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3979 return NULL;
3980 CHECK_ENV_NOT_CLOSED(self);
3982 err = self->db_env->set_shm_key(self->db_env, shm_key);
3983 RETURN_IF_ERR();
3984 RETURN_NONE();
3987 static PyObject*
3988 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3990 int err, gbytes=0, bytes=0, ncache=0;
3992 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3993 &gbytes, &bytes, &ncache))
3994 return NULL;
3995 CHECK_ENV_NOT_CLOSED(self);
3997 MYDB_BEGIN_ALLOW_THREADS;
3998 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3999 MYDB_END_ALLOW_THREADS;
4000 RETURN_IF_ERR();
4001 RETURN_NONE();
4005 #if (DBVER >= 32)
4006 static PyObject*
4007 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4009 int err, flags=0, onoff=0;
4011 if (!PyArg_ParseTuple(args, "ii:set_flags",
4012 &flags, &onoff))
4013 return NULL;
4014 CHECK_ENV_NOT_CLOSED(self);
4016 MYDB_BEGIN_ALLOW_THREADS;
4017 err = self->db_env->set_flags(self->db_env, flags, onoff);
4018 MYDB_END_ALLOW_THREADS;
4019 RETURN_IF_ERR();
4020 RETURN_NONE();
4022 #endif
4025 static PyObject*
4026 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4028 int err;
4029 char *dir;
4031 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4032 return NULL;
4033 CHECK_ENV_NOT_CLOSED(self);
4035 MYDB_BEGIN_ALLOW_THREADS;
4036 err = self->db_env->set_data_dir(self->db_env, dir);
4037 MYDB_END_ALLOW_THREADS;
4038 RETURN_IF_ERR();
4039 RETURN_NONE();
4043 static PyObject*
4044 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4046 int err, lg_bsize;
4048 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4049 return NULL;
4050 CHECK_ENV_NOT_CLOSED(self);
4052 MYDB_BEGIN_ALLOW_THREADS;
4053 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4054 MYDB_END_ALLOW_THREADS;
4055 RETURN_IF_ERR();
4056 RETURN_NONE();
4060 static PyObject*
4061 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4063 int err;
4064 char *dir;
4066 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_dir(self->db_env, dir);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4077 static PyObject*
4078 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4080 int err, lg_max;
4082 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4083 return NULL;
4084 CHECK_ENV_NOT_CLOSED(self);
4086 MYDB_BEGIN_ALLOW_THREADS;
4087 err = self->db_env->set_lg_max(self->db_env, lg_max);
4088 MYDB_END_ALLOW_THREADS;
4089 RETURN_IF_ERR();
4090 RETURN_NONE();
4094 #if (DBVER >= 33)
4095 static PyObject*
4096 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4098 int err, lg_max;
4100 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4101 return NULL;
4102 CHECK_ENV_NOT_CLOSED(self);
4104 MYDB_BEGIN_ALLOW_THREADS;
4105 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4106 MYDB_END_ALLOW_THREADS;
4107 RETURN_IF_ERR();
4108 RETURN_NONE();
4110 #endif
4113 static PyObject*
4114 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4116 int err, lk_detect;
4118 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4119 return NULL;
4120 CHECK_ENV_NOT_CLOSED(self);
4122 MYDB_BEGIN_ALLOW_THREADS;
4123 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4124 MYDB_END_ALLOW_THREADS;
4125 RETURN_IF_ERR();
4126 RETURN_NONE();
4130 static PyObject*
4131 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4133 int err, max;
4135 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4136 return NULL;
4137 CHECK_ENV_NOT_CLOSED(self);
4139 MYDB_BEGIN_ALLOW_THREADS;
4140 err = self->db_env->set_lk_max(self->db_env, max);
4141 MYDB_END_ALLOW_THREADS;
4142 RETURN_IF_ERR();
4143 RETURN_NONE();
4147 #if (DBVER >= 32)
4149 static PyObject*
4150 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4152 int err, max;
4154 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4155 return NULL;
4156 CHECK_ENV_NOT_CLOSED(self);
4158 MYDB_BEGIN_ALLOW_THREADS;
4159 err = self->db_env->set_lk_max_locks(self->db_env, max);
4160 MYDB_END_ALLOW_THREADS;
4161 RETURN_IF_ERR();
4162 RETURN_NONE();
4166 static PyObject*
4167 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4169 int err, max;
4171 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4172 return NULL;
4173 CHECK_ENV_NOT_CLOSED(self);
4175 MYDB_BEGIN_ALLOW_THREADS;
4176 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4177 MYDB_END_ALLOW_THREADS;
4178 RETURN_IF_ERR();
4179 RETURN_NONE();
4183 static PyObject*
4184 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4186 int err, max;
4188 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4189 return NULL;
4190 CHECK_ENV_NOT_CLOSED(self);
4192 MYDB_BEGIN_ALLOW_THREADS;
4193 err = self->db_env->set_lk_max_objects(self->db_env, max);
4194 MYDB_END_ALLOW_THREADS;
4195 RETURN_IF_ERR();
4196 RETURN_NONE();
4199 #endif
4202 static PyObject*
4203 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4205 int err, mp_mmapsize;
4207 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4208 return NULL;
4209 CHECK_ENV_NOT_CLOSED(self);
4211 MYDB_BEGIN_ALLOW_THREADS;
4212 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4213 MYDB_END_ALLOW_THREADS;
4214 RETURN_IF_ERR();
4215 RETURN_NONE();
4219 static PyObject*
4220 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4222 int err;
4223 char *dir;
4225 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4226 return NULL;
4227 CHECK_ENV_NOT_CLOSED(self);
4229 MYDB_BEGIN_ALLOW_THREADS;
4230 err = self->db_env->set_tmp_dir(self->db_env, dir);
4231 MYDB_END_ALLOW_THREADS;
4232 RETURN_IF_ERR();
4233 RETURN_NONE();
4237 static PyObject*
4238 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4240 int flags = 0;
4241 PyObject* txnobj = NULL;
4242 DB_TXN *txn = NULL;
4243 static char* kwnames[] = { "parent", "flags", NULL };
4245 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4246 &txnobj, &flags))
4247 return NULL;
4249 if (!checkTxnObj(txnobj, &txn))
4250 return NULL;
4251 CHECK_ENV_NOT_CLOSED(self);
4253 return (PyObject*)newDBTxnObject(self, txn, flags);
4257 static PyObject*
4258 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4260 int err, kbyte=0, min=0, flags=0;
4262 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4263 return NULL;
4264 CHECK_ENV_NOT_CLOSED(self);
4266 MYDB_BEGIN_ALLOW_THREADS;
4267 #if (DBVER >= 40)
4268 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4269 #else
4270 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4271 #endif
4272 MYDB_END_ALLOW_THREADS;
4273 RETURN_IF_ERR();
4274 RETURN_NONE();
4278 static PyObject*
4279 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4281 int err, max;
4283 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4284 return NULL;
4285 CHECK_ENV_NOT_CLOSED(self);
4287 err = self->db_env->set_tx_max(self->db_env, max);
4288 RETURN_IF_ERR();
4289 RETURN_NONE();
4293 static PyObject*
4294 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4296 int err;
4297 long stamp;
4298 time_t timestamp;
4300 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4301 return NULL;
4302 CHECK_ENV_NOT_CLOSED(self);
4303 timestamp = (time_t)stamp;
4304 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4305 RETURN_IF_ERR();
4306 RETURN_NONE();
4310 static PyObject*
4311 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4313 int err, atype, flags=0;
4314 int aborted = 0;
4316 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4317 return NULL;
4318 CHECK_ENV_NOT_CLOSED(self);
4320 MYDB_BEGIN_ALLOW_THREADS;
4321 #if (DBVER >= 40)
4322 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4323 #else
4324 err = lock_detect(self->db_env, flags, atype, &aborted);
4325 #endif
4326 MYDB_END_ALLOW_THREADS;
4327 RETURN_IF_ERR();
4328 return PyInt_FromLong(aborted);
4332 static PyObject*
4333 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4335 int flags=0;
4336 int locker, lock_mode;
4337 DBT obj;
4338 PyObject* objobj;
4340 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4341 return NULL;
4344 if (!make_dbt(objobj, &obj))
4345 return NULL;
4347 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4351 static PyObject*
4352 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4354 int err;
4355 u_int32_t theID;
4357 if (!PyArg_ParseTuple(args, ":lock_id"))
4358 return NULL;
4360 CHECK_ENV_NOT_CLOSED(self);
4361 MYDB_BEGIN_ALLOW_THREADS;
4362 #if (DBVER >= 40)
4363 err = self->db_env->lock_id(self->db_env, &theID);
4364 #else
4365 err = lock_id(self->db_env, &theID);
4366 #endif
4367 MYDB_END_ALLOW_THREADS;
4368 RETURN_IF_ERR();
4370 return PyInt_FromLong((long)theID);
4374 static PyObject*
4375 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4377 int err;
4378 DBLockObject* dblockobj;
4380 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4381 return NULL;
4383 CHECK_ENV_NOT_CLOSED(self);
4384 MYDB_BEGIN_ALLOW_THREADS;
4385 #if (DBVER >= 40)
4386 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4387 #else
4388 err = lock_put(self->db_env, &dblockobj->lock);
4389 #endif
4390 MYDB_END_ALLOW_THREADS;
4391 RETURN_IF_ERR();
4392 RETURN_NONE();
4395 #if (DBVER >= 44)
4396 static PyObject*
4397 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4399 int err;
4400 char *file;
4401 u_int32_t flags = 0;
4402 static char* kwnames[] = { "file", "flags", NULL};
4404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4405 &file, &flags))
4406 return NULL;
4407 CHECK_ENV_NOT_CLOSED(self);
4409 MYDB_BEGIN_ALLOW_THREADS;
4410 err = self->db_env->lsn_reset(self->db_env, file, flags);
4411 MYDB_END_ALLOW_THREADS;
4412 RETURN_IF_ERR();
4413 RETURN_NONE();
4415 #endif /* DBVER >= 4.4 */
4417 #if (DBVER >= 40)
4418 static PyObject*
4419 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4421 int err;
4422 DB_LOG_STAT* statp = NULL;
4423 PyObject* d = NULL;
4424 u_int32_t flags = 0;
4426 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4427 return NULL;
4428 CHECK_ENV_NOT_CLOSED(self);
4430 MYDB_BEGIN_ALLOW_THREADS;
4431 err = self->db_env->log_stat(self->db_env, &statp, flags);
4432 MYDB_END_ALLOW_THREADS;
4433 RETURN_IF_ERR();
4435 /* Turn the stat structure into a dictionary */
4436 d = PyDict_New();
4437 if (d == NULL) {
4438 if (statp)
4439 free(statp);
4440 return NULL;
4443 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4445 MAKE_ENTRY(magic);
4446 MAKE_ENTRY(version);
4447 MAKE_ENTRY(mode);
4448 MAKE_ENTRY(lg_bsize);
4449 #if (DBVER >= 44)
4450 MAKE_ENTRY(lg_size);
4451 MAKE_ENTRY(record);
4452 #endif
4453 #if (DBVER <= 40)
4454 MAKE_ENTRY(lg_max);
4455 #endif
4456 MAKE_ENTRY(w_mbytes);
4457 MAKE_ENTRY(w_bytes);
4458 MAKE_ENTRY(wc_mbytes);
4459 MAKE_ENTRY(wc_bytes);
4460 MAKE_ENTRY(wcount);
4461 MAKE_ENTRY(wcount_fill);
4462 #if (DBVER >= 44)
4463 MAKE_ENTRY(rcount);
4464 #endif
4465 MAKE_ENTRY(scount);
4466 MAKE_ENTRY(cur_file);
4467 MAKE_ENTRY(cur_offset);
4468 MAKE_ENTRY(disk_file);
4469 MAKE_ENTRY(disk_offset);
4470 MAKE_ENTRY(maxcommitperflush);
4471 MAKE_ENTRY(mincommitperflush);
4472 MAKE_ENTRY(regsize);
4473 MAKE_ENTRY(region_wait);
4474 MAKE_ENTRY(region_nowait);
4476 #undef MAKE_ENTRY
4477 free(statp);
4478 return d;
4479 } /* DBEnv_log_stat */
4480 #endif /* DBVER >= 4.0 for log_stat method */
4483 static PyObject*
4484 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4486 int err;
4487 DB_LOCK_STAT* sp;
4488 PyObject* d = NULL;
4489 u_int32_t flags = 0;
4491 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4492 return NULL;
4493 CHECK_ENV_NOT_CLOSED(self);
4495 MYDB_BEGIN_ALLOW_THREADS;
4496 #if (DBVER >= 40)
4497 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4498 #else
4499 #if (DBVER >= 33)
4500 err = lock_stat(self->db_env, &sp);
4501 #else
4502 err = lock_stat(self->db_env, &sp, NULL);
4503 #endif
4504 #endif
4505 MYDB_END_ALLOW_THREADS;
4506 RETURN_IF_ERR();
4508 /* Turn the stat structure into a dictionary */
4509 d = PyDict_New();
4510 if (d == NULL) {
4511 free(sp);
4512 return NULL;
4515 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4517 #if (DBVER < 41)
4518 MAKE_ENTRY(lastid);
4519 #endif
4520 MAKE_ENTRY(nmodes);
4521 #if (DBVER >= 32)
4522 MAKE_ENTRY(maxlocks);
4523 MAKE_ENTRY(maxlockers);
4524 MAKE_ENTRY(maxobjects);
4525 MAKE_ENTRY(nlocks);
4526 MAKE_ENTRY(maxnlocks);
4527 #endif
4528 MAKE_ENTRY(nlockers);
4529 MAKE_ENTRY(maxnlockers);
4530 #if (DBVER >= 32)
4531 MAKE_ENTRY(nobjects);
4532 MAKE_ENTRY(maxnobjects);
4533 #endif
4534 MAKE_ENTRY(nrequests);
4535 MAKE_ENTRY(nreleases);
4536 #if (DBVER < 44)
4537 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4538 MAKE_ENTRY(nconflicts);
4539 #else
4540 MAKE_ENTRY(lock_nowait);
4541 MAKE_ENTRY(lock_wait);
4542 #endif
4543 MAKE_ENTRY(ndeadlocks);
4544 MAKE_ENTRY(regsize);
4545 MAKE_ENTRY(region_wait);
4546 MAKE_ENTRY(region_nowait);
4548 #undef MAKE_ENTRY
4549 free(sp);
4550 return d;
4554 static PyObject*
4555 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4557 int flags=0;
4558 int err;
4559 char **log_list = NULL;
4560 PyObject* list;
4561 PyObject* item = NULL;
4563 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4564 return NULL;
4566 CHECK_ENV_NOT_CLOSED(self);
4567 MYDB_BEGIN_ALLOW_THREADS;
4568 #if (DBVER >= 40)
4569 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4570 #elif (DBVER == 33)
4571 err = log_archive(self->db_env, &log_list, flags);
4572 #else
4573 err = log_archive(self->db_env, &log_list, flags, NULL);
4574 #endif
4575 MYDB_END_ALLOW_THREADS;
4576 RETURN_IF_ERR();
4578 list = PyList_New(0);
4579 if (list == NULL) {
4580 if (log_list)
4581 free(log_list);
4582 return NULL;
4585 if (log_list) {
4586 char **log_list_start;
4587 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4588 item = PyString_FromString (*log_list);
4589 if (item == NULL) {
4590 Py_DECREF(list);
4591 list = NULL;
4592 break;
4594 PyList_Append(list, item);
4595 Py_DECREF(item);
4597 free(log_list_start);
4599 return list;
4603 static PyObject*
4604 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4606 int err;
4607 DB_TXN_STAT* sp;
4608 PyObject* d = NULL;
4609 u_int32_t flags=0;
4611 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4612 return NULL;
4613 CHECK_ENV_NOT_CLOSED(self);
4615 MYDB_BEGIN_ALLOW_THREADS;
4616 #if (DBVER >= 40)
4617 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4618 #elif (DBVER == 33)
4619 err = txn_stat(self->db_env, &sp);
4620 #else
4621 err = txn_stat(self->db_env, &sp, NULL);
4622 #endif
4623 MYDB_END_ALLOW_THREADS;
4624 RETURN_IF_ERR();
4626 /* Turn the stat structure into a dictionary */
4627 d = PyDict_New();
4628 if (d == NULL) {
4629 free(sp);
4630 return NULL;
4633 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4635 MAKE_ENTRY(time_ckp);
4636 MAKE_ENTRY(last_txnid);
4637 MAKE_ENTRY(maxtxns);
4638 MAKE_ENTRY(nactive);
4639 MAKE_ENTRY(maxnactive);
4640 MAKE_ENTRY(nbegins);
4641 MAKE_ENTRY(naborts);
4642 MAKE_ENTRY(ncommits);
4643 MAKE_ENTRY(regsize);
4644 MAKE_ENTRY(region_wait);
4645 MAKE_ENTRY(region_nowait);
4647 #undef MAKE_ENTRY
4648 free(sp);
4649 return d;
4653 static PyObject*
4654 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4656 int flags=0;
4657 int oldValue=0;
4659 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4660 return NULL;
4661 CHECK_ENV_NOT_CLOSED(self);
4663 if (self->moduleFlags.getReturnsNone)
4664 ++oldValue;
4665 if (self->moduleFlags.cursorSetReturnsNone)
4666 ++oldValue;
4667 self->moduleFlags.getReturnsNone = (flags >= 1);
4668 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4669 return PyInt_FromLong(oldValue);
4673 /* --------------------------------------------------------------------- */
4674 /* DBTxn methods */
4677 static PyObject*
4678 DBTxn_commit(DBTxnObject* self, PyObject* args)
4680 int flags=0, err;
4681 DB_TXN *txn;
4683 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4684 return NULL;
4686 if (!self->txn) {
4687 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4688 "after txn_commit or txn_abort");
4689 PyErr_SetObject(DBError, t);
4690 Py_DECREF(t);
4691 return NULL;
4693 txn = self->txn;
4694 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4695 MYDB_BEGIN_ALLOW_THREADS;
4696 #if (DBVER >= 40)
4697 err = txn->commit(txn, flags);
4698 #else
4699 err = txn_commit(txn, flags);
4700 #endif
4701 MYDB_END_ALLOW_THREADS;
4702 RETURN_IF_ERR();
4703 RETURN_NONE();
4706 static PyObject*
4707 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4709 #if (DBVER >= 33)
4710 int err;
4711 char* gid=NULL;
4712 int gid_size=0;
4714 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4715 return NULL;
4717 if (gid_size != DB_XIDDATASIZE) {
4718 PyErr_SetString(PyExc_TypeError,
4719 "gid must be DB_XIDDATASIZE bytes long");
4720 return NULL;
4723 if (!self->txn) {
4724 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4725 "after txn_commit or txn_abort");
4726 PyErr_SetObject(DBError, t);
4727 Py_DECREF(t);
4728 return NULL;
4730 MYDB_BEGIN_ALLOW_THREADS;
4731 #if (DBVER >= 40)
4732 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4733 #else
4734 err = txn_prepare(self->txn, (u_int8_t*)gid);
4735 #endif
4736 MYDB_END_ALLOW_THREADS;
4737 RETURN_IF_ERR();
4738 RETURN_NONE();
4739 #else
4740 int err;
4742 if (!PyArg_ParseTuple(args, ":prepare"))
4743 return NULL;
4745 if (!self->txn) {
4746 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4747 "after txn_commit or txn_abort");
4748 PyErr_SetObject(DBError, t);
4749 Py_DECREF(t);
4750 return NULL;
4752 MYDB_BEGIN_ALLOW_THREADS;
4753 err = txn_prepare(self->txn);
4754 MYDB_END_ALLOW_THREADS;
4755 RETURN_IF_ERR();
4756 RETURN_NONE();
4757 #endif
4761 static PyObject*
4762 DBTxn_abort(DBTxnObject* self, PyObject* args)
4764 int err;
4765 DB_TXN *txn;
4767 if (!PyArg_ParseTuple(args, ":abort"))
4768 return NULL;
4770 if (!self->txn) {
4771 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4772 "after txn_commit or txn_abort");
4773 PyErr_SetObject(DBError, t);
4774 Py_DECREF(t);
4775 return NULL;
4777 txn = self->txn;
4778 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4779 MYDB_BEGIN_ALLOW_THREADS;
4780 #if (DBVER >= 40)
4781 err = txn->abort(txn);
4782 #else
4783 err = txn_abort(txn);
4784 #endif
4785 MYDB_END_ALLOW_THREADS;
4786 RETURN_IF_ERR();
4787 RETURN_NONE();
4791 static PyObject*
4792 DBTxn_id(DBTxnObject* self, PyObject* args)
4794 int id;
4796 if (!PyArg_ParseTuple(args, ":id"))
4797 return NULL;
4799 if (!self->txn) {
4800 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4801 "after txn_commit or txn_abort");
4802 PyErr_SetObject(DBError, t);
4803 Py_DECREF(t);
4804 return NULL;
4806 MYDB_BEGIN_ALLOW_THREADS;
4807 #if (DBVER >= 40)
4808 id = self->txn->id(self->txn);
4809 #else
4810 id = txn_id(self->txn);
4811 #endif
4812 MYDB_END_ALLOW_THREADS;
4813 return PyInt_FromLong(id);
4816 #if (DBVER >= 43)
4817 /* --------------------------------------------------------------------- */
4818 /* DBSequence methods */
4821 static PyObject*
4822 DBSequence_close(DBSequenceObject* self, PyObject* args)
4824 int err, flags=0;
4825 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4826 return NULL;
4827 CHECK_SEQUENCE_NOT_CLOSED(self)
4829 MYDB_BEGIN_ALLOW_THREADS
4830 err = self->sequence->close(self->sequence, flags);
4831 self->sequence = NULL;
4832 MYDB_END_ALLOW_THREADS
4834 RETURN_IF_ERR();
4836 RETURN_NONE();
4839 static PyObject*
4840 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4842 int err, flags = 0;
4843 int delta = 1;
4844 db_seq_t value;
4845 PyObject *txnobj = NULL;
4846 DB_TXN *txn = NULL;
4847 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4849 return NULL;
4850 CHECK_SEQUENCE_NOT_CLOSED(self)
4852 if (!checkTxnObj(txnobj, &txn))
4853 return NULL;
4855 MYDB_BEGIN_ALLOW_THREADS
4856 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4857 MYDB_END_ALLOW_THREADS
4859 RETURN_IF_ERR();
4860 return PyLong_FromLongLong(value);
4864 static PyObject*
4865 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4867 if (!PyArg_ParseTuple(args,":get_dbp"))
4868 return NULL;
4869 CHECK_SEQUENCE_NOT_CLOSED(self)
4870 Py_INCREF(self->mydb);
4871 return (PyObject* )self->mydb;
4874 static PyObject*
4875 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4877 int err;
4878 DBT key;
4879 CHECK_SEQUENCE_NOT_CLOSED(self)
4880 MYDB_BEGIN_ALLOW_THREADS
4881 err = self->sequence->get_key(self->sequence, &key);
4882 MYDB_END_ALLOW_THREADS
4884 RETURN_IF_ERR();
4886 return PyString_FromStringAndSize(key.data, key.size);
4889 static PyObject*
4890 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4892 int err;
4893 db_seq_t value;
4894 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4895 return NULL;
4896 CHECK_SEQUENCE_NOT_CLOSED(self)
4898 MYDB_BEGIN_ALLOW_THREADS
4899 err = self->sequence->initial_value(self->sequence, value);
4900 MYDB_END_ALLOW_THREADS
4902 RETURN_IF_ERR();
4904 RETURN_NONE();
4907 static PyObject*
4908 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4910 int err, flags = 0;
4911 PyObject* keyobj;
4912 PyObject *txnobj = NULL;
4913 DB_TXN *txn = NULL;
4914 DBT key;
4916 static char* kwnames[] = {"key", "txn", "flags", NULL };
4917 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4918 return NULL;
4920 if (!checkTxnObj(txnobj, &txn))
4921 return NULL;
4923 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4924 return NULL;
4926 MYDB_BEGIN_ALLOW_THREADS
4927 err = self->sequence->open(self->sequence, txn, &key, flags);
4928 MYDB_END_ALLOW_THREADS
4930 CLEAR_DBT(key);
4931 RETURN_IF_ERR();
4933 RETURN_NONE();
4936 static PyObject*
4937 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4939 int err, flags = 0;
4940 PyObject *txnobj = NULL;
4941 DB_TXN *txn = NULL;
4943 static char* kwnames[] = {"txn", "flags", NULL };
4944 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4945 return NULL;
4947 if (!checkTxnObj(txnobj, &txn))
4948 return NULL;
4950 CHECK_SEQUENCE_NOT_CLOSED(self)
4952 MYDB_BEGIN_ALLOW_THREADS
4953 err = self->sequence->remove(self->sequence, txn, flags);
4954 MYDB_END_ALLOW_THREADS
4956 RETURN_IF_ERR();
4957 RETURN_NONE();
4960 static PyObject*
4961 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4963 int err, size;
4964 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4965 return NULL;
4966 CHECK_SEQUENCE_NOT_CLOSED(self)
4968 MYDB_BEGIN_ALLOW_THREADS
4969 err = self->sequence->set_cachesize(self->sequence, size);
4970 MYDB_END_ALLOW_THREADS
4972 RETURN_IF_ERR();
4973 RETURN_NONE();
4976 static PyObject*
4977 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4979 int err, size;
4980 if (!PyArg_ParseTuple(args,":get_cachesize"))
4981 return NULL;
4982 CHECK_SEQUENCE_NOT_CLOSED(self)
4984 MYDB_BEGIN_ALLOW_THREADS
4985 err = self->sequence->get_cachesize(self->sequence, &size);
4986 MYDB_END_ALLOW_THREADS
4988 RETURN_IF_ERR();
4989 return PyInt_FromLong(size);
4992 static PyObject*
4993 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4995 int err, flags = 0;
4996 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4997 return NULL;
4998 CHECK_SEQUENCE_NOT_CLOSED(self)
5000 MYDB_BEGIN_ALLOW_THREADS
5001 err = self->sequence->set_flags(self->sequence, flags);
5002 MYDB_END_ALLOW_THREADS
5004 RETURN_IF_ERR();
5005 RETURN_NONE();
5009 static PyObject*
5010 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5012 unsigned int flags;
5013 int err;
5014 if (!PyArg_ParseTuple(args,":get_flags"))
5015 return NULL;
5016 CHECK_SEQUENCE_NOT_CLOSED(self)
5018 MYDB_BEGIN_ALLOW_THREADS
5019 err = self->sequence->get_flags(self->sequence, &flags);
5020 MYDB_END_ALLOW_THREADS
5022 RETURN_IF_ERR();
5023 return PyInt_FromLong((int)flags);
5026 static PyObject*
5027 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5029 int err;
5030 db_seq_t min, max;
5031 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
5032 return NULL;
5033 CHECK_SEQUENCE_NOT_CLOSED(self)
5035 MYDB_BEGIN_ALLOW_THREADS
5036 err = self->sequence->set_range(self->sequence, min, max);
5037 MYDB_END_ALLOW_THREADS
5039 RETURN_IF_ERR();
5040 RETURN_NONE();
5043 static PyObject*
5044 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5046 int err;
5047 db_seq_t min, max;
5048 if (!PyArg_ParseTuple(args,":get_range"))
5049 return NULL;
5050 CHECK_SEQUENCE_NOT_CLOSED(self)
5052 MYDB_BEGIN_ALLOW_THREADS
5053 err = self->sequence->get_range(self->sequence, &min, &max);
5054 MYDB_END_ALLOW_THREADS
5056 RETURN_IF_ERR();
5057 return Py_BuildValue("(LL)", min, max);
5060 static PyObject*
5061 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5063 int err, flags = 0;
5064 DB_SEQUENCE_STAT* sp = NULL;
5065 PyObject* dict_stat;
5066 static char* kwnames[] = {"flags", NULL };
5067 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5068 return NULL;
5069 CHECK_SEQUENCE_NOT_CLOSED(self);
5071 MYDB_BEGIN_ALLOW_THREADS;
5072 err = self->sequence->stat(self->sequence, &sp, flags);
5073 MYDB_END_ALLOW_THREADS;
5074 RETURN_IF_ERR();
5076 if ((dict_stat = PyDict_New()) == NULL) {
5077 free(sp);
5078 return NULL;
5082 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5083 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5085 MAKE_INT_ENTRY(wait);
5086 MAKE_INT_ENTRY(nowait);
5087 MAKE_LONG_LONG_ENTRY(current);
5088 MAKE_LONG_LONG_ENTRY(value);
5089 MAKE_LONG_LONG_ENTRY(last_value);
5090 MAKE_LONG_LONG_ENTRY(min);
5091 MAKE_LONG_LONG_ENTRY(max);
5092 MAKE_INT_ENTRY(cache_size);
5093 MAKE_INT_ENTRY(flags);
5095 #undef MAKE_INT_ENTRY
5096 #undef MAKE_LONG_LONG_ENTRY
5098 free(sp);
5099 return dict_stat;
5101 #endif
5104 /* --------------------------------------------------------------------- */
5105 /* Method definition tables and type objects */
5107 static PyMethodDef DB_methods[] = {
5108 {"append", (PyCFunction)DB_append, METH_VARARGS},
5109 #if (DBVER >= 33)
5110 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5111 #endif
5112 {"close", (PyCFunction)DB_close, METH_VARARGS},
5113 #if (DBVER >= 32)
5114 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5115 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5116 #endif
5117 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5118 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5119 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5120 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5121 #if (DBVER >= 33)
5122 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5123 #endif
5124 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5125 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5126 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5127 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5128 {"join", (PyCFunction)DB_join, METH_VARARGS},
5129 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5130 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5131 {"items", (PyCFunction)DB_items, METH_VARARGS},
5132 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5133 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5134 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5135 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5136 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5137 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5138 #if (DBVER >= 33)
5139 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5140 #endif
5141 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5142 #if (DBVER >= 41)
5143 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5144 #endif
5145 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5146 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5147 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5148 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5149 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5150 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5151 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5152 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5153 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5154 #if (DBVER >= 32)
5155 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5156 #endif
5157 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5158 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5159 #if (DBVER >= 33)
5160 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5161 #endif
5162 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5163 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5164 {"values", (PyCFunction)DB_values, METH_VARARGS},
5165 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5166 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5167 {NULL, NULL} /* sentinel */
5171 static PyMappingMethods DB_mapping = {
5172 DB_length, /*mp_length*/
5173 (binaryfunc)DB_subscript, /*mp_subscript*/
5174 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5178 static PyMethodDef DBCursor_methods[] = {
5179 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5180 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5181 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5182 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5183 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5184 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5185 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5186 #if (DBVER >= 33)
5187 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5188 #endif
5189 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5190 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5191 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5192 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5193 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5194 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5195 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5196 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5197 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5198 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5199 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5200 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5201 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5202 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5203 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5204 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5205 {NULL, NULL} /* sentinel */
5209 static PyMethodDef DBEnv_methods[] = {
5210 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5211 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5212 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5213 #if (DBVER >= 41)
5214 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5215 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5216 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5217 #endif
5218 #if (DBVER >= 40)
5219 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5220 #endif
5221 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5222 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5223 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5224 #if (DBVER >= 32)
5225 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5226 #endif
5227 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5228 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5229 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5230 #if (DBVER >= 33)
5231 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5232 #endif
5233 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5234 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5235 #if (DBVER >= 32)
5236 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5237 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5238 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5239 #endif
5240 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5241 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5242 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5243 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5244 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5245 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5246 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5247 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5248 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5249 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5250 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5251 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5252 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5253 #if (DBVER >= 40)
5254 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5255 #endif
5256 #if (DBVER >= 44)
5257 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5258 #endif
5259 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5260 {NULL, NULL} /* sentinel */
5264 static PyMethodDef DBTxn_methods[] = {
5265 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5266 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5267 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5268 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5269 {NULL, NULL} /* sentinel */
5273 #if (DBVER >= 43)
5274 static PyMethodDef DBSequence_methods[] = {
5275 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5276 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5277 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5278 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5279 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5280 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5281 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5282 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5283 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5284 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5285 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5286 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5287 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5288 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5289 {NULL, NULL} /* sentinel */
5291 #endif
5294 static PyObject*
5295 DB_getattr(DBObject* self, char *name)
5297 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5301 static PyObject*
5302 DBEnv_getattr(DBEnvObject* self, char *name)
5304 if (!strcmp(name, "db_home")) {
5305 CHECK_ENV_NOT_CLOSED(self);
5306 if (self->db_env->db_home == NULL) {
5307 RETURN_NONE();
5309 return PyString_FromString(self->db_env->db_home);
5312 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5316 static PyObject*
5317 DBCursor_getattr(DBCursorObject* self, char *name)
5319 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5322 static PyObject*
5323 DBTxn_getattr(DBTxnObject* self, char *name)
5325 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5328 static PyObject*
5329 DBLock_getattr(DBLockObject* self, char *name)
5331 return NULL;
5334 #if (DBVER >= 43)
5335 static PyObject*
5336 DBSequence_getattr(DBSequenceObject* self, char *name)
5338 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5340 #endif
5342 statichere PyTypeObject DB_Type = {
5343 PyObject_HEAD_INIT(NULL)
5344 0, /*ob_size*/
5345 "DB", /*tp_name*/
5346 sizeof(DBObject), /*tp_basicsize*/
5347 0, /*tp_itemsize*/
5348 /* methods */
5349 (destructor)DB_dealloc, /*tp_dealloc*/
5350 0, /*tp_print*/
5351 (getattrfunc)DB_getattr, /*tp_getattr*/
5352 0, /*tp_setattr*/
5353 0, /*tp_compare*/
5354 0, /*tp_repr*/
5355 0, /*tp_as_number*/
5356 0, /*tp_as_sequence*/
5357 &DB_mapping,/*tp_as_mapping*/
5358 0, /*tp_hash*/
5359 #ifdef HAVE_WEAKREF
5360 0, /* tp_call */
5361 0, /* tp_str */
5362 0, /* tp_getattro */
5363 0, /* tp_setattro */
5364 0, /* tp_as_buffer */
5365 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5366 0, /* tp_doc */
5367 0, /* tp_traverse */
5368 0, /* tp_clear */
5369 0, /* tp_richcompare */
5370 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5371 #endif
5375 statichere PyTypeObject DBCursor_Type = {
5376 PyObject_HEAD_INIT(NULL)
5377 0, /*ob_size*/
5378 "DBCursor", /*tp_name*/
5379 sizeof(DBCursorObject), /*tp_basicsize*/
5380 0, /*tp_itemsize*/
5381 /* methods */
5382 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5383 0, /*tp_print*/
5384 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5385 0, /*tp_setattr*/
5386 0, /*tp_compare*/
5387 0, /*tp_repr*/
5388 0, /*tp_as_number*/
5389 0, /*tp_as_sequence*/
5390 0, /*tp_as_mapping*/
5391 0, /*tp_hash*/
5392 #ifdef HAVE_WEAKREF
5393 0, /* tp_call */
5394 0, /* tp_str */
5395 0, /* tp_getattro */
5396 0, /* tp_setattro */
5397 0, /* tp_as_buffer */
5398 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5399 0, /* tp_doc */
5400 0, /* tp_traverse */
5401 0, /* tp_clear */
5402 0, /* tp_richcompare */
5403 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5404 #endif
5408 statichere PyTypeObject DBEnv_Type = {
5409 PyObject_HEAD_INIT(NULL)
5410 0, /*ob_size*/
5411 "DBEnv", /*tp_name*/
5412 sizeof(DBEnvObject), /*tp_basicsize*/
5413 0, /*tp_itemsize*/
5414 /* methods */
5415 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5416 0, /*tp_print*/
5417 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5418 0, /*tp_setattr*/
5419 0, /*tp_compare*/
5420 0, /*tp_repr*/
5421 0, /*tp_as_number*/
5422 0, /*tp_as_sequence*/
5423 0, /*tp_as_mapping*/
5424 0, /*tp_hash*/
5425 #ifdef HAVE_WEAKREF
5426 0, /* tp_call */
5427 0, /* tp_str */
5428 0, /* tp_getattro */
5429 0, /* tp_setattro */
5430 0, /* tp_as_buffer */
5431 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5432 0, /* tp_doc */
5433 0, /* tp_traverse */
5434 0, /* tp_clear */
5435 0, /* tp_richcompare */
5436 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5437 #endif
5440 statichere PyTypeObject DBTxn_Type = {
5441 PyObject_HEAD_INIT(NULL)
5442 0, /*ob_size*/
5443 "DBTxn", /*tp_name*/
5444 sizeof(DBTxnObject), /*tp_basicsize*/
5445 0, /*tp_itemsize*/
5446 /* methods */
5447 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5448 0, /*tp_print*/
5449 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5450 0, /*tp_setattr*/
5451 0, /*tp_compare*/
5452 0, /*tp_repr*/
5453 0, /*tp_as_number*/
5454 0, /*tp_as_sequence*/
5455 0, /*tp_as_mapping*/
5456 0, /*tp_hash*/
5457 #ifdef HAVE_WEAKREF
5458 0, /* tp_call */
5459 0, /* tp_str */
5460 0, /* tp_getattro */
5461 0, /* tp_setattro */
5462 0, /* tp_as_buffer */
5463 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5464 0, /* tp_doc */
5465 0, /* tp_traverse */
5466 0, /* tp_clear */
5467 0, /* tp_richcompare */
5468 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5469 #endif
5473 statichere PyTypeObject DBLock_Type = {
5474 PyObject_HEAD_INIT(NULL)
5475 0, /*ob_size*/
5476 "DBLock", /*tp_name*/
5477 sizeof(DBLockObject), /*tp_basicsize*/
5478 0, /*tp_itemsize*/
5479 /* methods */
5480 (destructor)DBLock_dealloc, /*tp_dealloc*/
5481 0, /*tp_print*/
5482 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5483 0, /*tp_setattr*/
5484 0, /*tp_compare*/
5485 0, /*tp_repr*/
5486 0, /*tp_as_number*/
5487 0, /*tp_as_sequence*/
5488 0, /*tp_as_mapping*/
5489 0, /*tp_hash*/
5490 #ifdef HAVE_WEAKREF
5491 0, /* tp_call */
5492 0, /* tp_str */
5493 0, /* tp_getattro */
5494 0, /* tp_setattro */
5495 0, /* tp_as_buffer */
5496 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5497 0, /* tp_doc */
5498 0, /* tp_traverse */
5499 0, /* tp_clear */
5500 0, /* tp_richcompare */
5501 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5502 #endif
5505 #if (DBVER >= 43)
5506 statichere PyTypeObject DBSequence_Type = {
5507 PyObject_HEAD_INIT(NULL)
5508 0, /*ob_size*/
5509 "DBSequence", /*tp_name*/
5510 sizeof(DBSequenceObject), /*tp_basicsize*/
5511 0, /*tp_itemsize*/
5512 /* methods */
5513 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5514 0, /*tp_print*/
5515 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5516 0, /*tp_setattr*/
5517 0, /*tp_compare*/
5518 0, /*tp_repr*/
5519 0, /*tp_as_number*/
5520 0, /*tp_as_sequence*/
5521 0, /*tp_as_mapping*/
5522 0, /*tp_hash*/
5523 #ifdef HAVE_WEAKREF
5524 0, /* tp_call */
5525 0, /* tp_str */
5526 0, /* tp_getattro */
5527 0, /* tp_setattro */
5528 0, /* tp_as_buffer */
5529 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5530 0, /* tp_doc */
5531 0, /* tp_traverse */
5532 0, /* tp_clear */
5533 0, /* tp_richcompare */
5534 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5535 #endif
5537 #endif
5539 /* --------------------------------------------------------------------- */
5540 /* Module-level functions */
5542 static PyObject*
5543 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5545 PyObject* dbenvobj = NULL;
5546 int flags = 0;
5547 static char* kwnames[] = { "dbEnv", "flags", NULL};
5549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5550 &dbenvobj, &flags))
5551 return NULL;
5552 if (dbenvobj == Py_None)
5553 dbenvobj = NULL;
5554 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5555 makeTypeError("DBEnv", dbenvobj);
5556 return NULL;
5559 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5563 static PyObject*
5564 DBEnv_construct(PyObject* self, PyObject* args)
5566 int flags = 0;
5567 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5568 return (PyObject* )newDBEnvObject(flags);
5571 #if (DBVER >= 43)
5572 static PyObject*
5573 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5575 PyObject* dbobj;
5576 int flags = 0;
5577 static char* kwnames[] = { "db", "flags", NULL};
5579 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5580 return NULL;
5581 if (!DBObject_Check(dbobj)) {
5582 makeTypeError("DB", dbobj);
5583 return NULL;
5585 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5587 #endif
5589 static char bsddb_version_doc[] =
5590 "Returns a tuple of major, minor, and patch release numbers of the\n\
5591 underlying DB library.";
5593 static PyObject*
5594 bsddb_version(PyObject* self, PyObject* args)
5596 int major, minor, patch;
5598 if (!PyArg_ParseTuple(args, ":version"))
5599 return NULL;
5600 db_version(&major, &minor, &patch);
5601 return Py_BuildValue("(iii)", major, minor, patch);
5605 /* List of functions defined in the module */
5607 static PyMethodDef bsddb_methods[] = {
5608 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5609 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5610 #if (DBVER >= 43)
5611 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5612 #endif
5613 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5614 {NULL, NULL} /* sentinel */
5618 /* --------------------------------------------------------------------- */
5619 /* Module initialization */
5622 /* Convenience routine to export an integer value.
5623 * Errors are silently ignored, for better or for worse...
5625 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5627 #define MODULE_NAME_MAX_LEN 11
5628 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5630 DL_EXPORT(void) init_bsddb(void)
5632 PyObject* m;
5633 PyObject* d;
5634 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5635 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5636 PyObject* cvsid_s = PyString_FromString( rcs_id );
5638 /* Initialize the type of the new type objects here; doing it here
5639 is required for portability to Windows without requiring C++. */
5640 DB_Type.ob_type = &PyType_Type;
5641 DBCursor_Type.ob_type = &PyType_Type;
5642 DBEnv_Type.ob_type = &PyType_Type;
5643 DBTxn_Type.ob_type = &PyType_Type;
5644 DBLock_Type.ob_type = &PyType_Type;
5645 #if (DBVER >= 43)
5646 DBSequence_Type.ob_type = &PyType_Type;
5647 #endif
5650 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5651 /* Save the current interpreter, so callbacks can do the right thing. */
5652 _db_interpreterState = PyThreadState_GET()->interp;
5653 #endif
5655 /* Create the module and add the functions */
5656 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5657 if (m == NULL)
5658 return;
5660 /* Add some symbolic constants to the module */
5661 d = PyModule_GetDict(m);
5662 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5663 PyDict_SetItemString(d, "cvsid", cvsid_s);
5664 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5665 Py_DECREF(pybsddb_version_s);
5666 pybsddb_version_s = NULL;
5667 Py_DECREF(cvsid_s);
5668 cvsid_s = NULL;
5669 Py_DECREF(db_version_s);
5670 db_version_s = NULL;
5672 ADD_INT(d, DB_VERSION_MAJOR);
5673 ADD_INT(d, DB_VERSION_MINOR);
5674 ADD_INT(d, DB_VERSION_PATCH);
5676 ADD_INT(d, DB_MAX_PAGES);
5677 ADD_INT(d, DB_MAX_RECORDS);
5679 #if (DBVER >= 42)
5680 ADD_INT(d, DB_RPCCLIENT);
5681 #else
5682 ADD_INT(d, DB_CLIENT);
5683 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5684 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5685 #endif
5686 ADD_INT(d, DB_XA_CREATE);
5688 ADD_INT(d, DB_CREATE);
5689 ADD_INT(d, DB_NOMMAP);
5690 ADD_INT(d, DB_THREAD);
5692 ADD_INT(d, DB_FORCE);
5693 ADD_INT(d, DB_INIT_CDB);
5694 ADD_INT(d, DB_INIT_LOCK);
5695 ADD_INT(d, DB_INIT_LOG);
5696 ADD_INT(d, DB_INIT_MPOOL);
5697 ADD_INT(d, DB_INIT_TXN);
5698 #if (DBVER >= 32)
5699 ADD_INT(d, DB_JOINENV);
5700 #endif
5702 ADD_INT(d, DB_RECOVER);
5703 ADD_INT(d, DB_RECOVER_FATAL);
5704 ADD_INT(d, DB_TXN_NOSYNC);
5705 ADD_INT(d, DB_USE_ENVIRON);
5706 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5708 ADD_INT(d, DB_LOCKDOWN);
5709 ADD_INT(d, DB_PRIVATE);
5710 ADD_INT(d, DB_SYSTEM_MEM);
5712 ADD_INT(d, DB_TXN_SYNC);
5713 ADD_INT(d, DB_TXN_NOWAIT);
5715 ADD_INT(d, DB_EXCL);
5716 ADD_INT(d, DB_FCNTL_LOCKING);
5717 ADD_INT(d, DB_ODDFILESIZE);
5718 ADD_INT(d, DB_RDWRMASTER);
5719 ADD_INT(d, DB_RDONLY);
5720 ADD_INT(d, DB_TRUNCATE);
5721 #if (DBVER >= 32)
5722 ADD_INT(d, DB_EXTENT);
5723 ADD_INT(d, DB_CDB_ALLDB);
5724 ADD_INT(d, DB_VERIFY);
5725 #endif
5726 ADD_INT(d, DB_UPGRADE);
5728 ADD_INT(d, DB_AGGRESSIVE);
5729 ADD_INT(d, DB_NOORDERCHK);
5730 ADD_INT(d, DB_ORDERCHKONLY);
5731 ADD_INT(d, DB_PR_PAGE);
5732 #if ! (DBVER >= 33)
5733 ADD_INT(d, DB_VRFY_FLAGMASK);
5734 ADD_INT(d, DB_PR_HEADERS);
5735 #endif
5736 ADD_INT(d, DB_PR_RECOVERYTEST);
5737 ADD_INT(d, DB_SALVAGE);
5739 ADD_INT(d, DB_LOCK_NORUN);
5740 ADD_INT(d, DB_LOCK_DEFAULT);
5741 ADD_INT(d, DB_LOCK_OLDEST);
5742 ADD_INT(d, DB_LOCK_RANDOM);
5743 ADD_INT(d, DB_LOCK_YOUNGEST);
5744 #if (DBVER >= 33)
5745 ADD_INT(d, DB_LOCK_MAXLOCKS);
5746 ADD_INT(d, DB_LOCK_MINLOCKS);
5747 ADD_INT(d, DB_LOCK_MINWRITE);
5748 #endif
5751 #if (DBVER >= 33)
5752 /* docs say to use zero instead */
5753 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5754 #else
5755 ADD_INT(d, DB_LOCK_CONFLICT);
5756 #endif
5758 ADD_INT(d, DB_LOCK_DUMP);
5759 ADD_INT(d, DB_LOCK_GET);
5760 ADD_INT(d, DB_LOCK_INHERIT);
5761 ADD_INT(d, DB_LOCK_PUT);
5762 ADD_INT(d, DB_LOCK_PUT_ALL);
5763 ADD_INT(d, DB_LOCK_PUT_OBJ);
5765 ADD_INT(d, DB_LOCK_NG);
5766 ADD_INT(d, DB_LOCK_READ);
5767 ADD_INT(d, DB_LOCK_WRITE);
5768 ADD_INT(d, DB_LOCK_NOWAIT);
5769 #if (DBVER >= 32)
5770 ADD_INT(d, DB_LOCK_WAIT);
5771 #endif
5772 ADD_INT(d, DB_LOCK_IWRITE);
5773 ADD_INT(d, DB_LOCK_IREAD);
5774 ADD_INT(d, DB_LOCK_IWR);
5775 #if (DBVER >= 33)
5776 #if (DBVER < 44)
5777 ADD_INT(d, DB_LOCK_DIRTY);
5778 #else
5779 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5780 #endif
5781 ADD_INT(d, DB_LOCK_WWRITE);
5782 #endif
5784 ADD_INT(d, DB_LOCK_RECORD);
5785 ADD_INT(d, DB_LOCK_UPGRADE);
5786 #if (DBVER >= 32)
5787 ADD_INT(d, DB_LOCK_SWITCH);
5788 #endif
5789 #if (DBVER >= 33)
5790 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5791 #endif
5793 ADD_INT(d, DB_LOCK_NOWAIT);
5794 ADD_INT(d, DB_LOCK_RECORD);
5795 ADD_INT(d, DB_LOCK_UPGRADE);
5797 #if (DBVER >= 33)
5798 ADD_INT(d, DB_LSTAT_ABORTED);
5799 #if (DBVER < 43)
5800 ADD_INT(d, DB_LSTAT_ERR);
5801 #endif
5802 ADD_INT(d, DB_LSTAT_FREE);
5803 ADD_INT(d, DB_LSTAT_HELD);
5804 #if (DBVER == 33)
5805 ADD_INT(d, DB_LSTAT_NOGRANT);
5806 #endif
5807 ADD_INT(d, DB_LSTAT_PENDING);
5808 ADD_INT(d, DB_LSTAT_WAITING);
5809 #endif
5811 ADD_INT(d, DB_ARCH_ABS);
5812 ADD_INT(d, DB_ARCH_DATA);
5813 ADD_INT(d, DB_ARCH_LOG);
5814 #if (DBVER >= 42)
5815 ADD_INT(d, DB_ARCH_REMOVE);
5816 #endif
5818 ADD_INT(d, DB_BTREE);
5819 ADD_INT(d, DB_HASH);
5820 ADD_INT(d, DB_RECNO);
5821 ADD_INT(d, DB_QUEUE);
5822 ADD_INT(d, DB_UNKNOWN);
5824 ADD_INT(d, DB_DUP);
5825 ADD_INT(d, DB_DUPSORT);
5826 ADD_INT(d, DB_RECNUM);
5827 ADD_INT(d, DB_RENUMBER);
5828 ADD_INT(d, DB_REVSPLITOFF);
5829 ADD_INT(d, DB_SNAPSHOT);
5831 ADD_INT(d, DB_JOIN_NOSORT);
5833 ADD_INT(d, DB_AFTER);
5834 ADD_INT(d, DB_APPEND);
5835 ADD_INT(d, DB_BEFORE);
5836 ADD_INT(d, DB_CACHED_COUNTS);
5837 #if (DBVER >= 41)
5838 _addIntToDict(d, "DB_CHECKPOINT", 0);
5839 #else
5840 ADD_INT(d, DB_CHECKPOINT);
5841 ADD_INT(d, DB_CURLSN);
5842 #endif
5843 #if ((DBVER >= 33) && (DBVER <= 41))
5844 ADD_INT(d, DB_COMMIT);
5845 #endif
5846 ADD_INT(d, DB_CONSUME);
5847 #if (DBVER >= 32)
5848 ADD_INT(d, DB_CONSUME_WAIT);
5849 #endif
5850 ADD_INT(d, DB_CURRENT);
5851 #if (DBVER >= 33)
5852 ADD_INT(d, DB_FAST_STAT);
5853 #endif
5854 ADD_INT(d, DB_FIRST);
5855 ADD_INT(d, DB_FLUSH);
5856 ADD_INT(d, DB_GET_BOTH);
5857 ADD_INT(d, DB_GET_RECNO);
5858 ADD_INT(d, DB_JOIN_ITEM);
5859 ADD_INT(d, DB_KEYFIRST);
5860 ADD_INT(d, DB_KEYLAST);
5861 ADD_INT(d, DB_LAST);
5862 ADD_INT(d, DB_NEXT);
5863 ADD_INT(d, DB_NEXT_DUP);
5864 ADD_INT(d, DB_NEXT_NODUP);
5865 ADD_INT(d, DB_NODUPDATA);
5866 ADD_INT(d, DB_NOOVERWRITE);
5867 ADD_INT(d, DB_NOSYNC);
5868 ADD_INT(d, DB_POSITION);
5869 ADD_INT(d, DB_PREV);
5870 ADD_INT(d, DB_PREV_NODUP);
5871 ADD_INT(d, DB_RECORDCOUNT);
5872 ADD_INT(d, DB_SET);
5873 ADD_INT(d, DB_SET_RANGE);
5874 ADD_INT(d, DB_SET_RECNO);
5875 ADD_INT(d, DB_WRITECURSOR);
5877 ADD_INT(d, DB_OPFLAGS_MASK);
5878 ADD_INT(d, DB_RMW);
5879 #if (DBVER >= 33)
5880 ADD_INT(d, DB_DIRTY_READ);
5881 ADD_INT(d, DB_MULTIPLE);
5882 ADD_INT(d, DB_MULTIPLE_KEY);
5883 #endif
5885 #if (DBVER >= 44)
5886 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5887 ADD_INT(d, DB_READ_COMMITTED);
5888 #endif
5890 #if (DBVER >= 33)
5891 ADD_INT(d, DB_DONOTINDEX);
5892 #endif
5894 #if (DBVER >= 41)
5895 _addIntToDict(d, "DB_INCOMPLETE", 0);
5896 #else
5897 ADD_INT(d, DB_INCOMPLETE);
5898 #endif
5899 ADD_INT(d, DB_KEYEMPTY);
5900 ADD_INT(d, DB_KEYEXIST);
5901 ADD_INT(d, DB_LOCK_DEADLOCK);
5902 ADD_INT(d, DB_LOCK_NOTGRANTED);
5903 ADD_INT(d, DB_NOSERVER);
5904 ADD_INT(d, DB_NOSERVER_HOME);
5905 ADD_INT(d, DB_NOSERVER_ID);
5906 ADD_INT(d, DB_NOTFOUND);
5907 ADD_INT(d, DB_OLD_VERSION);
5908 ADD_INT(d, DB_RUNRECOVERY);
5909 ADD_INT(d, DB_VERIFY_BAD);
5910 #if (DBVER >= 33)
5911 ADD_INT(d, DB_PAGE_NOTFOUND);
5912 ADD_INT(d, DB_SECONDARY_BAD);
5913 #endif
5914 #if (DBVER >= 40)
5915 ADD_INT(d, DB_STAT_CLEAR);
5916 ADD_INT(d, DB_REGION_INIT);
5917 ADD_INT(d, DB_NOLOCKING);
5918 ADD_INT(d, DB_YIELDCPU);
5919 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5920 ADD_INT(d, DB_NOPANIC);
5921 #endif
5923 #if (DBVER >= 42)
5924 ADD_INT(d, DB_TIME_NOTGRANTED);
5925 ADD_INT(d, DB_TXN_NOT_DURABLE);
5926 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5927 ADD_INT(d, DB_LOG_AUTOREMOVE);
5928 ADD_INT(d, DB_DIRECT_LOG);
5929 ADD_INT(d, DB_DIRECT_DB);
5930 ADD_INT(d, DB_INIT_REP);
5931 ADD_INT(d, DB_ENCRYPT);
5932 ADD_INT(d, DB_CHKSUM);
5933 #endif
5935 #if (DBVER >= 43)
5936 ADD_INT(d, DB_LOG_INMEMORY);
5937 ADD_INT(d, DB_BUFFER_SMALL);
5938 ADD_INT(d, DB_SEQ_DEC);
5939 ADD_INT(d, DB_SEQ_INC);
5940 ADD_INT(d, DB_SEQ_WRAP);
5941 #endif
5943 #if (DBVER >= 41)
5944 ADD_INT(d, DB_ENCRYPT_AES);
5945 ADD_INT(d, DB_AUTO_COMMIT);
5946 #else
5947 /* allow berkeleydb 4.1 aware apps to run on older versions */
5948 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5949 #endif
5951 ADD_INT(d, EINVAL);
5952 ADD_INT(d, EACCES);
5953 ADD_INT(d, ENOSPC);
5954 ADD_INT(d, ENOMEM);
5955 ADD_INT(d, EAGAIN);
5956 ADD_INT(d, EBUSY);
5957 ADD_INT(d, EEXIST);
5958 ADD_INT(d, ENOENT);
5959 ADD_INT(d, EPERM);
5961 #if (DBVER >= 40)
5962 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5963 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5964 #endif
5966 /* The exception name must be correct for pickled exception *
5967 * objects to unpickle properly. */
5968 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5969 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5970 #else
5971 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5972 #endif
5974 /* All the rest of the exceptions derive only from DBError */
5975 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5976 PyDict_SetItemString(d, #name, name)
5978 /* The base exception class is DBError */
5979 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5980 MAKE_EX(DBError);
5982 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5983 * from both DBError and KeyError, since the API only supports
5984 * using one base class. */
5985 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5986 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5987 "class DBKeyEmptyError(DBError, KeyError): pass",
5988 Py_file_input, d, d);
5989 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5990 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5991 PyDict_DelItemString(d, "KeyError");
5994 #if !INCOMPLETE_IS_WARNING
5995 MAKE_EX(DBIncompleteError);
5996 #endif
5997 MAKE_EX(DBCursorClosedError);
5998 MAKE_EX(DBKeyEmptyError);
5999 MAKE_EX(DBKeyExistError);
6000 MAKE_EX(DBLockDeadlockError);
6001 MAKE_EX(DBLockNotGrantedError);
6002 MAKE_EX(DBOldVersionError);
6003 MAKE_EX(DBRunRecoveryError);
6004 MAKE_EX(DBVerifyBadError);
6005 MAKE_EX(DBNoServerError);
6006 MAKE_EX(DBNoServerHomeError);
6007 MAKE_EX(DBNoServerIDError);
6008 #if (DBVER >= 33)
6009 MAKE_EX(DBPageNotFoundError);
6010 MAKE_EX(DBSecondaryBadError);
6011 #endif
6013 MAKE_EX(DBInvalidArgError);
6014 MAKE_EX(DBAccessError);
6015 MAKE_EX(DBNoSpaceError);
6016 MAKE_EX(DBNoMemoryError);
6017 MAKE_EX(DBAgainError);
6018 MAKE_EX(DBBusyError);
6019 MAKE_EX(DBFileExistsError);
6020 MAKE_EX(DBNoSuchFileError);
6021 MAKE_EX(DBPermissionsError);
6023 #undef MAKE_EX
6025 /* Check for errors */
6026 if (PyErr_Occurred()) {
6027 PyErr_Print();
6028 Py_FatalError("can't initialize module _bsddb");
6032 /* allow this module to be named _pybsddb so that it can be installed
6033 * and imported on top of python >= 2.3 that includes its own older
6034 * copy of the library named _bsddb without importing the old version. */
6035 DL_EXPORT(void) init_pybsddb(void)
6037 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6038 init_bsddb();