Fix a bunch of parameter strings
[python.git] / Modules / _bsddb.c
blob0822aa9886c730410475a47067d170a07d96f174
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.4"
102 static char *rcs_id = "$Id$";
105 #if (PY_VERSION_HEX < 0x02050000)
106 #define Py_ssize_t int
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;
532 switch (err) {
533 case 0: /* successful, no error */ break;
535 #if (DBVER < 41)
536 case DB_INCOMPLETE:
537 #if INCOMPLETE_IS_WARNING
538 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
539 if (_db_errmsg[0]) {
540 strcat(errTxt, " -- ");
541 strcat(errTxt, _db_errmsg);
542 _db_errmsg[0] = 0;
544 #ifdef HAVE_WARNINGS
545 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
546 #else
547 fprintf(stderr, errTxt);
548 fprintf(stderr, "\n");
549 #endif
551 #else /* do an exception instead */
552 errObj = DBIncompleteError;
553 #endif
554 break;
555 #endif /* DBVER < 41 */
557 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
558 case DB_KEYEXIST: errObj = DBKeyExistError; break;
559 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
560 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
561 case DB_NOTFOUND: errObj = DBNotFoundError; break;
562 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
563 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
564 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
565 case DB_NOSERVER: errObj = DBNoServerError; break;
566 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
567 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
568 #if (DBVER >= 33)
569 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
570 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
571 #endif
572 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
574 #if (DBVER >= 43)
575 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
576 case ENOMEM: errObj = PyExc_MemoryError; break;
577 #endif
578 case EINVAL: errObj = DBInvalidArgError; break;
579 case EACCES: errObj = DBAccessError; break;
580 case ENOSPC: errObj = DBNoSpaceError; break;
581 case EAGAIN: errObj = DBAgainError; break;
582 case EBUSY : errObj = DBBusyError; break;
583 case EEXIST: errObj = DBFileExistsError; break;
584 case ENOENT: errObj = DBNoSuchFileError; break;
585 case EPERM : errObj = DBPermissionsError; break;
587 default: errObj = DBError; break;
590 if (errObj != NULL) {
591 our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
592 if (_db_errmsg[0]) {
593 strcat(errTxt, " -- ");
594 strcat(errTxt, _db_errmsg);
595 _db_errmsg[0] = 0;
598 errTuple = Py_BuildValue("(is)", err, errTxt);
599 PyErr_SetObject(errObj, errTuple);
600 Py_DECREF(errTuple);
603 return ((errObj != NULL) || exceptionRaised);
608 /* set a type exception */
609 static void makeTypeError(char* expected, PyObject* found)
611 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
612 expected, found->ob_type->tp_name);
616 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
617 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
619 if (txnobj == Py_None || txnobj == NULL) {
620 *txn = NULL;
621 return 1;
623 if (DBTxnObject_Check(txnobj)) {
624 *txn = ((DBTxnObject*)txnobj)->txn;
625 return 1;
627 else
628 makeTypeError("DBTxn", txnobj);
629 return 0;
633 /* Delete a key from a database
634 Returns 0 on success, -1 on an error. */
635 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
637 int err;
639 MYDB_BEGIN_ALLOW_THREADS;
640 err = self->db->del(self->db, txn, key, 0);
641 MYDB_END_ALLOW_THREADS;
642 if (makeDBError(err)) {
643 return -1;
645 self->haveStat = 0;
646 return 0;
650 /* Store a key into a database
651 Returns 0 on success, -1 on an error. */
652 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
654 int err;
656 MYDB_BEGIN_ALLOW_THREADS;
657 err = self->db->put(self->db, txn, key, data, flags);
658 MYDB_END_ALLOW_THREADS;
659 if (makeDBError(err)) {
660 return -1;
662 self->haveStat = 0;
663 return 0;
666 /* Get a key/data pair from a cursor */
667 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
668 PyObject *args, PyObject *kwargs, char *format)
670 int err;
671 PyObject* retval = NULL;
672 DBT key, data;
673 int dlen = -1;
674 int doff = -1;
675 int flags = 0;
676 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
678 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
679 &flags, &dlen, &doff))
680 return NULL;
682 CHECK_CURSOR_NOT_CLOSED(self);
684 flags |= extra_flags;
685 CLEAR_DBT(key);
686 CLEAR_DBT(data);
687 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
688 /* Tell BerkeleyDB to malloc the return value (thread safe) */
689 data.flags = DB_DBT_MALLOC;
690 key.flags = DB_DBT_MALLOC;
692 if (!add_partial_dbt(&data, dlen, doff))
693 return NULL;
695 MYDB_BEGIN_ALLOW_THREADS;
696 err = self->dbc->c_get(self->dbc, &key, &data, flags);
697 MYDB_END_ALLOW_THREADS;
699 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
700 && self->mydb->moduleFlags.getReturnsNone) {
701 Py_INCREF(Py_None);
702 retval = Py_None;
704 else if (makeDBError(err)) {
705 retval = NULL;
707 else { /* otherwise, success! */
709 /* if Recno or Queue, return the key as an Int */
710 switch (_DB_get_type(self->mydb)) {
711 case -1:
712 retval = NULL;
713 break;
715 case DB_RECNO:
716 case DB_QUEUE:
717 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
718 data.data, data.size);
719 break;
720 case DB_HASH:
721 case DB_BTREE:
722 default:
723 retval = Py_BuildValue("s#s#", key.data, key.size,
724 data.data, data.size);
725 break;
728 if (!err) {
729 FREE_DBT(key);
730 FREE_DBT(data);
732 return retval;
736 /* add an integer to a dictionary using the given name as a key */
737 static void _addIntToDict(PyObject* dict, char *name, int value)
739 PyObject* v = PyInt_FromLong((long) value);
740 if (!v || PyDict_SetItemString(dict, name, v))
741 PyErr_Clear();
743 Py_XDECREF(v);
745 #if (DBVER >= 43)
746 /* add an db_seq_t to a dictionary using the given name as a key */
747 static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
749 PyObject* v = PyLong_FromLongLong(value);
750 if (!v || PyDict_SetItemString(dict, name, v))
751 PyErr_Clear();
753 Py_XDECREF(v);
755 #endif
759 /* --------------------------------------------------------------------- */
760 /* Allocators and deallocators */
762 static DBObject*
763 newDBObject(DBEnvObject* arg, int flags)
765 DBObject* self;
766 DB_ENV* db_env = NULL;
767 int err;
769 self = PyObject_New(DBObject, &DB_Type);
770 if (self == NULL)
771 return NULL;
773 self->haveStat = 0;
774 self->flags = 0;
775 self->setflags = 0;
776 self->myenvobj = NULL;
777 #if (DBVER >= 33)
778 self->associateCallback = NULL;
779 self->btCompareCallback = NULL;
780 self->primaryDBType = 0;
781 #endif
782 #ifdef HAVE_WEAKREF
783 self->in_weakreflist = NULL;
784 #endif
786 /* keep a reference to our python DBEnv object */
787 if (arg) {
788 Py_INCREF(arg);
789 self->myenvobj = arg;
790 db_env = arg->db_env;
793 if (self->myenvobj)
794 self->moduleFlags = self->myenvobj->moduleFlags;
795 else
796 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
797 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
799 MYDB_BEGIN_ALLOW_THREADS;
800 err = db_create(&self->db, db_env, flags);
801 self->db->set_errcall(self->db, _db_errorCallback);
802 #if (DBVER >= 33)
803 self->db->app_private = (void*)self;
804 #endif
805 MYDB_END_ALLOW_THREADS;
806 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
807 * list so that a DBEnv can refuse to close without aborting any open
808 * DBTxns and closing any open DBs first. */
809 if (makeDBError(err)) {
810 if (self->myenvobj) {
811 Py_DECREF(self->myenvobj);
812 self->myenvobj = NULL;
814 PyObject_Del(self);
815 self = NULL;
817 return self;
821 static void
822 DB_dealloc(DBObject* self)
824 if (self->db != NULL) {
825 /* avoid closing a DB when its DBEnv has been closed out from under
826 * it */
827 if (!self->myenvobj ||
828 (self->myenvobj && self->myenvobj->db_env))
830 MYDB_BEGIN_ALLOW_THREADS;
831 self->db->close(self->db, 0);
832 MYDB_END_ALLOW_THREADS;
833 #ifdef HAVE_WARNINGS
834 } else {
835 PyErr_Warn(PyExc_RuntimeWarning,
836 "DB could not be closed in destructor: DBEnv already closed");
837 #endif
839 self->db = NULL;
841 #ifdef HAVE_WEAKREF
842 if (self->in_weakreflist != NULL) {
843 PyObject_ClearWeakRefs((PyObject *) self);
845 #endif
846 if (self->myenvobj) {
847 Py_DECREF(self->myenvobj);
848 self->myenvobj = NULL;
850 #if (DBVER >= 33)
851 if (self->associateCallback != NULL) {
852 Py_DECREF(self->associateCallback);
853 self->associateCallback = NULL;
855 if (self->btCompareCallback != NULL) {
856 Py_DECREF(self->btCompareCallback);
857 self->btCompareCallback = NULL;
859 #endif
860 PyObject_Del(self);
864 static DBCursorObject*
865 newDBCursorObject(DBC* dbc, DBObject* db)
867 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
868 if (self == NULL)
869 return NULL;
871 self->dbc = dbc;
872 self->mydb = db;
873 #ifdef HAVE_WEAKREF
874 self->in_weakreflist = NULL;
875 #endif
876 Py_INCREF(self->mydb);
877 return self;
881 static void
882 DBCursor_dealloc(DBCursorObject* self)
884 int err;
886 #ifdef HAVE_WEAKREF
887 if (self->in_weakreflist != NULL) {
888 PyObject_ClearWeakRefs((PyObject *) self);
890 #endif
892 if (self->dbc != NULL) {
893 MYDB_BEGIN_ALLOW_THREADS;
894 /* If the underlying database has been closed, we don't
895 need to do anything. If the environment has been closed
896 we need to leak, as BerkeleyDB will crash trying to access
897 the environment. There was an exception when the
898 user closed the environment even though there still was
899 a database open. */
900 if (self->mydb->db && self->mydb->myenvobj &&
901 !self->mydb->myenvobj->closed)
902 err = self->dbc->c_close(self->dbc);
903 self->dbc = NULL;
904 MYDB_END_ALLOW_THREADS;
906 Py_XDECREF( self->mydb );
907 PyObject_Del(self);
911 static DBEnvObject*
912 newDBEnvObject(int flags)
914 int err;
915 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
916 if (self == NULL)
917 return NULL;
919 self->closed = 1;
920 self->flags = flags;
921 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
922 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
923 #ifdef HAVE_WEAKREF
924 self->in_weakreflist = NULL;
925 #endif
927 MYDB_BEGIN_ALLOW_THREADS;
928 err = db_env_create(&self->db_env, flags);
929 MYDB_END_ALLOW_THREADS;
930 if (makeDBError(err)) {
931 PyObject_Del(self);
932 self = NULL;
934 else {
935 self->db_env->set_errcall(self->db_env, _db_errorCallback);
937 return self;
941 static void
942 DBEnv_dealloc(DBEnvObject* self)
944 #ifdef HAVE_WEAKREF
945 if (self->in_weakreflist != NULL) {
946 PyObject_ClearWeakRefs((PyObject *) self);
948 #endif
950 if (self->db_env && !self->closed) {
951 MYDB_BEGIN_ALLOW_THREADS;
952 self->db_env->close(self->db_env, 0);
953 MYDB_END_ALLOW_THREADS;
955 PyObject_Del(self);
959 static DBTxnObject*
960 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
962 int err;
963 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
964 if (self == NULL)
965 return NULL;
966 Py_INCREF(myenv);
967 self->env = (PyObject*)myenv;
968 #ifdef HAVE_WEAKREF
969 self->in_weakreflist = NULL;
970 #endif
972 MYDB_BEGIN_ALLOW_THREADS;
973 #if (DBVER >= 40)
974 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
975 #else
976 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
977 #endif
978 MYDB_END_ALLOW_THREADS;
979 if (makeDBError(err)) {
980 Py_DECREF(self->env);
981 PyObject_Del(self);
982 self = NULL;
984 return self;
988 static void
989 DBTxn_dealloc(DBTxnObject* self)
991 #ifdef HAVE_WEAKREF
992 if (self->in_weakreflist != NULL) {
993 PyObject_ClearWeakRefs((PyObject *) self);
995 #endif
997 #ifdef HAVE_WARNINGS
998 if (self->txn) {
999 /* it hasn't been finalized, abort it! */
1000 MYDB_BEGIN_ALLOW_THREADS;
1001 #if (DBVER >= 40)
1002 self->txn->abort(self->txn);
1003 #else
1004 txn_abort(self->txn);
1005 #endif
1006 MYDB_END_ALLOW_THREADS;
1007 PyErr_Warn(PyExc_RuntimeWarning,
1008 "DBTxn aborted in destructor. No prior commit() or abort().");
1010 #endif
1012 Py_DECREF(self->env);
1013 PyObject_Del(self);
1017 static DBLockObject*
1018 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1019 db_lockmode_t lock_mode, int flags)
1021 int err;
1022 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
1023 if (self == NULL)
1024 return NULL;
1025 #ifdef HAVE_WEAKREF
1026 self->in_weakreflist = NULL;
1027 #endif
1029 MYDB_BEGIN_ALLOW_THREADS;
1030 #if (DBVER >= 40)
1031 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1032 &self->lock);
1033 #else
1034 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1035 #endif
1036 MYDB_END_ALLOW_THREADS;
1037 if (makeDBError(err)) {
1038 PyObject_Del(self);
1039 self = NULL;
1042 return self;
1046 static void
1047 DBLock_dealloc(DBLockObject* self)
1049 #ifdef HAVE_WEAKREF
1050 if (self->in_weakreflist != NULL) {
1051 PyObject_ClearWeakRefs((PyObject *) self);
1053 #endif
1054 /* TODO: is this lock held? should we release it? */
1056 PyObject_Del(self);
1060 #if (DBVER >= 43)
1061 static DBSequenceObject*
1062 newDBSequenceObject(DBObject* mydb, int flags)
1064 int err;
1065 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1066 if (self == NULL)
1067 return NULL;
1068 Py_INCREF(mydb);
1069 self->mydb = mydb;
1070 #ifdef HAVE_WEAKREF
1071 self->in_weakreflist = NULL;
1072 #endif
1075 MYDB_BEGIN_ALLOW_THREADS;
1076 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1077 MYDB_END_ALLOW_THREADS;
1078 if (makeDBError(err)) {
1079 Py_DECREF(self->mydb);
1080 PyObject_Del(self);
1081 self = NULL;
1084 return self;
1088 static void
1089 DBSequence_dealloc(DBSequenceObject* self)
1091 #ifdef HAVE_WEAKREF
1092 if (self->in_weakreflist != NULL) {
1093 PyObject_ClearWeakRefs((PyObject *) self);
1095 #endif
1097 Py_DECREF(self->mydb);
1098 PyObject_Del(self);
1100 #endif
1102 /* --------------------------------------------------------------------- */
1103 /* DB methods */
1105 static PyObject*
1106 DB_append(DBObject* self, PyObject* args)
1108 PyObject* txnobj = NULL;
1109 PyObject* dataobj;
1110 db_recno_t recno;
1111 DBT key, data;
1112 DB_TXN *txn = NULL;
1114 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
1115 return NULL;
1117 CHECK_DB_NOT_CLOSED(self);
1119 /* make a dummy key out of a recno */
1120 recno = 0;
1121 CLEAR_DBT(key);
1122 key.data = &recno;
1123 key.size = sizeof(recno);
1124 key.ulen = key.size;
1125 key.flags = DB_DBT_USERMEM;
1127 if (!make_dbt(dataobj, &data)) return NULL;
1128 if (!checkTxnObj(txnobj, &txn)) return NULL;
1130 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1131 return NULL;
1133 return PyInt_FromLong(recno);
1137 #if (DBVER >= 33)
1139 static int
1140 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1141 DBT* secKey)
1143 int retval = DB_DONOTINDEX;
1144 DBObject* secondaryDB = (DBObject*)db->app_private;
1145 PyObject* callback = secondaryDB->associateCallback;
1146 int type = secondaryDB->primaryDBType;
1147 PyObject* args;
1148 PyObject* result = NULL;
1151 if (callback != NULL) {
1152 MYDB_BEGIN_BLOCK_THREADS;
1154 if (type == DB_RECNO || type == DB_QUEUE)
1155 args = Py_BuildValue("(ls#)", *((db_recno_t*)priKey->data),
1156 priData->data, priData->size);
1157 else
1158 args = Py_BuildValue("(s#s#)", priKey->data, priKey->size,
1159 priData->data, priData->size);
1160 if (args != NULL) {
1161 result = PyEval_CallObject(callback, args);
1163 if (args == NULL || result == NULL) {
1164 PyErr_Print();
1166 else if (result == Py_None) {
1167 retval = DB_DONOTINDEX;
1169 else if (PyInt_Check(result)) {
1170 retval = PyInt_AsLong(result);
1172 else if (PyString_Check(result)) {
1173 char* data;
1174 Py_ssize_t size;
1176 CLEAR_DBT(*secKey);
1177 #if PYTHON_API_VERSION <= 1007
1178 /* 1.5 compatibility */
1179 size = PyString_Size(result);
1180 data = PyString_AsString(result);
1181 #else
1182 PyString_AsStringAndSize(result, &data, &size);
1183 #endif
1184 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1185 secKey->data = malloc(size); /* TODO, check this */
1186 if (secKey->data) {
1187 memcpy(secKey->data, data, size);
1188 secKey->size = size;
1189 retval = 0;
1191 else {
1192 PyErr_SetString(PyExc_MemoryError,
1193 "malloc failed in _db_associateCallback");
1194 PyErr_Print();
1197 else {
1198 PyErr_SetString(
1199 PyExc_TypeError,
1200 "DB associate callback should return DB_DONOTINDEX or string.");
1201 PyErr_Print();
1204 Py_XDECREF(args);
1205 Py_XDECREF(result);
1207 MYDB_END_BLOCK_THREADS;
1209 return retval;
1213 static PyObject*
1214 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1216 int err, flags=0;
1217 DBObject* secondaryDB;
1218 PyObject* callback;
1219 #if (DBVER >= 41)
1220 PyObject *txnobj = NULL;
1221 DB_TXN *txn = NULL;
1222 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
1223 NULL};
1224 #else
1225 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1226 #endif
1228 #if (DBVER >= 41)
1229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1230 &secondaryDB, &callback, &flags,
1231 &txnobj)) {
1232 #else
1233 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1234 &secondaryDB, &callback, &flags)) {
1235 #endif
1236 return NULL;
1239 #if (DBVER >= 41)
1240 if (!checkTxnObj(txnobj, &txn)) return NULL;
1241 #endif
1243 CHECK_DB_NOT_CLOSED(self);
1244 if (!DBObject_Check(secondaryDB)) {
1245 makeTypeError("DB", (PyObject*)secondaryDB);
1246 return NULL;
1248 CHECK_DB_NOT_CLOSED(secondaryDB);
1249 if (callback == Py_None) {
1250 callback = NULL;
1252 else if (!PyCallable_Check(callback)) {
1253 makeTypeError("Callable", callback);
1254 return NULL;
1257 /* Save a reference to the callback in the secondary DB. */
1258 Py_XDECREF(secondaryDB->associateCallback);
1259 Py_XINCREF(callback);
1260 secondaryDB->associateCallback = callback;
1261 secondaryDB->primaryDBType = _DB_get_type(self);
1263 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1264 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1265 * The global interepreter lock is not initialized until the first
1266 * thread is created using thread.start_new_thread() or fork() is
1267 * called. that would cause the ALLOW_THREADS here to segfault due
1268 * to a null pointer reference if no threads or child processes
1269 * have been created. This works around that and is a no-op if
1270 * threads have already been initialized.
1271 * (see pybsddb-users mailing list post on 2002-08-07)
1273 #ifdef WITH_THREAD
1274 PyEval_InitThreads();
1275 #endif
1276 MYDB_BEGIN_ALLOW_THREADS;
1277 #if (DBVER >= 41)
1278 err = self->db->associate(self->db,
1279 txn,
1280 secondaryDB->db,
1281 _db_associateCallback,
1282 flags);
1283 #else
1284 err = self->db->associate(self->db,
1285 secondaryDB->db,
1286 _db_associateCallback,
1287 flags);
1288 #endif
1289 MYDB_END_ALLOW_THREADS;
1291 if (err) {
1292 Py_XDECREF(secondaryDB->associateCallback);
1293 secondaryDB->associateCallback = NULL;
1294 secondaryDB->primaryDBType = 0;
1297 RETURN_IF_ERR();
1298 RETURN_NONE();
1302 #endif
1305 static PyObject*
1306 DB_close(DBObject* self, PyObject* args)
1308 int err, flags=0;
1309 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1310 return NULL;
1311 if (self->db != NULL) {
1312 if (self->myenvobj)
1313 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1314 err = self->db->close(self->db, flags);
1315 self->db = NULL;
1316 RETURN_IF_ERR();
1318 RETURN_NONE();
1322 #if (DBVER >= 32)
1323 static PyObject*
1324 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1326 int err, flags=0, type;
1327 PyObject* txnobj = NULL;
1328 PyObject* retval = NULL;
1329 DBT key, data;
1330 DB_TXN *txn = NULL;
1331 static char* kwnames[] = { "txn", "flags", NULL };
1333 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1334 &txnobj, &flags))
1335 return NULL;
1337 CHECK_DB_NOT_CLOSED(self);
1338 type = _DB_get_type(self);
1339 if (type == -1)
1340 return NULL;
1341 if (type != DB_QUEUE) {
1342 PyErr_SetString(PyExc_TypeError,
1343 "Consume methods only allowed for Queue DB's");
1344 return NULL;
1346 if (!checkTxnObj(txnobj, &txn))
1347 return NULL;
1349 CLEAR_DBT(key);
1350 CLEAR_DBT(data);
1351 if (CHECK_DBFLAG(self, DB_THREAD)) {
1352 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1353 data.flags = DB_DBT_MALLOC;
1354 key.flags = DB_DBT_MALLOC;
1357 MYDB_BEGIN_ALLOW_THREADS;
1358 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1359 MYDB_END_ALLOW_THREADS;
1361 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1362 && self->moduleFlags.getReturnsNone) {
1363 err = 0;
1364 Py_INCREF(Py_None);
1365 retval = Py_None;
1367 else if (!err) {
1368 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1369 data.size);
1370 FREE_DBT(key);
1371 FREE_DBT(data);
1374 RETURN_IF_ERR();
1375 return retval;
1378 static PyObject*
1379 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1381 return _DB_consume(self, args, kwargs, DB_CONSUME);
1384 static PyObject*
1385 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1386 int consume_flag)
1388 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1390 #endif
1394 static PyObject*
1395 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1397 int err, flags=0;
1398 DBC* dbc;
1399 PyObject* txnobj = NULL;
1400 DB_TXN *txn = NULL;
1401 static char* kwnames[] = { "txn", "flags", NULL };
1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1404 &txnobj, &flags))
1405 return NULL;
1406 CHECK_DB_NOT_CLOSED(self);
1407 if (!checkTxnObj(txnobj, &txn))
1408 return NULL;
1410 MYDB_BEGIN_ALLOW_THREADS;
1411 err = self->db->cursor(self->db, txn, &dbc, flags);
1412 MYDB_END_ALLOW_THREADS;
1413 RETURN_IF_ERR();
1414 return (PyObject*) newDBCursorObject(dbc, self);
1418 static PyObject*
1419 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1421 PyObject* txnobj = NULL;
1422 int flags = 0;
1423 PyObject* keyobj;
1424 DBT key;
1425 DB_TXN *txn = NULL;
1426 static char* kwnames[] = { "key", "txn", "flags", NULL };
1428 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1429 &keyobj, &txnobj, &flags))
1430 return NULL;
1431 CHECK_DB_NOT_CLOSED(self);
1432 if (!make_key_dbt(self, keyobj, &key, NULL))
1433 return NULL;
1434 if (!checkTxnObj(txnobj, &txn)) {
1435 FREE_DBT(key);
1436 return NULL;
1439 if (-1 == _DB_delete(self, txn, &key, 0)) {
1440 FREE_DBT(key);
1441 return NULL;
1444 FREE_DBT(key);
1445 RETURN_NONE();
1449 static PyObject*
1450 DB_fd(DBObject* self, PyObject* args)
1452 int err, the_fd;
1454 if (!PyArg_ParseTuple(args,":fd"))
1455 return NULL;
1456 CHECK_DB_NOT_CLOSED(self);
1458 MYDB_BEGIN_ALLOW_THREADS;
1459 err = self->db->fd(self->db, &the_fd);
1460 MYDB_END_ALLOW_THREADS;
1461 RETURN_IF_ERR();
1462 return PyInt_FromLong(the_fd);
1466 static PyObject*
1467 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1469 int err, flags=0;
1470 PyObject* txnobj = NULL;
1471 PyObject* keyobj;
1472 PyObject* dfltobj = NULL;
1473 PyObject* retval = NULL;
1474 int dlen = -1;
1475 int doff = -1;
1476 DBT key, data;
1477 DB_TXN *txn = NULL;
1478 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1479 "doff", NULL};
1481 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1482 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1483 &doff))
1484 return NULL;
1486 CHECK_DB_NOT_CLOSED(self);
1487 if (!make_key_dbt(self, keyobj, &key, &flags))
1488 return NULL;
1489 if (!checkTxnObj(txnobj, &txn)) {
1490 FREE_DBT(key);
1491 return NULL;
1494 CLEAR_DBT(data);
1495 if (CHECK_DBFLAG(self, DB_THREAD)) {
1496 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1497 data.flags = DB_DBT_MALLOC;
1499 if (!add_partial_dbt(&data, dlen, doff)) {
1500 FREE_DBT(key);
1501 return NULL;
1504 MYDB_BEGIN_ALLOW_THREADS;
1505 err = self->db->get(self->db, txn, &key, &data, flags);
1506 MYDB_END_ALLOW_THREADS;
1508 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1509 err = 0;
1510 Py_INCREF(dfltobj);
1511 retval = dfltobj;
1513 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1514 && self->moduleFlags.getReturnsNone) {
1515 err = 0;
1516 Py_INCREF(Py_None);
1517 retval = Py_None;
1519 else if (!err) {
1520 if (flags & DB_SET_RECNO) /* return both key and data */
1521 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1522 data.size);
1523 else /* return just the data */
1524 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1525 FREE_DBT(data);
1527 FREE_DBT(key);
1529 RETURN_IF_ERR();
1530 return retval;
1533 #if (DBVER >= 33)
1534 static PyObject*
1535 DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1537 int err, flags=0;
1538 PyObject* txnobj = NULL;
1539 PyObject* keyobj;
1540 PyObject* dfltobj = NULL;
1541 PyObject* retval = NULL;
1542 int dlen = -1;
1543 int doff = -1;
1544 DBT key, pkey, data;
1545 DB_TXN *txn = NULL;
1546 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
1547 "doff", NULL};
1549 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1550 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1551 &doff))
1552 return NULL;
1554 CHECK_DB_NOT_CLOSED(self);
1555 if (!make_key_dbt(self, keyobj, &key, &flags))
1556 return NULL;
1557 if (!checkTxnObj(txnobj, &txn)) {
1558 FREE_DBT(key);
1559 return NULL;
1562 CLEAR_DBT(data);
1563 if (CHECK_DBFLAG(self, DB_THREAD)) {
1564 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1565 data.flags = DB_DBT_MALLOC;
1567 if (!add_partial_dbt(&data, dlen, doff)) {
1568 FREE_DBT(key);
1569 return NULL;
1572 CLEAR_DBT(pkey);
1573 pkey.flags = DB_DBT_MALLOC;
1575 MYDB_BEGIN_ALLOW_THREADS;
1576 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1577 MYDB_END_ALLOW_THREADS;
1579 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
1580 err = 0;
1581 Py_INCREF(dfltobj);
1582 retval = dfltobj;
1584 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1585 && self->moduleFlags.getReturnsNone) {
1586 err = 0;
1587 Py_INCREF(Py_None);
1588 retval = Py_None;
1590 else if (!err) {
1591 PyObject *pkeyObj;
1592 PyObject *dataObj;
1593 dataObj = PyString_FromStringAndSize(data.data, data.size);
1595 if (self->primaryDBType == DB_RECNO ||
1596 self->primaryDBType == DB_QUEUE)
1597 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
1598 else
1599 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
1601 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1603 PyObject *keyObj;
1604 int type = _DB_get_type(self);
1605 if (type == DB_RECNO || type == DB_QUEUE)
1606 keyObj = PyInt_FromLong(*(int *)key.data);
1607 else
1608 keyObj = PyString_FromStringAndSize(key.data, key.size);
1609 #if (PY_VERSION_HEX >= 0x02040000)
1610 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
1611 #else
1612 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1613 #endif
1614 Py_DECREF(keyObj);
1616 else /* return just the pkey and data */
1618 #if (PY_VERSION_HEX >= 0x02040000)
1619 retval = PyTuple_Pack(2, pkeyObj, dataObj);
1620 #else
1621 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1622 #endif
1624 Py_DECREF(dataObj);
1625 Py_DECREF(pkeyObj);
1626 FREE_DBT(pkey);
1627 FREE_DBT(data);
1629 FREE_DBT(key);
1631 RETURN_IF_ERR();
1632 return retval;
1634 #endif
1637 /* Return size of entry */
1638 static PyObject*
1639 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1641 int err, flags=0;
1642 PyObject* txnobj = NULL;
1643 PyObject* keyobj;
1644 PyObject* retval = NULL;
1645 DBT key, data;
1646 DB_TXN *txn = NULL;
1647 static char* kwnames[] = { "key", "txn", NULL };
1649 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1650 &keyobj, &txnobj))
1651 return NULL;
1652 CHECK_DB_NOT_CLOSED(self);
1653 if (!make_key_dbt(self, keyobj, &key, &flags))
1654 return NULL;
1655 if (!checkTxnObj(txnobj, &txn)) {
1656 FREE_DBT(key);
1657 return NULL;
1659 CLEAR_DBT(data);
1661 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1662 thus getting the record size. */
1663 data.flags = DB_DBT_USERMEM;
1664 data.ulen = 0;
1665 MYDB_BEGIN_ALLOW_THREADS;
1666 err = self->db->get(self->db, txn, &key, &data, flags);
1667 MYDB_END_ALLOW_THREADS;
1668 if (err == DB_BUFFER_SMALL) {
1669 retval = PyInt_FromLong((long)data.size);
1670 err = 0;
1673 FREE_DBT(key);
1674 FREE_DBT(data);
1675 RETURN_IF_ERR();
1676 return retval;
1680 static PyObject*
1681 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1683 int err, flags=0;
1684 PyObject* txnobj = NULL;
1685 PyObject* keyobj;
1686 PyObject* dataobj;
1687 PyObject* retval = NULL;
1688 DBT key, data;
1689 DB_TXN *txn = NULL;
1690 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1693 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1694 &keyobj, &dataobj, &txnobj, &flags))
1695 return NULL;
1697 CHECK_DB_NOT_CLOSED(self);
1698 if (!make_key_dbt(self, keyobj, &key, NULL))
1699 return NULL;
1700 if ( !make_dbt(dataobj, &data) ||
1701 !checkTxnObj(txnobj, &txn) )
1703 FREE_DBT(key);
1704 return NULL;
1707 flags |= DB_GET_BOTH;
1709 if (CHECK_DBFLAG(self, DB_THREAD)) {
1710 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1711 data.flags = DB_DBT_MALLOC;
1712 /* TODO: Is this flag needed? We're passing a data object that should
1713 match what's in the DB, so there should be no need to malloc.
1714 We run the risk of freeing something twice! Check this. */
1717 MYDB_BEGIN_ALLOW_THREADS;
1718 err = self->db->get(self->db, txn, &key, &data, flags);
1719 MYDB_END_ALLOW_THREADS;
1721 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1722 && self->moduleFlags.getReturnsNone) {
1723 err = 0;
1724 Py_INCREF(Py_None);
1725 retval = Py_None;
1727 else if (!err) {
1728 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1729 FREE_DBT(data); /* Only if retrieval was successful */
1732 FREE_DBT(key);
1733 RETURN_IF_ERR();
1734 return retval;
1738 static PyObject*
1739 DB_get_byteswapped(DBObject* self, PyObject* args)
1741 #if (DBVER >= 33)
1742 int err = 0;
1743 #endif
1744 int retval = -1;
1746 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1747 return NULL;
1748 CHECK_DB_NOT_CLOSED(self);
1750 #if (DBVER >= 33)
1751 MYDB_BEGIN_ALLOW_THREADS;
1752 err = self->db->get_byteswapped(self->db, &retval);
1753 MYDB_END_ALLOW_THREADS;
1754 RETURN_IF_ERR();
1755 #else
1756 MYDB_BEGIN_ALLOW_THREADS;
1757 retval = self->db->get_byteswapped(self->db);
1758 MYDB_END_ALLOW_THREADS;
1759 #endif
1760 return PyInt_FromLong(retval);
1764 static PyObject*
1765 DB_get_type(DBObject* self, PyObject* args)
1767 int type;
1769 if (!PyArg_ParseTuple(args,":get_type"))
1770 return NULL;
1771 CHECK_DB_NOT_CLOSED(self);
1773 MYDB_BEGIN_ALLOW_THREADS;
1774 type = _DB_get_type(self);
1775 MYDB_END_ALLOW_THREADS;
1776 if (type == -1)
1777 return NULL;
1778 return PyInt_FromLong(type);
1782 static PyObject*
1783 DB_join(DBObject* self, PyObject* args)
1785 int err, flags=0;
1786 int length, x;
1787 PyObject* cursorsObj;
1788 DBC** cursors;
1789 DBC* dbc;
1792 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1793 return NULL;
1795 CHECK_DB_NOT_CLOSED(self);
1797 if (!PySequence_Check(cursorsObj)) {
1798 PyErr_SetString(PyExc_TypeError,
1799 "Sequence of DBCursor objects expected");
1800 return NULL;
1803 length = PyObject_Length(cursorsObj);
1804 cursors = malloc((length+1) * sizeof(DBC*));
1805 cursors[length] = NULL;
1806 for (x=0; x<length; x++) {
1807 PyObject* item = PySequence_GetItem(cursorsObj, x);
1808 if (item == NULL) {
1809 free(cursors);
1810 return NULL;
1812 if (!DBCursorObject_Check(item)) {
1813 PyErr_SetString(PyExc_TypeError,
1814 "Sequence of DBCursor objects expected");
1815 free(cursors);
1816 return NULL;
1818 cursors[x] = ((DBCursorObject*)item)->dbc;
1819 Py_DECREF(item);
1822 MYDB_BEGIN_ALLOW_THREADS;
1823 err = self->db->join(self->db, cursors, &dbc, flags);
1824 MYDB_END_ALLOW_THREADS;
1825 free(cursors);
1826 RETURN_IF_ERR();
1828 /* FIXME: this is a buggy interface. The returned cursor
1829 contains internal references to the passed in cursors
1830 but does not hold python references to them or prevent
1831 them from being closed prematurely. This can cause
1832 python to crash when things are done in the wrong order. */
1833 return (PyObject*) newDBCursorObject(dbc, self);
1837 static PyObject*
1838 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1840 int err, flags=0;
1841 PyObject* txnobj = NULL;
1842 PyObject* keyobj;
1843 DBT key;
1844 DB_TXN *txn = NULL;
1845 DB_KEY_RANGE range;
1846 static char* kwnames[] = { "key", "txn", "flags", NULL };
1848 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1849 &keyobj, &txnobj, &flags))
1850 return NULL;
1851 CHECK_DB_NOT_CLOSED(self);
1852 if (!make_dbt(keyobj, &key))
1853 /* BTree only, don't need to allow for an int key */
1854 return NULL;
1855 if (!checkTxnObj(txnobj, &txn))
1856 return NULL;
1858 MYDB_BEGIN_ALLOW_THREADS;
1859 err = self->db->key_range(self->db, txn, &key, &range, flags);
1860 MYDB_END_ALLOW_THREADS;
1862 RETURN_IF_ERR();
1863 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1867 static PyObject*
1868 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1870 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1871 char* filename = NULL;
1872 char* dbname = NULL;
1873 #if (DBVER >= 41)
1874 PyObject *txnobj = NULL;
1875 DB_TXN *txn = NULL;
1876 /* with dbname */
1877 static char* kwnames[] = {
1878 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1879 /* without dbname */
1880 static char* kwnames_basic[] = {
1881 "filename", "dbtype", "flags", "mode", "txn", NULL};
1882 #else
1883 /* with dbname */
1884 static char* kwnames[] = {
1885 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1886 /* without dbname */
1887 static char* kwnames_basic[] = {
1888 "filename", "dbtype", "flags", "mode", NULL};
1889 #endif
1891 #if (DBVER >= 41)
1892 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1893 &filename, &dbname, &type, &flags, &mode,
1894 &txnobj))
1895 #else
1896 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1897 &filename, &dbname, &type, &flags,
1898 &mode))
1899 #endif
1901 PyErr_Clear();
1902 type = DB_UNKNOWN; flags = 0; mode = 0660;
1903 filename = NULL; dbname = NULL;
1904 #if (DBVER >= 41)
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1906 kwnames_basic,
1907 &filename, &type, &flags, &mode,
1908 &txnobj))
1909 return NULL;
1910 #else
1911 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1912 kwnames_basic,
1913 &filename, &type, &flags, &mode))
1914 return NULL;
1915 #endif
1918 #if (DBVER >= 41)
1919 if (!checkTxnObj(txnobj, &txn)) return NULL;
1920 #endif
1922 if (NULL == self->db) {
1923 PyObject *t = Py_BuildValue("(is)", 0,
1924 "Cannot call open() twice for DB object");
1925 PyErr_SetObject(DBError, t);
1926 Py_DECREF(t);
1927 return NULL;
1930 #if 0 && (DBVER >= 41)
1931 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1932 && (self->myenvobj->flags & DB_INIT_TXN))
1934 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1935 * explicitly passed) but we are in a transaction ready environment:
1936 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1937 * to work on BerkeleyDB 4.1 without needing to modify their
1938 * DBEnv or DB open calls.
1939 * TODO make this behaviour of the library configurable.
1941 flags |= DB_AUTO_COMMIT;
1943 #endif
1945 MYDB_BEGIN_ALLOW_THREADS;
1946 #if (DBVER >= 41)
1947 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1948 #else
1949 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1950 #endif
1951 MYDB_END_ALLOW_THREADS;
1952 if (makeDBError(err)) {
1953 self->db->close(self->db, 0);
1954 self->db = NULL;
1955 return NULL;
1958 self->flags = flags;
1959 RETURN_NONE();
1963 static PyObject*
1964 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1966 int flags=0;
1967 PyObject* txnobj = NULL;
1968 int dlen = -1;
1969 int doff = -1;
1970 PyObject* keyobj, *dataobj, *retval;
1971 DBT key, data;
1972 DB_TXN *txn = NULL;
1973 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
1974 "doff", NULL };
1976 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1977 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1978 return NULL;
1980 CHECK_DB_NOT_CLOSED(self);
1981 if (!make_key_dbt(self, keyobj, &key, NULL))
1982 return NULL;
1983 if ( !make_dbt(dataobj, &data) ||
1984 !add_partial_dbt(&data, dlen, doff) ||
1985 !checkTxnObj(txnobj, &txn) )
1987 FREE_DBT(key);
1988 return NULL;
1991 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1992 FREE_DBT(key);
1993 return NULL;
1996 if (flags & DB_APPEND)
1997 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1998 else {
1999 retval = Py_None;
2000 Py_INCREF(retval);
2002 FREE_DBT(key);
2003 return retval;
2008 static PyObject*
2009 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2011 char* filename;
2012 char* database = NULL;
2013 int err, flags=0;
2014 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
2016 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2017 &filename, &database, &flags))
2018 return NULL;
2019 CHECK_DB_NOT_CLOSED(self);
2021 err = self->db->remove(self->db, filename, database, flags);
2022 self->db = NULL;
2023 RETURN_IF_ERR();
2024 RETURN_NONE();
2029 static PyObject*
2030 DB_rename(DBObject* self, PyObject* args)
2032 char* filename;
2033 char* database;
2034 char* newname;
2035 int err, flags=0;
2037 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2038 &flags))
2039 return NULL;
2040 CHECK_DB_NOT_CLOSED(self);
2042 MYDB_BEGIN_ALLOW_THREADS;
2043 err = self->db->rename(self->db, filename, database, newname, flags);
2044 MYDB_END_ALLOW_THREADS;
2045 RETURN_IF_ERR();
2046 RETURN_NONE();
2050 static PyObject*
2051 DB_set_bt_minkey(DBObject* self, PyObject* args)
2053 int err, minkey;
2055 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2056 return NULL;
2057 CHECK_DB_NOT_CLOSED(self);
2059 MYDB_BEGIN_ALLOW_THREADS;
2060 err = self->db->set_bt_minkey(self->db, minkey);
2061 MYDB_END_ALLOW_THREADS;
2062 RETURN_IF_ERR();
2063 RETURN_NONE();
2066 #if (DBVER >= 33)
2067 static int
2068 _default_cmp(const DBT *leftKey,
2069 const DBT *rightKey)
2071 int res;
2072 int lsize = leftKey->size, rsize = rightKey->size;
2074 res = memcmp(leftKey->data, rightKey->data,
2075 lsize < rsize ? lsize : rsize);
2077 if (res == 0) {
2078 if (lsize < rsize) {
2079 res = -1;
2081 else if (lsize > rsize) {
2082 res = 1;
2085 return res;
2088 static int
2089 _db_compareCallback(DB* db,
2090 const DBT *leftKey,
2091 const DBT *rightKey)
2093 int res = 0;
2094 PyObject *args;
2095 PyObject *result = NULL;
2096 DBObject *self = (DBObject *)db->app_private;
2098 if (self == NULL || self->btCompareCallback == NULL) {
2099 MYDB_BEGIN_BLOCK_THREADS;
2100 PyErr_SetString(PyExc_TypeError,
2101 (self == 0
2102 ? "DB_bt_compare db is NULL."
2103 : "DB_bt_compare callback is NULL."));
2104 /* we're in a callback within the DB code, we can't raise */
2105 PyErr_Print();
2106 res = _default_cmp(leftKey, rightKey);
2107 MYDB_END_BLOCK_THREADS;
2108 } else {
2109 MYDB_BEGIN_BLOCK_THREADS;
2111 args = Py_BuildValue("s#s#", leftKey->data, leftKey->size,
2112 rightKey->data, rightKey->size);
2113 if (args != NULL) {
2114 /* XXX(twouters) I highly doubt this INCREF is correct */
2115 Py_INCREF(self);
2116 result = PyEval_CallObject(self->btCompareCallback, args);
2118 if (args == NULL || result == NULL) {
2119 /* we're in a callback within the DB code, we can't raise */
2120 PyErr_Print();
2121 res = _default_cmp(leftKey, rightKey);
2122 } else if (PyInt_Check(result)) {
2123 res = PyInt_AsLong(result);
2124 } else {
2125 PyErr_SetString(PyExc_TypeError,
2126 "DB_bt_compare callback MUST return an int.");
2127 /* we're in a callback within the DB code, we can't raise */
2128 PyErr_Print();
2129 res = _default_cmp(leftKey, rightKey);
2132 Py_XDECREF(args);
2133 Py_XDECREF(result);
2135 MYDB_END_BLOCK_THREADS;
2137 return res;
2140 static PyObject*
2141 DB_set_bt_compare(DBObject* self, PyObject* args)
2143 int err;
2144 PyObject *comparator;
2145 PyObject *tuple, *result;
2147 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
2148 return NULL;
2150 CHECK_DB_NOT_CLOSED(self);
2152 if (!PyCallable_Check(comparator)) {
2153 makeTypeError("Callable", comparator);
2154 return NULL;
2158 * Perform a test call of the comparator function with two empty
2159 * string objects here. verify that it returns an int (0).
2160 * err if not.
2162 tuple = Py_BuildValue("(ss)", "", "");
2163 result = PyEval_CallObject(comparator, tuple);
2164 Py_DECREF(tuple);
2165 if (result == NULL)
2166 return NULL;
2167 if (!PyInt_Check(result)) {
2168 PyErr_SetString(PyExc_TypeError,
2169 "callback MUST return an int");
2170 return NULL;
2171 } else if (PyInt_AsLong(result) != 0) {
2172 PyErr_SetString(PyExc_TypeError,
2173 "callback failed to return 0 on two empty strings");
2174 return NULL;
2176 Py_DECREF(result);
2178 /* We don't accept multiple set_bt_compare operations, in order to
2179 * simplify the code. This would have no real use, as one cannot
2180 * change the function once the db is opened anyway */
2181 if (self->btCompareCallback != NULL) {
2182 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
2183 return NULL;
2186 Py_INCREF(comparator);
2187 self->btCompareCallback = comparator;
2189 /* This is to workaround a problem with un-initialized threads (see
2190 comment in DB_associate) */
2191 #ifdef WITH_THREAD
2192 PyEval_InitThreads();
2193 #endif
2195 err = self->db->set_bt_compare(self->db, _db_compareCallback);
2197 if (err) {
2198 /* restore the old state in case of error */
2199 Py_DECREF(comparator);
2200 self->btCompareCallback = NULL;
2203 RETURN_IF_ERR();
2204 RETURN_NONE();
2206 #endif /* DBVER >= 33 */
2209 static PyObject*
2210 DB_set_cachesize(DBObject* self, PyObject* args)
2212 int err;
2213 int gbytes = 0, bytes = 0, ncache = 0;
2215 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2216 &gbytes,&bytes,&ncache))
2217 return NULL;
2218 CHECK_DB_NOT_CLOSED(self);
2220 MYDB_BEGIN_ALLOW_THREADS;
2221 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2222 MYDB_END_ALLOW_THREADS;
2223 RETURN_IF_ERR();
2224 RETURN_NONE();
2228 static PyObject*
2229 DB_set_flags(DBObject* self, PyObject* args)
2231 int err, flags;
2233 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2234 return NULL;
2235 CHECK_DB_NOT_CLOSED(self);
2237 MYDB_BEGIN_ALLOW_THREADS;
2238 err = self->db->set_flags(self->db, flags);
2239 MYDB_END_ALLOW_THREADS;
2240 RETURN_IF_ERR();
2242 self->setflags |= flags;
2243 RETURN_NONE();
2247 static PyObject*
2248 DB_set_h_ffactor(DBObject* self, PyObject* args)
2250 int err, ffactor;
2252 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2253 return NULL;
2254 CHECK_DB_NOT_CLOSED(self);
2256 MYDB_BEGIN_ALLOW_THREADS;
2257 err = self->db->set_h_ffactor(self->db, ffactor);
2258 MYDB_END_ALLOW_THREADS;
2259 RETURN_IF_ERR();
2260 RETURN_NONE();
2264 static PyObject*
2265 DB_set_h_nelem(DBObject* self, PyObject* args)
2267 int err, nelem;
2269 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2270 return NULL;
2271 CHECK_DB_NOT_CLOSED(self);
2273 MYDB_BEGIN_ALLOW_THREADS;
2274 err = self->db->set_h_nelem(self->db, nelem);
2275 MYDB_END_ALLOW_THREADS;
2276 RETURN_IF_ERR();
2277 RETURN_NONE();
2281 static PyObject*
2282 DB_set_lorder(DBObject* self, PyObject* args)
2284 int err, lorder;
2286 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2287 return NULL;
2288 CHECK_DB_NOT_CLOSED(self);
2290 MYDB_BEGIN_ALLOW_THREADS;
2291 err = self->db->set_lorder(self->db, lorder);
2292 MYDB_END_ALLOW_THREADS;
2293 RETURN_IF_ERR();
2294 RETURN_NONE();
2298 static PyObject*
2299 DB_set_pagesize(DBObject* self, PyObject* args)
2301 int err, pagesize;
2303 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2304 return NULL;
2305 CHECK_DB_NOT_CLOSED(self);
2307 MYDB_BEGIN_ALLOW_THREADS;
2308 err = self->db->set_pagesize(self->db, pagesize);
2309 MYDB_END_ALLOW_THREADS;
2310 RETURN_IF_ERR();
2311 RETURN_NONE();
2315 static PyObject*
2316 DB_set_re_delim(DBObject* self, PyObject* args)
2318 int err;
2319 char delim;
2321 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2322 PyErr_Clear();
2323 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2324 return NULL;
2327 CHECK_DB_NOT_CLOSED(self);
2329 MYDB_BEGIN_ALLOW_THREADS;
2330 err = self->db->set_re_delim(self->db, delim);
2331 MYDB_END_ALLOW_THREADS;
2332 RETURN_IF_ERR();
2333 RETURN_NONE();
2336 static PyObject*
2337 DB_set_re_len(DBObject* self, PyObject* args)
2339 int err, len;
2341 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2342 return NULL;
2343 CHECK_DB_NOT_CLOSED(self);
2345 MYDB_BEGIN_ALLOW_THREADS;
2346 err = self->db->set_re_len(self->db, len);
2347 MYDB_END_ALLOW_THREADS;
2348 RETURN_IF_ERR();
2349 RETURN_NONE();
2353 static PyObject*
2354 DB_set_re_pad(DBObject* self, PyObject* args)
2356 int err;
2357 char pad;
2359 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2360 PyErr_Clear();
2361 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2362 return NULL;
2364 CHECK_DB_NOT_CLOSED(self);
2366 MYDB_BEGIN_ALLOW_THREADS;
2367 err = self->db->set_re_pad(self->db, pad);
2368 MYDB_END_ALLOW_THREADS;
2369 RETURN_IF_ERR();
2370 RETURN_NONE();
2374 static PyObject*
2375 DB_set_re_source(DBObject* self, PyObject* args)
2377 int err;
2378 char *re_source;
2380 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2381 return NULL;
2382 CHECK_DB_NOT_CLOSED(self);
2384 MYDB_BEGIN_ALLOW_THREADS;
2385 err = self->db->set_re_source(self->db, re_source);
2386 MYDB_END_ALLOW_THREADS;
2387 RETURN_IF_ERR();
2388 RETURN_NONE();
2392 #if (DBVER >= 32)
2393 static PyObject*
2394 DB_set_q_extentsize(DBObject* self, PyObject* args)
2396 int err;
2397 int extentsize;
2399 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2400 return NULL;
2401 CHECK_DB_NOT_CLOSED(self);
2403 MYDB_BEGIN_ALLOW_THREADS;
2404 err = self->db->set_q_extentsize(self->db, extentsize);
2405 MYDB_END_ALLOW_THREADS;
2406 RETURN_IF_ERR();
2407 RETURN_NONE();
2409 #endif
2411 static PyObject*
2412 DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
2414 int err, flags = 0, type;
2415 void* sp;
2416 PyObject* d;
2417 #if (DBVER >= 43)
2418 PyObject* txnobj = NULL;
2419 DB_TXN *txn = NULL;
2420 static char* kwnames[] = { "txn", "flags", NULL };
2421 #else
2422 static char* kwnames[] = { "flags", NULL };
2423 #endif
2425 #if (DBVER >= 43)
2426 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2427 &flags, &txnobj))
2428 return NULL;
2429 if (!checkTxnObj(txnobj, &txn))
2430 return NULL;
2431 #else
2432 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2433 return NULL;
2434 #endif
2435 CHECK_DB_NOT_CLOSED(self);
2437 MYDB_BEGIN_ALLOW_THREADS;
2438 #if (DBVER >= 43)
2439 err = self->db->stat(self->db, txn, &sp, flags);
2440 #elif (DBVER >= 33)
2441 err = self->db->stat(self->db, &sp, flags);
2442 #else
2443 err = self->db->stat(self->db, &sp, NULL, flags);
2444 #endif
2445 MYDB_END_ALLOW_THREADS;
2446 RETURN_IF_ERR();
2448 self->haveStat = 1;
2450 /* Turn the stat structure into a dictionary */
2451 type = _DB_get_type(self);
2452 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2453 free(sp);
2454 return NULL;
2457 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2458 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2459 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2461 switch (type) {
2462 case DB_HASH:
2463 MAKE_HASH_ENTRY(magic);
2464 MAKE_HASH_ENTRY(version);
2465 MAKE_HASH_ENTRY(nkeys);
2466 MAKE_HASH_ENTRY(ndata);
2467 MAKE_HASH_ENTRY(pagesize);
2468 #if (DBVER < 41)
2469 MAKE_HASH_ENTRY(nelem);
2470 #endif
2471 MAKE_HASH_ENTRY(ffactor);
2472 MAKE_HASH_ENTRY(buckets);
2473 MAKE_HASH_ENTRY(free);
2474 MAKE_HASH_ENTRY(bfree);
2475 MAKE_HASH_ENTRY(bigpages);
2476 MAKE_HASH_ENTRY(big_bfree);
2477 MAKE_HASH_ENTRY(overflows);
2478 MAKE_HASH_ENTRY(ovfl_free);
2479 MAKE_HASH_ENTRY(dup);
2480 MAKE_HASH_ENTRY(dup_free);
2481 break;
2483 case DB_BTREE:
2484 case DB_RECNO:
2485 MAKE_BT_ENTRY(magic);
2486 MAKE_BT_ENTRY(version);
2487 MAKE_BT_ENTRY(nkeys);
2488 MAKE_BT_ENTRY(ndata);
2489 MAKE_BT_ENTRY(pagesize);
2490 MAKE_BT_ENTRY(minkey);
2491 MAKE_BT_ENTRY(re_len);
2492 MAKE_BT_ENTRY(re_pad);
2493 MAKE_BT_ENTRY(levels);
2494 MAKE_BT_ENTRY(int_pg);
2495 MAKE_BT_ENTRY(leaf_pg);
2496 MAKE_BT_ENTRY(dup_pg);
2497 MAKE_BT_ENTRY(over_pg);
2498 MAKE_BT_ENTRY(free);
2499 MAKE_BT_ENTRY(int_pgfree);
2500 MAKE_BT_ENTRY(leaf_pgfree);
2501 MAKE_BT_ENTRY(dup_pgfree);
2502 MAKE_BT_ENTRY(over_pgfree);
2503 break;
2505 case DB_QUEUE:
2506 MAKE_QUEUE_ENTRY(magic);
2507 MAKE_QUEUE_ENTRY(version);
2508 MAKE_QUEUE_ENTRY(nkeys);
2509 MAKE_QUEUE_ENTRY(ndata);
2510 MAKE_QUEUE_ENTRY(pagesize);
2511 MAKE_QUEUE_ENTRY(pages);
2512 MAKE_QUEUE_ENTRY(re_len);
2513 MAKE_QUEUE_ENTRY(re_pad);
2514 MAKE_QUEUE_ENTRY(pgfree);
2515 #if (DBVER == 31)
2516 MAKE_QUEUE_ENTRY(start);
2517 #endif
2518 MAKE_QUEUE_ENTRY(first_recno);
2519 MAKE_QUEUE_ENTRY(cur_recno);
2520 break;
2522 default:
2523 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2524 Py_DECREF(d);
2525 d = NULL;
2528 #undef MAKE_HASH_ENTRY
2529 #undef MAKE_BT_ENTRY
2530 #undef MAKE_QUEUE_ENTRY
2532 free(sp);
2533 return d;
2536 static PyObject*
2537 DB_sync(DBObject* self, PyObject* args)
2539 int err;
2540 int flags = 0;
2542 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2543 return NULL;
2544 CHECK_DB_NOT_CLOSED(self);
2546 MYDB_BEGIN_ALLOW_THREADS;
2547 err = self->db->sync(self->db, flags);
2548 MYDB_END_ALLOW_THREADS;
2549 RETURN_IF_ERR();
2550 RETURN_NONE();
2554 #if (DBVER >= 33)
2555 static PyObject*
2556 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2558 int err, flags=0;
2559 u_int32_t count=0;
2560 PyObject* txnobj = NULL;
2561 DB_TXN *txn = NULL;
2562 static char* kwnames[] = { "txn", "flags", NULL };
2564 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2565 &txnobj, &flags))
2566 return NULL;
2567 CHECK_DB_NOT_CLOSED(self);
2568 if (!checkTxnObj(txnobj, &txn))
2569 return NULL;
2571 MYDB_BEGIN_ALLOW_THREADS;
2572 err = self->db->truncate(self->db, txn, &count, flags);
2573 MYDB_END_ALLOW_THREADS;
2574 RETURN_IF_ERR();
2575 return PyInt_FromLong(count);
2577 #endif
2580 static PyObject*
2581 DB_upgrade(DBObject* self, PyObject* args)
2583 int err, flags=0;
2584 char *filename;
2586 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2587 return NULL;
2588 CHECK_DB_NOT_CLOSED(self);
2590 MYDB_BEGIN_ALLOW_THREADS;
2591 err = self->db->upgrade(self->db, filename, flags);
2592 MYDB_END_ALLOW_THREADS;
2593 RETURN_IF_ERR();
2594 RETURN_NONE();
2598 static PyObject*
2599 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2601 int err, flags=0;
2602 char* fileName;
2603 char* dbName=NULL;
2604 char* outFileName=NULL;
2605 FILE* outFile=NULL;
2606 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
2607 NULL };
2609 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2610 &fileName, &dbName, &outFileName, &flags))
2611 return NULL;
2613 CHECK_DB_NOT_CLOSED(self);
2614 if (outFileName)
2615 outFile = fopen(outFileName, "w");
2617 MYDB_BEGIN_ALLOW_THREADS;
2618 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2619 MYDB_END_ALLOW_THREADS;
2620 if (outFileName)
2621 fclose(outFile);
2623 /* DB.verify acts as a DB handle destructor (like close); this was
2624 * documented in BerkeleyDB 4.2 but had the undocumented effect
2625 * of not being safe in prior versions while still requiring an explicit
2626 * DB.close call afterwards. Lets call close for the user to emulate
2627 * the safe 4.2 behaviour. */
2628 #if (DBVER <= 41)
2629 self->db->close(self->db, 0);
2630 #endif
2631 self->db = NULL;
2633 RETURN_IF_ERR();
2634 RETURN_NONE();
2638 static PyObject*
2639 DB_set_get_returns_none(DBObject* self, PyObject* args)
2641 int flags=0;
2642 int oldValue=0;
2644 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2645 return NULL;
2646 CHECK_DB_NOT_CLOSED(self);
2648 if (self->moduleFlags.getReturnsNone)
2649 ++oldValue;
2650 if (self->moduleFlags.cursorSetReturnsNone)
2651 ++oldValue;
2652 self->moduleFlags.getReturnsNone = (flags >= 1);
2653 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2654 return PyInt_FromLong(oldValue);
2657 #if (DBVER >= 41)
2658 static PyObject*
2659 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2661 int err;
2662 u_int32_t flags=0;
2663 char *passwd = NULL;
2664 static char* kwnames[] = { "passwd", "flags", NULL };
2666 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2667 &passwd, &flags)) {
2668 return NULL;
2671 MYDB_BEGIN_ALLOW_THREADS;
2672 err = self->db->set_encrypt(self->db, passwd, flags);
2673 MYDB_END_ALLOW_THREADS;
2675 RETURN_IF_ERR();
2676 RETURN_NONE();
2678 #endif /* DBVER >= 41 */
2681 /*-------------------------------------------------------------- */
2682 /* Mapping and Dictionary-like access routines */
2684 Py_ssize_t DB_length(DBObject* self)
2686 int err;
2687 Py_ssize_t size = 0;
2688 int flags = 0;
2689 void* sp;
2691 if (self->db == NULL) {
2692 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2693 PyErr_SetObject(DBError, t);
2694 Py_DECREF(t);
2695 return -1;
2698 if (self->haveStat) { /* Has the stat function been called recently? If
2699 so, we can use the cached value. */
2700 flags = DB_FAST_STAT;
2703 MYDB_BEGIN_ALLOW_THREADS;
2704 redo_stat_for_length:
2705 #if (DBVER >= 43)
2706 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2707 #elif (DBVER >= 33)
2708 err = self->db->stat(self->db, &sp, flags);
2709 #else
2710 err = self->db->stat(self->db, &sp, NULL, flags);
2711 #endif
2713 /* All the stat structures have matching fields upto the ndata field,
2714 so we can use any of them for the type cast */
2715 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2717 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2718 * redo a full stat to make sure.
2719 * Fixes SF python bug 1493322, pybsddb bug 1184012
2721 if (size == 0 && (flags & DB_FAST_STAT)) {
2722 flags = 0;
2723 goto redo_stat_for_length;
2726 MYDB_END_ALLOW_THREADS;
2728 if (err)
2729 return -1;
2731 self->haveStat = 1;
2733 free(sp);
2734 return size;
2738 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2740 int err;
2741 PyObject* retval;
2742 DBT key;
2743 DBT data;
2745 CHECK_DB_NOT_CLOSED(self);
2746 if (!make_key_dbt(self, keyobj, &key, NULL))
2747 return NULL;
2749 CLEAR_DBT(data);
2750 if (CHECK_DBFLAG(self, DB_THREAD)) {
2751 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2752 data.flags = DB_DBT_MALLOC;
2754 MYDB_BEGIN_ALLOW_THREADS;
2755 err = self->db->get(self->db, NULL, &key, &data, 0);
2756 MYDB_END_ALLOW_THREADS;
2757 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2758 PyErr_SetObject(PyExc_KeyError, keyobj);
2759 retval = NULL;
2761 else if (makeDBError(err)) {
2762 retval = NULL;
2764 else {
2765 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2766 FREE_DBT(data);
2769 FREE_DBT(key);
2770 return retval;
2774 static int
2775 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2777 DBT key, data;
2778 int retval;
2779 int flags = 0;
2781 if (self->db == NULL) {
2782 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2783 PyErr_SetObject(DBError, t);
2784 Py_DECREF(t);
2785 return -1;
2788 if (!make_key_dbt(self, keyobj, &key, NULL))
2789 return -1;
2791 if (dataobj != NULL) {
2792 if (!make_dbt(dataobj, &data))
2793 retval = -1;
2794 else {
2795 if (self->setflags & (DB_DUP|DB_DUPSORT))
2796 /* dictionaries shouldn't have duplicate keys */
2797 flags = DB_NOOVERWRITE;
2798 retval = _DB_put(self, NULL, &key, &data, flags);
2800 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2801 /* try deleting any old record that matches and then PUT it
2802 * again... */
2803 _DB_delete(self, NULL, &key, 0);
2804 PyErr_Clear();
2805 retval = _DB_put(self, NULL, &key, &data, flags);
2809 else {
2810 /* dataobj == NULL, so delete the key */
2811 retval = _DB_delete(self, NULL, &key, 0);
2813 FREE_DBT(key);
2814 return retval;
2818 static PyObject*
2819 DB_has_key(DBObject* self, PyObject* args)
2821 int err;
2822 PyObject* keyobj;
2823 DBT key, data;
2824 PyObject* txnobj = NULL;
2825 DB_TXN *txn = NULL;
2827 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2828 return NULL;
2829 CHECK_DB_NOT_CLOSED(self);
2830 if (!make_key_dbt(self, keyobj, &key, NULL))
2831 return NULL;
2832 if (!checkTxnObj(txnobj, &txn)) {
2833 FREE_DBT(key);
2834 return NULL;
2837 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2838 it has a record but can't allocate a buffer for the data. This saves
2839 having to deal with data we won't be using.
2841 CLEAR_DBT(data);
2842 data.flags = DB_DBT_USERMEM;
2844 MYDB_BEGIN_ALLOW_THREADS;
2845 err = self->db->get(self->db, txn, &key, &data, 0);
2846 MYDB_END_ALLOW_THREADS;
2847 FREE_DBT(key);
2849 if (err == DB_BUFFER_SMALL || err == 0) {
2850 return PyInt_FromLong(1);
2851 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2852 return PyInt_FromLong(0);
2855 makeDBError(err);
2856 return NULL;
2860 #define _KEYS_LIST 1
2861 #define _VALUES_LIST 2
2862 #define _ITEMS_LIST 3
2864 static PyObject*
2865 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2867 int err, dbtype;
2868 DBT key;
2869 DBT data;
2870 DBC *cursor;
2871 PyObject* list;
2872 PyObject* item = NULL;
2874 CHECK_DB_NOT_CLOSED(self);
2875 CLEAR_DBT(key);
2876 CLEAR_DBT(data);
2878 dbtype = _DB_get_type(self);
2879 if (dbtype == -1)
2880 return NULL;
2882 list = PyList_New(0);
2883 if (list == NULL)
2884 return NULL;
2886 /* get a cursor */
2887 MYDB_BEGIN_ALLOW_THREADS;
2888 err = self->db->cursor(self->db, txn, &cursor, 0);
2889 MYDB_END_ALLOW_THREADS;
2890 if (makeDBError(err)) {
2891 Py_DECREF(list);
2892 return NULL;
2895 if (CHECK_DBFLAG(self, DB_THREAD)) {
2896 key.flags = DB_DBT_REALLOC;
2897 data.flags = DB_DBT_REALLOC;
2900 while (1) { /* use the cursor to traverse the DB, collecting items */
2901 MYDB_BEGIN_ALLOW_THREADS;
2902 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2903 MYDB_END_ALLOW_THREADS;
2905 if (err) {
2906 /* for any error, break out of the loop */
2907 break;
2910 switch (type) {
2911 case _KEYS_LIST:
2912 switch(dbtype) {
2913 case DB_BTREE:
2914 case DB_HASH:
2915 default:
2916 item = PyString_FromStringAndSize((char*)key.data, key.size);
2917 break;
2918 case DB_RECNO:
2919 case DB_QUEUE:
2920 item = PyInt_FromLong(*((db_recno_t*)key.data));
2921 break;
2923 break;
2925 case _VALUES_LIST:
2926 item = PyString_FromStringAndSize((char*)data.data, data.size);
2927 break;
2929 case _ITEMS_LIST:
2930 switch(dbtype) {
2931 case DB_BTREE:
2932 case DB_HASH:
2933 default:
2934 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2935 data.size);
2936 break;
2937 case DB_RECNO:
2938 case DB_QUEUE:
2939 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2940 data.data, data.size);
2941 break;
2943 break;
2944 default:
2945 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
2946 item = NULL;
2947 break;
2949 if (item == NULL) {
2950 Py_DECREF(list);
2951 list = NULL;
2952 goto done;
2954 PyList_Append(list, item);
2955 Py_DECREF(item);
2958 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2959 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
2960 Py_DECREF(list);
2961 list = NULL;
2964 done:
2965 FREE_DBT(key);
2966 FREE_DBT(data);
2967 MYDB_BEGIN_ALLOW_THREADS;
2968 cursor->c_close(cursor);
2969 MYDB_END_ALLOW_THREADS;
2970 return list;
2974 static PyObject*
2975 DB_keys(DBObject* self, PyObject* args)
2977 PyObject* txnobj = NULL;
2978 DB_TXN *txn = NULL;
2980 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
2981 return NULL;
2982 if (!checkTxnObj(txnobj, &txn))
2983 return NULL;
2984 return _DB_make_list(self, txn, _KEYS_LIST);
2988 static PyObject*
2989 DB_items(DBObject* self, PyObject* args)
2991 PyObject* txnobj = NULL;
2992 DB_TXN *txn = NULL;
2994 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
2995 return NULL;
2996 if (!checkTxnObj(txnobj, &txn))
2997 return NULL;
2998 return _DB_make_list(self, txn, _ITEMS_LIST);
3002 static PyObject*
3003 DB_values(DBObject* self, PyObject* args)
3005 PyObject* txnobj = NULL;
3006 DB_TXN *txn = NULL;
3008 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
3009 return NULL;
3010 if (!checkTxnObj(txnobj, &txn))
3011 return NULL;
3012 return _DB_make_list(self, txn, _VALUES_LIST);
3015 /* --------------------------------------------------------------------- */
3016 /* DBCursor methods */
3019 static PyObject*
3020 DBC_close(DBCursorObject* self, PyObject* args)
3022 int err = 0;
3024 if (!PyArg_ParseTuple(args, ":close"))
3025 return NULL;
3027 if (self->dbc != NULL) {
3028 MYDB_BEGIN_ALLOW_THREADS;
3029 err = self->dbc->c_close(self->dbc);
3030 self->dbc = NULL;
3031 MYDB_END_ALLOW_THREADS;
3033 RETURN_IF_ERR();
3034 RETURN_NONE();
3038 static PyObject*
3039 DBC_count(DBCursorObject* self, PyObject* args)
3041 int err = 0;
3042 db_recno_t count;
3043 int flags = 0;
3045 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3046 return NULL;
3048 CHECK_CURSOR_NOT_CLOSED(self);
3050 MYDB_BEGIN_ALLOW_THREADS;
3051 err = self->dbc->c_count(self->dbc, &count, flags);
3052 MYDB_END_ALLOW_THREADS;
3053 RETURN_IF_ERR();
3055 return PyInt_FromLong(count);
3059 static PyObject*
3060 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3062 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3066 static PyObject*
3067 DBC_delete(DBCursorObject* self, PyObject* args)
3069 int err, flags=0;
3071 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3072 return NULL;
3074 CHECK_CURSOR_NOT_CLOSED(self);
3076 MYDB_BEGIN_ALLOW_THREADS;
3077 err = self->dbc->c_del(self->dbc, flags);
3078 MYDB_END_ALLOW_THREADS;
3079 RETURN_IF_ERR();
3081 self->mydb->haveStat = 0;
3082 RETURN_NONE();
3086 static PyObject*
3087 DBC_dup(DBCursorObject* self, PyObject* args)
3089 int err, flags =0;
3090 DBC* dbc = NULL;
3092 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3093 return NULL;
3095 CHECK_CURSOR_NOT_CLOSED(self);
3097 MYDB_BEGIN_ALLOW_THREADS;
3098 err = self->dbc->c_dup(self->dbc, &dbc, flags);
3099 MYDB_END_ALLOW_THREADS;
3100 RETURN_IF_ERR();
3102 return (PyObject*) newDBCursorObject(dbc, self->mydb);
3105 static PyObject*
3106 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3108 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3112 static PyObject*
3113 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3115 int err, flags=0;
3116 PyObject* keyobj = NULL;
3117 PyObject* dataobj = NULL;
3118 PyObject* retval = NULL;
3119 int dlen = -1;
3120 int doff = -1;
3121 DBT key, data;
3122 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
3123 NULL };
3125 CLEAR_DBT(key);
3126 CLEAR_DBT(data);
3127 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
3128 &flags, &dlen, &doff))
3130 PyErr_Clear();
3131 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3132 &kwnames[1],
3133 &keyobj, &flags, &dlen, &doff))
3135 PyErr_Clear();
3136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3137 kwnames, &keyobj, &dataobj,
3138 &flags, &dlen, &doff))
3140 return NULL;
3145 CHECK_CURSOR_NOT_CLOSED(self);
3147 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3148 return NULL;
3149 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3150 (!add_partial_dbt(&data, dlen, doff)) )
3152 FREE_DBT(key);
3153 return NULL;
3156 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3157 data.flags = DB_DBT_MALLOC;
3158 if (!(key.flags & DB_DBT_REALLOC)) {
3159 key.flags |= DB_DBT_MALLOC;
3163 MYDB_BEGIN_ALLOW_THREADS;
3164 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3165 MYDB_END_ALLOW_THREADS;
3167 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3168 && self->mydb->moduleFlags.getReturnsNone) {
3169 Py_INCREF(Py_None);
3170 retval = Py_None;
3172 else if (makeDBError(err)) {
3173 retval = NULL;
3175 else {
3176 switch (_DB_get_type(self->mydb)) {
3177 case -1:
3178 retval = NULL;
3179 break;
3180 case DB_BTREE:
3181 case DB_HASH:
3182 default:
3183 retval = Py_BuildValue("s#s#", key.data, key.size,
3184 data.data, data.size);
3185 break;
3186 case DB_RECNO:
3187 case DB_QUEUE:
3188 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3189 data.data, data.size);
3190 break;
3192 FREE_DBT(data);
3194 FREE_DBT(key);
3195 return retval;
3198 #if (DBVER >= 33)
3199 static PyObject*
3200 DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3202 int err, flags=0;
3203 PyObject* keyobj = NULL;
3204 PyObject* dataobj = NULL;
3205 PyObject* retval = NULL;
3206 int dlen = -1;
3207 int doff = -1;
3208 DBT key, pkey, data;
3209 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3210 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
3212 CLEAR_DBT(key);
3213 CLEAR_DBT(data);
3214 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3215 &flags, &dlen, &doff))
3217 PyErr_Clear();
3218 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
3219 kwnames_keyOnly,
3220 &keyobj, &flags, &dlen, &doff))
3222 PyErr_Clear();
3223 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3224 kwnames, &keyobj, &dataobj,
3225 &flags, &dlen, &doff))
3227 return NULL;
3232 CHECK_CURSOR_NOT_CLOSED(self);
3234 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3235 return NULL;
3236 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3237 (!add_partial_dbt(&data, dlen, doff)) ) {
3238 FREE_DBT(key);
3239 return NULL;
3242 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3243 data.flags = DB_DBT_MALLOC;
3244 if (!(key.flags & DB_DBT_REALLOC)) {
3245 key.flags |= DB_DBT_MALLOC;
3249 CLEAR_DBT(pkey);
3250 pkey.flags = DB_DBT_MALLOC;
3252 MYDB_BEGIN_ALLOW_THREADS;
3253 err = self->dbc->c_pget(self->dbc, &key, &pkey, &data, flags);
3254 MYDB_END_ALLOW_THREADS;
3256 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3257 && self->mydb->moduleFlags.getReturnsNone) {
3258 Py_INCREF(Py_None);
3259 retval = Py_None;
3261 else if (makeDBError(err)) {
3262 retval = NULL;
3264 else {
3265 PyObject *pkeyObj;
3266 PyObject *dataObj;
3267 dataObj = PyString_FromStringAndSize(data.data, data.size);
3269 if (self->mydb->primaryDBType == DB_RECNO ||
3270 self->mydb->primaryDBType == DB_QUEUE)
3271 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
3272 else
3273 pkeyObj = PyString_FromStringAndSize(pkey.data, pkey.size);
3275 if (key.data && key.size) /* return key, pkey and data */
3277 PyObject *keyObj;
3278 int type = _DB_get_type(self->mydb);
3279 if (type == DB_RECNO || type == DB_QUEUE)
3280 keyObj = PyInt_FromLong(*(int *)key.data);
3281 else
3282 keyObj = PyString_FromStringAndSize(key.data, key.size);
3283 #if (PY_VERSION_HEX >= 0x02040000)
3284 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
3285 #else
3286 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3287 #endif
3288 Py_DECREF(keyObj);
3289 FREE_DBT(key);
3291 else /* return just the pkey and data */
3293 #if (PY_VERSION_HEX >= 0x02040000)
3294 retval = PyTuple_Pack(2, pkeyObj, dataObj);
3295 #else
3296 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3297 #endif
3299 Py_DECREF(dataObj);
3300 Py_DECREF(pkeyObj);
3301 FREE_DBT(pkey);
3302 FREE_DBT(data);
3304 /* the only time REALLOC should be set is if we used an integer
3305 * key that make_key_dbt malloc'd for us. always free these. */
3306 if (key.flags & DB_DBT_REALLOC) {
3307 FREE_DBT(key);
3309 return retval;
3311 #endif
3314 static PyObject*
3315 DBC_get_recno(DBCursorObject* self, PyObject* args)
3317 int err;
3318 db_recno_t recno;
3319 DBT key;
3320 DBT data;
3322 if (!PyArg_ParseTuple(args, ":get_recno"))
3323 return NULL;
3325 CHECK_CURSOR_NOT_CLOSED(self);
3327 CLEAR_DBT(key);
3328 CLEAR_DBT(data);
3329 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3330 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3331 data.flags = DB_DBT_MALLOC;
3332 key.flags = DB_DBT_MALLOC;
3335 MYDB_BEGIN_ALLOW_THREADS;
3336 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
3337 MYDB_END_ALLOW_THREADS;
3338 RETURN_IF_ERR();
3340 recno = *((db_recno_t*)data.data);
3341 FREE_DBT(key);
3342 FREE_DBT(data);
3343 return PyInt_FromLong(recno);
3347 static PyObject*
3348 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3350 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3354 static PyObject*
3355 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3357 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3361 static PyObject*
3362 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3364 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3368 static PyObject*
3369 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3371 int err, flags = 0;
3372 PyObject* keyobj, *dataobj;
3373 DBT key, data;
3374 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
3375 NULL };
3376 int dlen = -1;
3377 int doff = -1;
3379 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3380 &keyobj, &dataobj, &flags, &dlen, &doff))
3381 return NULL;
3383 CHECK_CURSOR_NOT_CLOSED(self);
3385 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3386 return NULL;
3387 if (!make_dbt(dataobj, &data) ||
3388 !add_partial_dbt(&data, dlen, doff) )
3390 FREE_DBT(key);
3391 return NULL;
3394 MYDB_BEGIN_ALLOW_THREADS;
3395 err = self->dbc->c_put(self->dbc, &key, &data, flags);
3396 MYDB_END_ALLOW_THREADS;
3397 FREE_DBT(key);
3398 RETURN_IF_ERR();
3399 self->mydb->haveStat = 0;
3400 RETURN_NONE();
3404 static PyObject*
3405 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3407 int err, flags = 0;
3408 DBT key, data;
3409 PyObject* retval, *keyobj;
3410 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3411 int dlen = -1;
3412 int doff = -1;
3414 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3415 &keyobj, &flags, &dlen, &doff))
3416 return NULL;
3418 CHECK_CURSOR_NOT_CLOSED(self);
3420 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3421 return NULL;
3423 CLEAR_DBT(data);
3424 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3425 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3426 data.flags = DB_DBT_MALLOC;
3428 if (!add_partial_dbt(&data, dlen, doff)) {
3429 FREE_DBT(key);
3430 return NULL;
3433 MYDB_BEGIN_ALLOW_THREADS;
3434 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
3435 MYDB_END_ALLOW_THREADS;
3436 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3437 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3438 Py_INCREF(Py_None);
3439 retval = Py_None;
3441 else if (makeDBError(err)) {
3442 retval = NULL;
3444 else {
3445 switch (_DB_get_type(self->mydb)) {
3446 case -1:
3447 retval = NULL;
3448 break;
3449 case DB_BTREE:
3450 case DB_HASH:
3451 default:
3452 retval = Py_BuildValue("s#s#", key.data, key.size,
3453 data.data, data.size);
3454 break;
3455 case DB_RECNO:
3456 case DB_QUEUE:
3457 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3458 data.data, data.size);
3459 break;
3461 FREE_DBT(data);
3462 FREE_DBT(key);
3464 /* the only time REALLOC should be set is if we used an integer
3465 * key that make_key_dbt malloc'd for us. always free these. */
3466 if (key.flags & DB_DBT_REALLOC) {
3467 FREE_DBT(key);
3470 return retval;
3474 static PyObject*
3475 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3477 int err, flags = 0;
3478 DBT key, data;
3479 PyObject* retval, *keyobj;
3480 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
3481 int dlen = -1;
3482 int doff = -1;
3484 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3485 &keyobj, &flags, &dlen, &doff))
3486 return NULL;
3488 CHECK_CURSOR_NOT_CLOSED(self);
3490 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3491 return NULL;
3493 CLEAR_DBT(data);
3494 if (!add_partial_dbt(&data, dlen, doff)) {
3495 FREE_DBT(key);
3496 return NULL;
3498 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3499 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3500 data.flags |= DB_DBT_MALLOC;
3501 /* only BTREE databases will return anything in the key */
3502 if (!(key.flags & DB_DBT_REALLOC) && _DB_get_type(self->mydb) == DB_BTREE) {
3503 key.flags |= DB_DBT_MALLOC;
3506 MYDB_BEGIN_ALLOW_THREADS;
3507 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
3508 MYDB_END_ALLOW_THREADS;
3509 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3510 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3511 Py_INCREF(Py_None);
3512 retval = Py_None;
3514 else if (makeDBError(err)) {
3515 retval = NULL;
3517 else {
3518 switch (_DB_get_type(self->mydb)) {
3519 case -1:
3520 retval = NULL;
3521 break;
3522 case DB_BTREE:
3523 case DB_HASH:
3524 default:
3525 retval = Py_BuildValue("s#s#", key.data, key.size,
3526 data.data, data.size);
3527 break;
3528 case DB_RECNO:
3529 case DB_QUEUE:
3530 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3531 data.data, data.size);
3532 break;
3534 FREE_DBT(key);
3535 FREE_DBT(data);
3537 /* the only time REALLOC should be set is if we used an integer
3538 * key that make_key_dbt malloc'd for us. always free these. */
3539 if (key.flags & DB_DBT_REALLOC) {
3540 FREE_DBT(key);
3543 return retval;
3546 static PyObject*
3547 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3548 int flags, unsigned int returnsNone)
3550 int err;
3551 DBT key, data;
3552 PyObject* retval;
3554 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3555 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3556 return NULL;
3557 if (!make_dbt(dataobj, &data)) {
3558 FREE_DBT(key);
3559 return NULL;
3562 MYDB_BEGIN_ALLOW_THREADS;
3563 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
3564 MYDB_END_ALLOW_THREADS;
3565 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
3566 Py_INCREF(Py_None);
3567 retval = Py_None;
3569 else if (makeDBError(err)) {
3570 retval = NULL;
3572 else {
3573 switch (_DB_get_type(self->mydb)) {
3574 case -1:
3575 retval = NULL;
3576 break;
3577 case DB_BTREE:
3578 case DB_HASH:
3579 default:
3580 retval = Py_BuildValue("s#s#", key.data, key.size,
3581 data.data, data.size);
3582 break;
3583 case DB_RECNO:
3584 case DB_QUEUE:
3585 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
3586 data.data, data.size);
3587 break;
3591 FREE_DBT(key);
3592 return retval;
3595 static PyObject*
3596 DBC_get_both(DBCursorObject* self, PyObject* args)
3598 int flags=0;
3599 PyObject *keyobj, *dataobj;
3601 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3602 return NULL;
3604 /* if the cursor is closed, self->mydb may be invalid */
3605 CHECK_CURSOR_NOT_CLOSED(self);
3607 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3608 self->mydb->moduleFlags.getReturnsNone);
3611 /* Return size of entry */
3612 static PyObject*
3613 DBC_get_current_size(DBCursorObject* self, PyObject* args)
3615 int err, flags=DB_CURRENT;
3616 PyObject* retval = NULL;
3617 DBT key, data;
3619 if (!PyArg_ParseTuple(args, ":get_current_size"))
3620 return NULL;
3621 CHECK_CURSOR_NOT_CLOSED(self);
3622 CLEAR_DBT(key);
3623 CLEAR_DBT(data);
3625 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3626 getting the record size. */
3627 data.flags = DB_DBT_USERMEM;
3628 data.ulen = 0;
3629 MYDB_BEGIN_ALLOW_THREADS;
3630 err = self->dbc->c_get(self->dbc, &key, &data, flags);
3631 MYDB_END_ALLOW_THREADS;
3632 if (err == DB_BUFFER_SMALL || !err) {
3633 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3634 retval = PyInt_FromLong((long)data.size);
3635 err = 0;
3638 FREE_DBT(key);
3639 FREE_DBT(data);
3640 RETURN_IF_ERR();
3641 return retval;
3644 static PyObject*
3645 DBC_set_both(DBCursorObject* self, PyObject* args)
3647 int flags=0;
3648 PyObject *keyobj, *dataobj;
3650 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3651 return NULL;
3653 /* if the cursor is closed, self->mydb may be invalid */
3654 CHECK_CURSOR_NOT_CLOSED(self);
3656 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3657 self->mydb->moduleFlags.cursorSetReturnsNone);
3661 static PyObject*
3662 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3664 int err, irecno, flags=0;
3665 db_recno_t recno;
3666 DBT key, data;
3667 PyObject* retval;
3668 int dlen = -1;
3669 int doff = -1;
3670 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3672 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3673 &irecno, &flags, &dlen, &doff))
3674 return NULL;
3676 CHECK_CURSOR_NOT_CLOSED(self);
3678 CLEAR_DBT(key);
3679 recno = (db_recno_t) irecno;
3680 /* use allocated space so DB will be able to realloc room for the real
3681 * key */
3682 key.data = malloc(sizeof(db_recno_t));
3683 if (key.data == NULL) {
3684 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3685 return NULL;
3687 key.size = sizeof(db_recno_t);
3688 key.ulen = key.size;
3689 memcpy(key.data, &recno, sizeof(db_recno_t));
3690 key.flags = DB_DBT_REALLOC;
3692 CLEAR_DBT(data);
3693 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3694 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3695 data.flags = DB_DBT_MALLOC;
3697 if (!add_partial_dbt(&data, dlen, doff)) {
3698 FREE_DBT(key);
3699 return NULL;
3702 MYDB_BEGIN_ALLOW_THREADS;
3703 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3704 MYDB_END_ALLOW_THREADS;
3705 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3706 && self->mydb->moduleFlags.cursorSetReturnsNone) {
3707 Py_INCREF(Py_None);
3708 retval = Py_None;
3710 else if (makeDBError(err)) {
3711 retval = NULL;
3713 else { /* Can only be used for BTrees, so no need to return int key */
3714 retval = Py_BuildValue("s#s#", key.data, key.size,
3715 data.data, data.size);
3716 FREE_DBT(data);
3718 FREE_DBT(key);
3720 return retval;
3724 static PyObject*
3725 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3727 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3731 static PyObject*
3732 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3734 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3738 static PyObject*
3739 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3741 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3745 static PyObject*
3746 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3748 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3752 static PyObject*
3753 DBC_join_item(DBCursorObject* self, PyObject* args)
3755 int err, flags=0;
3756 DBT key, data;
3757 PyObject* retval;
3759 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3760 return NULL;
3762 CHECK_CURSOR_NOT_CLOSED(self);
3764 CLEAR_DBT(key);
3765 CLEAR_DBT(data);
3766 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3767 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3768 key.flags = DB_DBT_MALLOC;
3771 MYDB_BEGIN_ALLOW_THREADS;
3772 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3773 MYDB_END_ALLOW_THREADS;
3774 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3775 && self->mydb->moduleFlags.getReturnsNone) {
3776 Py_INCREF(Py_None);
3777 retval = Py_None;
3779 else if (makeDBError(err)) {
3780 retval = NULL;
3782 else {
3783 retval = Py_BuildValue("s#", key.data, key.size);
3784 FREE_DBT(key);
3787 return retval;
3792 /* --------------------------------------------------------------------- */
3793 /* DBEnv methods */
3796 static PyObject*
3797 DBEnv_close(DBEnvObject* self, PyObject* args)
3799 int err, flags = 0;
3801 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3802 return NULL;
3803 if (!self->closed) { /* Don't close more than once */
3804 MYDB_BEGIN_ALLOW_THREADS;
3805 err = self->db_env->close(self->db_env, flags);
3806 MYDB_END_ALLOW_THREADS;
3807 /* after calling DBEnv->close, regardless of error, this DBEnv
3808 * may not be accessed again (BerkeleyDB docs). */
3809 self->closed = 1;
3810 self->db_env = NULL;
3811 RETURN_IF_ERR();
3813 RETURN_NONE();
3817 static PyObject*
3818 DBEnv_open(DBEnvObject* self, PyObject* args)
3820 int err, flags=0, mode=0660;
3821 char *db_home;
3823 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3824 return NULL;
3826 CHECK_ENV_NOT_CLOSED(self);
3828 MYDB_BEGIN_ALLOW_THREADS;
3829 err = self->db_env->open(self->db_env, db_home, flags, mode);
3830 MYDB_END_ALLOW_THREADS;
3831 RETURN_IF_ERR();
3832 self->closed = 0;
3833 self->flags = flags;
3834 RETURN_NONE();
3838 static PyObject*
3839 DBEnv_remove(DBEnvObject* self, PyObject* args)
3841 int err, flags=0;
3842 char *db_home;
3844 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3845 return NULL;
3846 CHECK_ENV_NOT_CLOSED(self);
3847 MYDB_BEGIN_ALLOW_THREADS;
3848 err = self->db_env->remove(self->db_env, db_home, flags);
3849 MYDB_END_ALLOW_THREADS;
3850 RETURN_IF_ERR();
3851 RETURN_NONE();
3854 #if (DBVER >= 41)
3855 static PyObject*
3856 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3858 int err;
3859 u_int32_t flags=0;
3860 char *file = NULL;
3861 char *database = NULL;
3862 PyObject *txnobj = NULL;
3863 DB_TXN *txn = NULL;
3864 static char* kwnames[] = { "file", "database", "txn", "flags",
3865 NULL };
3867 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3868 &file, &database, &txnobj, &flags)) {
3869 return NULL;
3871 if (!checkTxnObj(txnobj, &txn)) {
3872 return NULL;
3874 CHECK_ENV_NOT_CLOSED(self);
3875 MYDB_BEGIN_ALLOW_THREADS;
3876 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3877 MYDB_END_ALLOW_THREADS;
3878 RETURN_IF_ERR();
3879 RETURN_NONE();
3882 static PyObject*
3883 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3885 int err;
3886 u_int32_t flags=0;
3887 char *file = NULL;
3888 char *database = NULL;
3889 char *newname = NULL;
3890 PyObject *txnobj = NULL;
3891 DB_TXN *txn = NULL;
3892 static char* kwnames[] = { "file", "database", "newname", "txn",
3893 "flags", NULL };
3895 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3896 &file, &database, &newname, &txnobj, &flags)) {
3897 return NULL;
3899 if (!checkTxnObj(txnobj, &txn)) {
3900 return NULL;
3902 CHECK_ENV_NOT_CLOSED(self);
3903 MYDB_BEGIN_ALLOW_THREADS;
3904 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3905 flags);
3906 MYDB_END_ALLOW_THREADS;
3907 RETURN_IF_ERR();
3908 RETURN_NONE();
3911 static PyObject*
3912 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3914 int err;
3915 u_int32_t flags=0;
3916 char *passwd = NULL;
3917 static char* kwnames[] = { "passwd", "flags", NULL };
3919 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3920 &passwd, &flags)) {
3921 return NULL;
3924 MYDB_BEGIN_ALLOW_THREADS;
3925 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3926 MYDB_END_ALLOW_THREADS;
3928 RETURN_IF_ERR();
3929 RETURN_NONE();
3931 #endif /* DBVER >= 41 */
3933 #if (DBVER >= 40)
3934 static PyObject*
3935 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3937 int err;
3938 u_int32_t flags=0;
3939 u_int32_t timeout = 0;
3940 static char* kwnames[] = { "timeout", "flags", NULL };
3942 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3943 &timeout, &flags)) {
3944 return NULL;
3947 MYDB_BEGIN_ALLOW_THREADS;
3948 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3949 MYDB_END_ALLOW_THREADS;
3951 RETURN_IF_ERR();
3952 RETURN_NONE();
3954 #endif /* DBVER >= 40 */
3956 static PyObject*
3957 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3959 int err;
3960 long shm_key = 0;
3962 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3963 return NULL;
3964 CHECK_ENV_NOT_CLOSED(self);
3966 err = self->db_env->set_shm_key(self->db_env, shm_key);
3967 RETURN_IF_ERR();
3968 RETURN_NONE();
3971 static PyObject*
3972 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3974 int err, gbytes=0, bytes=0, ncache=0;
3976 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3977 &gbytes, &bytes, &ncache))
3978 return NULL;
3979 CHECK_ENV_NOT_CLOSED(self);
3981 MYDB_BEGIN_ALLOW_THREADS;
3982 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3983 MYDB_END_ALLOW_THREADS;
3984 RETURN_IF_ERR();
3985 RETURN_NONE();
3989 #if (DBVER >= 32)
3990 static PyObject*
3991 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3993 int err, flags=0, onoff=0;
3995 if (!PyArg_ParseTuple(args, "ii:set_flags",
3996 &flags, &onoff))
3997 return NULL;
3998 CHECK_ENV_NOT_CLOSED(self);
4000 MYDB_BEGIN_ALLOW_THREADS;
4001 err = self->db_env->set_flags(self->db_env, flags, onoff);
4002 MYDB_END_ALLOW_THREADS;
4003 RETURN_IF_ERR();
4004 RETURN_NONE();
4006 #endif
4009 static PyObject*
4010 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4012 int err;
4013 char *dir;
4015 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4016 return NULL;
4017 CHECK_ENV_NOT_CLOSED(self);
4019 MYDB_BEGIN_ALLOW_THREADS;
4020 err = self->db_env->set_data_dir(self->db_env, dir);
4021 MYDB_END_ALLOW_THREADS;
4022 RETURN_IF_ERR();
4023 RETURN_NONE();
4027 static PyObject*
4028 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4030 int err, lg_bsize;
4032 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4033 return NULL;
4034 CHECK_ENV_NOT_CLOSED(self);
4036 MYDB_BEGIN_ALLOW_THREADS;
4037 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4038 MYDB_END_ALLOW_THREADS;
4039 RETURN_IF_ERR();
4040 RETURN_NONE();
4044 static PyObject*
4045 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4047 int err;
4048 char *dir;
4050 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4051 return NULL;
4052 CHECK_ENV_NOT_CLOSED(self);
4054 MYDB_BEGIN_ALLOW_THREADS;
4055 err = self->db_env->set_lg_dir(self->db_env, dir);
4056 MYDB_END_ALLOW_THREADS;
4057 RETURN_IF_ERR();
4058 RETURN_NONE();
4061 static PyObject*
4062 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4064 int err, lg_max;
4066 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4067 return NULL;
4068 CHECK_ENV_NOT_CLOSED(self);
4070 MYDB_BEGIN_ALLOW_THREADS;
4071 err = self->db_env->set_lg_max(self->db_env, lg_max);
4072 MYDB_END_ALLOW_THREADS;
4073 RETURN_IF_ERR();
4074 RETURN_NONE();
4078 #if (DBVER >= 33)
4079 static PyObject*
4080 DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4082 int err, lg_max;
4084 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4085 return NULL;
4086 CHECK_ENV_NOT_CLOSED(self);
4088 MYDB_BEGIN_ALLOW_THREADS;
4089 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4090 MYDB_END_ALLOW_THREADS;
4091 RETURN_IF_ERR();
4092 RETURN_NONE();
4094 #endif
4097 static PyObject*
4098 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4100 int err, lk_detect;
4102 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4114 static PyObject*
4115 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4117 int err, max;
4119 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4120 return NULL;
4121 CHECK_ENV_NOT_CLOSED(self);
4123 MYDB_BEGIN_ALLOW_THREADS;
4124 err = self->db_env->set_lk_max(self->db_env, max);
4125 MYDB_END_ALLOW_THREADS;
4126 RETURN_IF_ERR();
4127 RETURN_NONE();
4131 #if (DBVER >= 32)
4133 static PyObject*
4134 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4136 int err, max;
4138 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4139 return NULL;
4140 CHECK_ENV_NOT_CLOSED(self);
4142 MYDB_BEGIN_ALLOW_THREADS;
4143 err = self->db_env->set_lk_max_locks(self->db_env, max);
4144 MYDB_END_ALLOW_THREADS;
4145 RETURN_IF_ERR();
4146 RETURN_NONE();
4150 static PyObject*
4151 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4153 int err, max;
4155 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4156 return NULL;
4157 CHECK_ENV_NOT_CLOSED(self);
4159 MYDB_BEGIN_ALLOW_THREADS;
4160 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4161 MYDB_END_ALLOW_THREADS;
4162 RETURN_IF_ERR();
4163 RETURN_NONE();
4167 static PyObject*
4168 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4170 int err, max;
4172 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4173 return NULL;
4174 CHECK_ENV_NOT_CLOSED(self);
4176 MYDB_BEGIN_ALLOW_THREADS;
4177 err = self->db_env->set_lk_max_objects(self->db_env, max);
4178 MYDB_END_ALLOW_THREADS;
4179 RETURN_IF_ERR();
4180 RETURN_NONE();
4183 #endif
4186 static PyObject*
4187 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4189 int err, mp_mmapsize;
4191 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4192 return NULL;
4193 CHECK_ENV_NOT_CLOSED(self);
4195 MYDB_BEGIN_ALLOW_THREADS;
4196 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4197 MYDB_END_ALLOW_THREADS;
4198 RETURN_IF_ERR();
4199 RETURN_NONE();
4203 static PyObject*
4204 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4206 int err;
4207 char *dir;
4209 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_tmp_dir(self->db_env, dir);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4221 static PyObject*
4222 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4224 int flags = 0;
4225 PyObject* txnobj = NULL;
4226 DB_TXN *txn = NULL;
4227 static char* kwnames[] = { "parent", "flags", NULL };
4229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4230 &txnobj, &flags))
4231 return NULL;
4233 if (!checkTxnObj(txnobj, &txn))
4234 return NULL;
4235 CHECK_ENV_NOT_CLOSED(self);
4237 return (PyObject*)newDBTxnObject(self, txn, flags);
4241 static PyObject*
4242 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4244 int err, kbyte=0, min=0, flags=0;
4246 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4247 return NULL;
4248 CHECK_ENV_NOT_CLOSED(self);
4250 MYDB_BEGIN_ALLOW_THREADS;
4251 #if (DBVER >= 40)
4252 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4253 #else
4254 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4255 #endif
4256 MYDB_END_ALLOW_THREADS;
4257 RETURN_IF_ERR();
4258 RETURN_NONE();
4262 static PyObject*
4263 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4265 int err, max;
4267 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4268 return NULL;
4269 CHECK_ENV_NOT_CLOSED(self);
4271 err = self->db_env->set_tx_max(self->db_env, max);
4272 RETURN_IF_ERR();
4273 RETURN_NONE();
4277 static PyObject*
4278 DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4280 int err;
4281 long stamp;
4282 time_t timestamp;
4284 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
4285 return NULL;
4286 CHECK_ENV_NOT_CLOSED(self);
4287 timestamp = (time_t)stamp;
4288 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
4289 RETURN_IF_ERR();
4290 RETURN_NONE();
4294 static PyObject*
4295 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4297 int err, atype, flags=0;
4298 int aborted = 0;
4300 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4301 return NULL;
4302 CHECK_ENV_NOT_CLOSED(self);
4304 MYDB_BEGIN_ALLOW_THREADS;
4305 #if (DBVER >= 40)
4306 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4307 #else
4308 err = lock_detect(self->db_env, flags, atype, &aborted);
4309 #endif
4310 MYDB_END_ALLOW_THREADS;
4311 RETURN_IF_ERR();
4312 return PyInt_FromLong(aborted);
4316 static PyObject*
4317 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4319 int flags=0;
4320 int locker, lock_mode;
4321 DBT obj;
4322 PyObject* objobj;
4324 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4325 return NULL;
4328 if (!make_dbt(objobj, &obj))
4329 return NULL;
4331 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4335 static PyObject*
4336 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4338 int err;
4339 u_int32_t theID;
4341 if (!PyArg_ParseTuple(args, ":lock_id"))
4342 return NULL;
4344 CHECK_ENV_NOT_CLOSED(self);
4345 MYDB_BEGIN_ALLOW_THREADS;
4346 #if (DBVER >= 40)
4347 err = self->db_env->lock_id(self->db_env, &theID);
4348 #else
4349 err = lock_id(self->db_env, &theID);
4350 #endif
4351 MYDB_END_ALLOW_THREADS;
4352 RETURN_IF_ERR();
4354 return PyInt_FromLong((long)theID);
4358 static PyObject*
4359 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4361 int err;
4362 DBLockObject* dblockobj;
4364 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4365 return NULL;
4367 CHECK_ENV_NOT_CLOSED(self);
4368 MYDB_BEGIN_ALLOW_THREADS;
4369 #if (DBVER >= 40)
4370 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4371 #else
4372 err = lock_put(self->db_env, &dblockobj->lock);
4373 #endif
4374 MYDB_END_ALLOW_THREADS;
4375 RETURN_IF_ERR();
4376 RETURN_NONE();
4379 #if (DBVER >= 44)
4380 static PyObject*
4381 DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4383 int err;
4384 char *file;
4385 u_int32_t flags = 0;
4386 static char* kwnames[] = { "file", "flags", NULL};
4388 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4389 &file, &flags))
4390 return NULL;
4391 CHECK_ENV_NOT_CLOSED(self);
4393 MYDB_BEGIN_ALLOW_THREADS;
4394 err = self->db_env->lsn_reset(self->db_env, file, flags);
4395 MYDB_END_ALLOW_THREADS;
4396 RETURN_IF_ERR();
4397 RETURN_NONE();
4399 #endif /* DBVER >= 4.4 */
4401 #if (DBVER >= 40)
4402 static PyObject*
4403 DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4405 int err;
4406 DB_LOG_STAT* statp = NULL;
4407 PyObject* d = NULL;
4408 u_int32_t flags = 0;
4410 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4411 return NULL;
4412 CHECK_ENV_NOT_CLOSED(self);
4414 MYDB_BEGIN_ALLOW_THREADS;
4415 err = self->db_env->log_stat(self->db_env, &statp, flags);
4416 MYDB_END_ALLOW_THREADS;
4417 RETURN_IF_ERR();
4419 /* Turn the stat structure into a dictionary */
4420 d = PyDict_New();
4421 if (d == NULL) {
4422 if (statp)
4423 free(statp);
4424 return NULL;
4427 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4429 MAKE_ENTRY(magic);
4430 MAKE_ENTRY(version);
4431 MAKE_ENTRY(mode);
4432 MAKE_ENTRY(lg_bsize);
4433 #if (DBVER >= 44)
4434 MAKE_ENTRY(lg_size);
4435 MAKE_ENTRY(record);
4436 #endif
4437 #if (DBVER <= 40)
4438 MAKE_ENTRY(lg_max);
4439 #endif
4440 MAKE_ENTRY(w_mbytes);
4441 MAKE_ENTRY(w_bytes);
4442 MAKE_ENTRY(wc_mbytes);
4443 MAKE_ENTRY(wc_bytes);
4444 MAKE_ENTRY(wcount);
4445 MAKE_ENTRY(wcount_fill);
4446 #if (DBVER >= 44)
4447 MAKE_ENTRY(rcount);
4448 #endif
4449 MAKE_ENTRY(scount);
4450 MAKE_ENTRY(cur_file);
4451 MAKE_ENTRY(cur_offset);
4452 MAKE_ENTRY(disk_file);
4453 MAKE_ENTRY(disk_offset);
4454 MAKE_ENTRY(maxcommitperflush);
4455 MAKE_ENTRY(mincommitperflush);
4456 MAKE_ENTRY(regsize);
4457 MAKE_ENTRY(region_wait);
4458 MAKE_ENTRY(region_nowait);
4460 #undef MAKE_ENTRY
4461 free(statp);
4462 return d;
4463 } /* DBEnv_log_stat */
4464 #endif /* DBVER >= 4.0 for log_stat method */
4467 static PyObject*
4468 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4470 int err;
4471 DB_LOCK_STAT* sp;
4472 PyObject* d = NULL;
4473 u_int32_t flags = 0;
4475 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4476 return NULL;
4477 CHECK_ENV_NOT_CLOSED(self);
4479 MYDB_BEGIN_ALLOW_THREADS;
4480 #if (DBVER >= 40)
4481 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4482 #else
4483 #if (DBVER >= 33)
4484 err = lock_stat(self->db_env, &sp);
4485 #else
4486 err = lock_stat(self->db_env, &sp, NULL);
4487 #endif
4488 #endif
4489 MYDB_END_ALLOW_THREADS;
4490 RETURN_IF_ERR();
4492 /* Turn the stat structure into a dictionary */
4493 d = PyDict_New();
4494 if (d == NULL) {
4495 free(sp);
4496 return NULL;
4499 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4501 #if (DBVER < 41)
4502 MAKE_ENTRY(lastid);
4503 #endif
4504 MAKE_ENTRY(nmodes);
4505 #if (DBVER >= 32)
4506 MAKE_ENTRY(maxlocks);
4507 MAKE_ENTRY(maxlockers);
4508 MAKE_ENTRY(maxobjects);
4509 MAKE_ENTRY(nlocks);
4510 MAKE_ENTRY(maxnlocks);
4511 #endif
4512 MAKE_ENTRY(nlockers);
4513 MAKE_ENTRY(maxnlockers);
4514 #if (DBVER >= 32)
4515 MAKE_ENTRY(nobjects);
4516 MAKE_ENTRY(maxnobjects);
4517 #endif
4518 MAKE_ENTRY(nrequests);
4519 MAKE_ENTRY(nreleases);
4520 #if (DBVER < 44)
4521 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
4522 MAKE_ENTRY(nconflicts);
4523 #else
4524 MAKE_ENTRY(lock_nowait);
4525 MAKE_ENTRY(lock_wait);
4526 #endif
4527 MAKE_ENTRY(ndeadlocks);
4528 MAKE_ENTRY(regsize);
4529 MAKE_ENTRY(region_wait);
4530 MAKE_ENTRY(region_nowait);
4532 #undef MAKE_ENTRY
4533 free(sp);
4534 return d;
4538 static PyObject*
4539 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4541 int flags=0;
4542 int err;
4543 char **log_list = NULL;
4544 PyObject* list;
4545 PyObject* item = NULL;
4547 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4548 return NULL;
4550 CHECK_ENV_NOT_CLOSED(self);
4551 MYDB_BEGIN_ALLOW_THREADS;
4552 #if (DBVER >= 40)
4553 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4554 #elif (DBVER == 33)
4555 err = log_archive(self->db_env, &log_list, flags);
4556 #else
4557 err = log_archive(self->db_env, &log_list, flags, NULL);
4558 #endif
4559 MYDB_END_ALLOW_THREADS;
4560 RETURN_IF_ERR();
4562 list = PyList_New(0);
4563 if (list == NULL) {
4564 if (log_list)
4565 free(log_list);
4566 return NULL;
4569 if (log_list) {
4570 char **log_list_start;
4571 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4572 item = PyString_FromString (*log_list);
4573 if (item == NULL) {
4574 Py_DECREF(list);
4575 list = NULL;
4576 break;
4578 PyList_Append(list, item);
4579 Py_DECREF(item);
4581 free(log_list_start);
4583 return list;
4587 static PyObject*
4588 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4590 int err;
4591 DB_TXN_STAT* sp;
4592 PyObject* d = NULL;
4593 u_int32_t flags=0;
4595 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4596 return NULL;
4597 CHECK_ENV_NOT_CLOSED(self);
4599 MYDB_BEGIN_ALLOW_THREADS;
4600 #if (DBVER >= 40)
4601 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4602 #elif (DBVER == 33)
4603 err = txn_stat(self->db_env, &sp);
4604 #else
4605 err = txn_stat(self->db_env, &sp, NULL);
4606 #endif
4607 MYDB_END_ALLOW_THREADS;
4608 RETURN_IF_ERR();
4610 /* Turn the stat structure into a dictionary */
4611 d = PyDict_New();
4612 if (d == NULL) {
4613 free(sp);
4614 return NULL;
4617 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4619 MAKE_ENTRY(time_ckp);
4620 MAKE_ENTRY(last_txnid);
4621 MAKE_ENTRY(maxtxns);
4622 MAKE_ENTRY(nactive);
4623 MAKE_ENTRY(maxnactive);
4624 MAKE_ENTRY(nbegins);
4625 MAKE_ENTRY(naborts);
4626 MAKE_ENTRY(ncommits);
4627 MAKE_ENTRY(regsize);
4628 MAKE_ENTRY(region_wait);
4629 MAKE_ENTRY(region_nowait);
4631 #undef MAKE_ENTRY
4632 free(sp);
4633 return d;
4637 static PyObject*
4638 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4640 int flags=0;
4641 int oldValue=0;
4643 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4644 return NULL;
4645 CHECK_ENV_NOT_CLOSED(self);
4647 if (self->moduleFlags.getReturnsNone)
4648 ++oldValue;
4649 if (self->moduleFlags.cursorSetReturnsNone)
4650 ++oldValue;
4651 self->moduleFlags.getReturnsNone = (flags >= 1);
4652 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
4653 return PyInt_FromLong(oldValue);
4657 /* --------------------------------------------------------------------- */
4658 /* DBTxn methods */
4661 static PyObject*
4662 DBTxn_commit(DBTxnObject* self, PyObject* args)
4664 int flags=0, err;
4665 DB_TXN *txn;
4667 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
4668 return NULL;
4670 if (!self->txn) {
4671 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4672 "after txn_commit or txn_abort");
4673 PyErr_SetObject(DBError, t);
4674 Py_DECREF(t);
4675 return NULL;
4677 txn = self->txn;
4678 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4679 MYDB_BEGIN_ALLOW_THREADS;
4680 #if (DBVER >= 40)
4681 err = txn->commit(txn, flags);
4682 #else
4683 err = txn_commit(txn, flags);
4684 #endif
4685 MYDB_END_ALLOW_THREADS;
4686 RETURN_IF_ERR();
4687 RETURN_NONE();
4690 static PyObject*
4691 DBTxn_prepare(DBTxnObject* self, PyObject* args)
4693 #if (DBVER >= 33)
4694 int err;
4695 char* gid=NULL;
4696 int gid_size=0;
4698 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
4699 return NULL;
4701 if (gid_size != DB_XIDDATASIZE) {
4702 PyErr_SetString(PyExc_TypeError,
4703 "gid must be DB_XIDDATASIZE bytes long");
4704 return NULL;
4707 if (!self->txn) {
4708 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
4709 "after txn_commit or txn_abort");
4710 PyErr_SetObject(DBError, t);
4711 Py_DECREF(t);
4712 return NULL;
4714 MYDB_BEGIN_ALLOW_THREADS;
4715 #if (DBVER >= 40)
4716 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
4717 #else
4718 err = txn_prepare(self->txn, (u_int8_t*)gid);
4719 #endif
4720 MYDB_END_ALLOW_THREADS;
4721 RETURN_IF_ERR();
4722 RETURN_NONE();
4723 #else
4724 int err;
4726 if (!PyArg_ParseTuple(args, ":prepare"))
4727 return NULL;
4729 if (!self->txn) {
4730 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4731 "after txn_commit or txn_abort");
4732 PyErr_SetObject(DBError, t);
4733 Py_DECREF(t);
4734 return NULL;
4736 MYDB_BEGIN_ALLOW_THREADS;
4737 err = txn_prepare(self->txn);
4738 MYDB_END_ALLOW_THREADS;
4739 RETURN_IF_ERR();
4740 RETURN_NONE();
4741 #endif
4745 static PyObject*
4746 DBTxn_abort(DBTxnObject* self, PyObject* args)
4748 int err;
4749 DB_TXN *txn;
4751 if (!PyArg_ParseTuple(args, ":abort"))
4752 return NULL;
4754 if (!self->txn) {
4755 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4756 "after txn_commit or txn_abort");
4757 PyErr_SetObject(DBError, t);
4758 Py_DECREF(t);
4759 return NULL;
4761 txn = self->txn;
4762 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
4763 MYDB_BEGIN_ALLOW_THREADS;
4764 #if (DBVER >= 40)
4765 err = txn->abort(txn);
4766 #else
4767 err = txn_abort(txn);
4768 #endif
4769 MYDB_END_ALLOW_THREADS;
4770 RETURN_IF_ERR();
4771 RETURN_NONE();
4775 static PyObject*
4776 DBTxn_id(DBTxnObject* self, PyObject* args)
4778 int id;
4780 if (!PyArg_ParseTuple(args, ":id"))
4781 return NULL;
4783 if (!self->txn) {
4784 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
4785 "after txn_commit or txn_abort");
4786 PyErr_SetObject(DBError, t);
4787 Py_DECREF(t);
4788 return NULL;
4790 MYDB_BEGIN_ALLOW_THREADS;
4791 #if (DBVER >= 40)
4792 id = self->txn->id(self->txn);
4793 #else
4794 id = txn_id(self->txn);
4795 #endif
4796 MYDB_END_ALLOW_THREADS;
4797 return PyInt_FromLong(id);
4800 #if (DBVER >= 43)
4801 /* --------------------------------------------------------------------- */
4802 /* DBSequence methods */
4805 static PyObject*
4806 DBSequence_close(DBSequenceObject* self, PyObject* args)
4808 int err, flags=0;
4809 if (!PyArg_ParseTuple(args,"|i:close", &flags))
4810 return NULL;
4811 CHECK_SEQUENCE_NOT_CLOSED(self)
4813 MYDB_BEGIN_ALLOW_THREADS
4814 err = self->sequence->close(self->sequence, flags);
4815 self->sequence = NULL;
4816 MYDB_END_ALLOW_THREADS
4818 RETURN_IF_ERR();
4820 RETURN_NONE();
4823 static PyObject*
4824 DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4826 int err, flags = 0;
4827 int delta = 1;
4828 db_seq_t value;
4829 PyObject *txnobj = NULL;
4830 DB_TXN *txn = NULL;
4831 static char* kwnames[] = {"delta", "txn", "flags", NULL };
4832 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
4833 return NULL;
4834 CHECK_SEQUENCE_NOT_CLOSED(self)
4836 if (!checkTxnObj(txnobj, &txn))
4837 return NULL;
4839 MYDB_BEGIN_ALLOW_THREADS
4840 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
4841 MYDB_END_ALLOW_THREADS
4843 RETURN_IF_ERR();
4844 return PyLong_FromLongLong(value);
4848 static PyObject*
4849 DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
4851 if (!PyArg_ParseTuple(args,":get_dbp"))
4852 return NULL;
4853 CHECK_SEQUENCE_NOT_CLOSED(self)
4854 Py_INCREF(self->mydb);
4855 return (PyObject* )self->mydb;
4858 static PyObject*
4859 DBSequence_get_key(DBSequenceObject* self, PyObject* args)
4861 int err;
4862 DBT key;
4863 CHECK_SEQUENCE_NOT_CLOSED(self)
4864 MYDB_BEGIN_ALLOW_THREADS
4865 err = self->sequence->get_key(self->sequence, &key);
4866 MYDB_END_ALLOW_THREADS
4868 RETURN_IF_ERR();
4870 return PyString_FromStringAndSize(key.data, key.size);
4873 static PyObject*
4874 DBSequence_init_value(DBSequenceObject* self, PyObject* args)
4876 int err;
4877 db_seq_t value;
4878 if (!PyArg_ParseTuple(args,"L:init_value", &value))
4879 return NULL;
4880 CHECK_SEQUENCE_NOT_CLOSED(self)
4882 MYDB_BEGIN_ALLOW_THREADS
4883 err = self->sequence->initial_value(self->sequence, value);
4884 MYDB_END_ALLOW_THREADS
4886 RETURN_IF_ERR();
4888 RETURN_NONE();
4891 static PyObject*
4892 DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4894 int err, flags = 0;
4895 PyObject* keyobj;
4896 PyObject *txnobj = NULL;
4897 DB_TXN *txn = NULL;
4898 DBT key;
4900 static char* kwnames[] = {"key", "txn", "flags", NULL };
4901 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
4902 return NULL;
4904 if (!checkTxnObj(txnobj, &txn))
4905 return NULL;
4907 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
4908 return NULL;
4910 MYDB_BEGIN_ALLOW_THREADS
4911 err = self->sequence->open(self->sequence, txn, &key, flags);
4912 MYDB_END_ALLOW_THREADS
4914 CLEAR_DBT(key);
4915 RETURN_IF_ERR();
4917 RETURN_NONE();
4920 static PyObject*
4921 DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
4923 int err, flags = 0;
4924 PyObject *txnobj = NULL;
4925 DB_TXN *txn = NULL;
4927 static char* kwnames[] = {"txn", "flags", NULL };
4928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
4929 return NULL;
4931 if (!checkTxnObj(txnobj, &txn))
4932 return NULL;
4934 CHECK_SEQUENCE_NOT_CLOSED(self)
4936 MYDB_BEGIN_ALLOW_THREADS
4937 err = self->sequence->remove(self->sequence, txn, flags);
4938 MYDB_END_ALLOW_THREADS
4940 RETURN_IF_ERR();
4941 RETURN_NONE();
4944 static PyObject*
4945 DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
4947 int err, size;
4948 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
4949 return NULL;
4950 CHECK_SEQUENCE_NOT_CLOSED(self)
4952 MYDB_BEGIN_ALLOW_THREADS
4953 err = self->sequence->set_cachesize(self->sequence, size);
4954 MYDB_END_ALLOW_THREADS
4956 RETURN_IF_ERR();
4957 RETURN_NONE();
4960 static PyObject*
4961 DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
4963 int err, size;
4964 if (!PyArg_ParseTuple(args,":get_cachesize"))
4965 return NULL;
4966 CHECK_SEQUENCE_NOT_CLOSED(self)
4968 MYDB_BEGIN_ALLOW_THREADS
4969 err = self->sequence->get_cachesize(self->sequence, &size);
4970 MYDB_END_ALLOW_THREADS
4972 RETURN_IF_ERR();
4973 return PyInt_FromLong(size);
4976 static PyObject*
4977 DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
4979 int err, flags = 0;
4980 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
4981 return NULL;
4982 CHECK_SEQUENCE_NOT_CLOSED(self)
4984 MYDB_BEGIN_ALLOW_THREADS
4985 err = self->sequence->set_flags(self->sequence, flags);
4986 MYDB_END_ALLOW_THREADS
4988 RETURN_IF_ERR();
4989 RETURN_NONE();
4993 static PyObject*
4994 DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
4996 unsigned int flags;
4997 int err;
4998 if (!PyArg_ParseTuple(args,":get_flags"))
4999 return NULL;
5000 CHECK_SEQUENCE_NOT_CLOSED(self)
5002 MYDB_BEGIN_ALLOW_THREADS
5003 err = self->sequence->get_flags(self->sequence, &flags);
5004 MYDB_END_ALLOW_THREADS
5006 RETURN_IF_ERR();
5007 return PyInt_FromLong((int)flags);
5010 static PyObject*
5011 DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5013 int err;
5014 db_seq_t min, max;
5015 if (!PyArg_ParseTuple(args,"LL:set_range", &min, &max))
5016 return NULL;
5017 CHECK_SEQUENCE_NOT_CLOSED(self)
5019 MYDB_BEGIN_ALLOW_THREADS
5020 err = self->sequence->set_range(self->sequence, min, max);
5021 MYDB_END_ALLOW_THREADS
5023 RETURN_IF_ERR();
5024 RETURN_NONE();
5027 static PyObject*
5028 DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5030 int err;
5031 db_seq_t min, max;
5032 if (!PyArg_ParseTuple(args,":get_range"))
5033 return NULL;
5034 CHECK_SEQUENCE_NOT_CLOSED(self)
5036 MYDB_BEGIN_ALLOW_THREADS
5037 err = self->sequence->get_range(self->sequence, &min, &max);
5038 MYDB_END_ALLOW_THREADS
5040 RETURN_IF_ERR();
5041 return Py_BuildValue("(LL)", min, max);
5044 static PyObject*
5045 DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5047 int err, flags = 0;
5048 DB_SEQUENCE_STAT* sp = NULL;
5049 PyObject* dict_stat;
5050 static char* kwnames[] = {"flags", NULL };
5051 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
5052 return NULL;
5053 CHECK_SEQUENCE_NOT_CLOSED(self);
5055 MYDB_BEGIN_ALLOW_THREADS;
5056 err = self->sequence->stat(self->sequence, &sp, flags);
5057 MYDB_END_ALLOW_THREADS;
5058 RETURN_IF_ERR();
5060 if ((dict_stat = PyDict_New()) == NULL) {
5061 free(sp);
5062 return NULL;
5066 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
5067 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
5069 MAKE_INT_ENTRY(wait);
5070 MAKE_INT_ENTRY(nowait);
5071 MAKE_LONG_LONG_ENTRY(current);
5072 MAKE_LONG_LONG_ENTRY(value);
5073 MAKE_LONG_LONG_ENTRY(last_value);
5074 MAKE_LONG_LONG_ENTRY(min);
5075 MAKE_LONG_LONG_ENTRY(max);
5076 MAKE_INT_ENTRY(cache_size);
5077 MAKE_INT_ENTRY(flags);
5079 #undef MAKE_INT_ENTRY
5080 #undef MAKE_LONG_LONG_ENTRY
5082 free(sp);
5083 return dict_stat;
5085 #endif
5088 /* --------------------------------------------------------------------- */
5089 /* Method definition tables and type objects */
5091 static PyMethodDef DB_methods[] = {
5092 {"append", (PyCFunction)DB_append, METH_VARARGS},
5093 #if (DBVER >= 33)
5094 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
5095 #endif
5096 {"close", (PyCFunction)DB_close, METH_VARARGS},
5097 #if (DBVER >= 32)
5098 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
5099 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
5100 #endif
5101 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
5102 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
5103 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
5104 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
5105 #if (DBVER >= 33)
5106 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
5107 #endif
5108 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
5109 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
5110 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
5111 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
5112 {"join", (PyCFunction)DB_join, METH_VARARGS},
5113 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
5114 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
5115 {"items", (PyCFunction)DB_items, METH_VARARGS},
5116 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
5117 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
5118 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
5119 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
5120 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
5121 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
5122 #if (DBVER >= 33)
5123 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
5124 #endif
5125 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
5126 #if (DBVER >= 41)
5127 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5128 #endif
5129 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
5130 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
5131 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
5132 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
5133 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
5134 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
5135 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
5136 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
5137 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
5138 #if (DBVER >= 32)
5139 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
5140 #endif
5141 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
5142 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
5143 #if (DBVER >= 33)
5144 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
5145 #endif
5146 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
5147 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
5148 {"values", (PyCFunction)DB_values, METH_VARARGS},
5149 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
5150 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
5151 {NULL, NULL} /* sentinel */
5155 static PyMappingMethods DB_mapping = {
5156 #if (PY_VERSION_HEX < 0x02050000)
5157 (inquiry)DB_length, /*mp_length*/
5158 #else
5159 (lenfunc)DB_length, /*mp_length*/
5160 #endif
5161 (binaryfunc)DB_subscript, /*mp_subscript*/
5162 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
5166 static PyMethodDef DBCursor_methods[] = {
5167 {"close", (PyCFunction)DBC_close, METH_VARARGS},
5168 {"count", (PyCFunction)DBC_count, METH_VARARGS},
5169 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
5170 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
5171 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
5172 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
5173 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
5174 #if (DBVER >= 33)
5175 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
5176 #endif
5177 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
5178 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
5179 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
5180 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
5181 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
5182 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
5183 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
5184 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
5185 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
5186 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
5187 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
5188 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
5189 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
5190 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
5191 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
5192 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
5193 {NULL, NULL} /* sentinel */
5197 static PyMethodDef DBEnv_methods[] = {
5198 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
5199 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
5200 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
5201 #if (DBVER >= 41)
5202 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
5203 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
5204 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
5205 #endif
5206 #if (DBVER >= 40)
5207 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
5208 #endif
5209 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
5210 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
5211 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
5212 #if (DBVER >= 32)
5213 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
5214 #endif
5215 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
5216 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
5217 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
5218 #if (DBVER >= 33)
5219 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
5220 #endif
5221 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
5222 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
5223 #if (DBVER >= 32)
5224 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
5225 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
5226 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
5227 #endif
5228 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
5229 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
5230 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
5231 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
5232 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
5233 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
5234 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
5235 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
5236 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
5237 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
5238 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
5239 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
5240 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
5241 #if (DBVER >= 40)
5242 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
5243 #endif
5244 #if (DBVER >= 44)
5245 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
5246 #endif
5247 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
5248 {NULL, NULL} /* sentinel */
5252 static PyMethodDef DBTxn_methods[] = {
5253 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
5254 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
5255 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
5256 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
5257 {NULL, NULL} /* sentinel */
5261 #if (DBVER >= 43)
5262 static PyMethodDef DBSequence_methods[] = {
5263 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
5264 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
5265 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
5266 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
5267 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
5268 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
5269 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
5270 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
5271 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
5272 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
5273 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
5274 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
5275 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
5276 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
5277 {NULL, NULL} /* sentinel */
5279 #endif
5282 static PyObject*
5283 DB_getattr(DBObject* self, char *name)
5285 return Py_FindMethod(DB_methods, (PyObject* )self, name);
5289 static PyObject*
5290 DBEnv_getattr(DBEnvObject* self, char *name)
5292 if (!strcmp(name, "db_home")) {
5293 CHECK_ENV_NOT_CLOSED(self);
5294 if (self->db_env->db_home == NULL) {
5295 RETURN_NONE();
5297 return PyString_FromString(self->db_env->db_home);
5300 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
5304 static PyObject*
5305 DBCursor_getattr(DBCursorObject* self, char *name)
5307 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
5310 static PyObject*
5311 DBTxn_getattr(DBTxnObject* self, char *name)
5313 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
5316 static PyObject*
5317 DBLock_getattr(DBLockObject* self, char *name)
5319 return NULL;
5322 #if (DBVER >= 43)
5323 static PyObject*
5324 DBSequence_getattr(DBSequenceObject* self, char *name)
5326 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
5328 #endif
5330 statichere PyTypeObject DB_Type = {
5331 PyObject_HEAD_INIT(NULL)
5332 0, /*ob_size*/
5333 "DB", /*tp_name*/
5334 sizeof(DBObject), /*tp_basicsize*/
5335 0, /*tp_itemsize*/
5336 /* methods */
5337 (destructor)DB_dealloc, /*tp_dealloc*/
5338 0, /*tp_print*/
5339 (getattrfunc)DB_getattr, /*tp_getattr*/
5340 0, /*tp_setattr*/
5341 0, /*tp_compare*/
5342 0, /*tp_repr*/
5343 0, /*tp_as_number*/
5344 0, /*tp_as_sequence*/
5345 &DB_mapping,/*tp_as_mapping*/
5346 0, /*tp_hash*/
5347 #ifdef HAVE_WEAKREF
5348 0, /* tp_call */
5349 0, /* tp_str */
5350 0, /* tp_getattro */
5351 0, /* tp_setattro */
5352 0, /* tp_as_buffer */
5353 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5354 0, /* tp_doc */
5355 0, /* tp_traverse */
5356 0, /* tp_clear */
5357 0, /* tp_richcompare */
5358 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
5359 #endif
5363 statichere PyTypeObject DBCursor_Type = {
5364 PyObject_HEAD_INIT(NULL)
5365 0, /*ob_size*/
5366 "DBCursor", /*tp_name*/
5367 sizeof(DBCursorObject), /*tp_basicsize*/
5368 0, /*tp_itemsize*/
5369 /* methods */
5370 (destructor)DBCursor_dealloc,/*tp_dealloc*/
5371 0, /*tp_print*/
5372 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
5373 0, /*tp_setattr*/
5374 0, /*tp_compare*/
5375 0, /*tp_repr*/
5376 0, /*tp_as_number*/
5377 0, /*tp_as_sequence*/
5378 0, /*tp_as_mapping*/
5379 0, /*tp_hash*/
5380 #ifdef HAVE_WEAKREF
5381 0, /* tp_call */
5382 0, /* tp_str */
5383 0, /* tp_getattro */
5384 0, /* tp_setattro */
5385 0, /* tp_as_buffer */
5386 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5387 0, /* tp_doc */
5388 0, /* tp_traverse */
5389 0, /* tp_clear */
5390 0, /* tp_richcompare */
5391 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
5392 #endif
5396 statichere PyTypeObject DBEnv_Type = {
5397 PyObject_HEAD_INIT(NULL)
5398 0, /*ob_size*/
5399 "DBEnv", /*tp_name*/
5400 sizeof(DBEnvObject), /*tp_basicsize*/
5401 0, /*tp_itemsize*/
5402 /* methods */
5403 (destructor)DBEnv_dealloc, /*tp_dealloc*/
5404 0, /*tp_print*/
5405 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
5406 0, /*tp_setattr*/
5407 0, /*tp_compare*/
5408 0, /*tp_repr*/
5409 0, /*tp_as_number*/
5410 0, /*tp_as_sequence*/
5411 0, /*tp_as_mapping*/
5412 0, /*tp_hash*/
5413 #ifdef HAVE_WEAKREF
5414 0, /* tp_call */
5415 0, /* tp_str */
5416 0, /* tp_getattro */
5417 0, /* tp_setattro */
5418 0, /* tp_as_buffer */
5419 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5420 0, /* tp_doc */
5421 0, /* tp_traverse */
5422 0, /* tp_clear */
5423 0, /* tp_richcompare */
5424 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
5425 #endif
5428 statichere PyTypeObject DBTxn_Type = {
5429 PyObject_HEAD_INIT(NULL)
5430 0, /*ob_size*/
5431 "DBTxn", /*tp_name*/
5432 sizeof(DBTxnObject), /*tp_basicsize*/
5433 0, /*tp_itemsize*/
5434 /* methods */
5435 (destructor)DBTxn_dealloc, /*tp_dealloc*/
5436 0, /*tp_print*/
5437 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
5438 0, /*tp_setattr*/
5439 0, /*tp_compare*/
5440 0, /*tp_repr*/
5441 0, /*tp_as_number*/
5442 0, /*tp_as_sequence*/
5443 0, /*tp_as_mapping*/
5444 0, /*tp_hash*/
5445 #ifdef HAVE_WEAKREF
5446 0, /* tp_call */
5447 0, /* tp_str */
5448 0, /* tp_getattro */
5449 0, /* tp_setattro */
5450 0, /* tp_as_buffer */
5451 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5452 0, /* tp_doc */
5453 0, /* tp_traverse */
5454 0, /* tp_clear */
5455 0, /* tp_richcompare */
5456 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
5457 #endif
5461 statichere PyTypeObject DBLock_Type = {
5462 PyObject_HEAD_INIT(NULL)
5463 0, /*ob_size*/
5464 "DBLock", /*tp_name*/
5465 sizeof(DBLockObject), /*tp_basicsize*/
5466 0, /*tp_itemsize*/
5467 /* methods */
5468 (destructor)DBLock_dealloc, /*tp_dealloc*/
5469 0, /*tp_print*/
5470 (getattrfunc)DBLock_getattr, /*tp_getattr*/
5471 0, /*tp_setattr*/
5472 0, /*tp_compare*/
5473 0, /*tp_repr*/
5474 0, /*tp_as_number*/
5475 0, /*tp_as_sequence*/
5476 0, /*tp_as_mapping*/
5477 0, /*tp_hash*/
5478 #ifdef HAVE_WEAKREF
5479 0, /* tp_call */
5480 0, /* tp_str */
5481 0, /* tp_getattro */
5482 0, /* tp_setattro */
5483 0, /* tp_as_buffer */
5484 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5485 0, /* tp_doc */
5486 0, /* tp_traverse */
5487 0, /* tp_clear */
5488 0, /* tp_richcompare */
5489 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
5490 #endif
5493 #if (DBVER >= 43)
5494 statichere PyTypeObject DBSequence_Type = {
5495 PyObject_HEAD_INIT(NULL)
5496 0, /*ob_size*/
5497 "DBSequence", /*tp_name*/
5498 sizeof(DBSequenceObject), /*tp_basicsize*/
5499 0, /*tp_itemsize*/
5500 /* methods */
5501 (destructor)DBSequence_dealloc, /*tp_dealloc*/
5502 0, /*tp_print*/
5503 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
5504 0, /*tp_setattr*/
5505 0, /*tp_compare*/
5506 0, /*tp_repr*/
5507 0, /*tp_as_number*/
5508 0, /*tp_as_sequence*/
5509 0, /*tp_as_mapping*/
5510 0, /*tp_hash*/
5511 #ifdef HAVE_WEAKREF
5512 0, /* tp_call */
5513 0, /* tp_str */
5514 0, /* tp_getattro */
5515 0, /* tp_setattro */
5516 0, /* tp_as_buffer */
5517 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
5518 0, /* tp_doc */
5519 0, /* tp_traverse */
5520 0, /* tp_clear */
5521 0, /* tp_richcompare */
5522 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
5523 #endif
5525 #endif
5527 /* --------------------------------------------------------------------- */
5528 /* Module-level functions */
5530 static PyObject*
5531 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5533 PyObject* dbenvobj = NULL;
5534 int flags = 0;
5535 static char* kwnames[] = { "dbEnv", "flags", NULL};
5537 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
5538 &dbenvobj, &flags))
5539 return NULL;
5540 if (dbenvobj == Py_None)
5541 dbenvobj = NULL;
5542 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
5543 makeTypeError("DBEnv", dbenvobj);
5544 return NULL;
5547 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
5551 static PyObject*
5552 DBEnv_construct(PyObject* self, PyObject* args)
5554 int flags = 0;
5555 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
5556 return (PyObject* )newDBEnvObject(flags);
5559 #if (DBVER >= 43)
5560 static PyObject*
5561 DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
5563 PyObject* dbobj = NULL;
5564 int flags = 0;
5565 static char* kwnames[] = { "db", "flags", NULL};
5567 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
5568 return NULL;
5569 if (dbobj == Py_None)
5570 dbobj = NULL;
5571 else if (dbobj && !DBObject_Check(dbobj)) {
5572 makeTypeError("DB", dbobj);
5573 return NULL;
5575 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
5577 #endif
5579 static char bsddb_version_doc[] =
5580 "Returns a tuple of major, minor, and patch release numbers of the\n\
5581 underlying DB library.";
5583 static PyObject*
5584 bsddb_version(PyObject* self, PyObject* args)
5586 int major, minor, patch;
5588 if (!PyArg_ParseTuple(args, ":version"))
5589 return NULL;
5590 db_version(&major, &minor, &patch);
5591 return Py_BuildValue("(iii)", major, minor, patch);
5595 /* List of functions defined in the module */
5597 static PyMethodDef bsddb_methods[] = {
5598 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
5599 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
5600 #if (DBVER >= 43)
5601 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
5602 #endif
5603 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
5604 {NULL, NULL} /* sentinel */
5608 /* --------------------------------------------------------------------- */
5609 /* Module initialization */
5612 /* Convenience routine to export an integer value.
5613 * Errors are silently ignored, for better or for worse...
5615 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5617 #define MODULE_NAME_MAX_LEN 11
5618 static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
5620 DL_EXPORT(void) init_bsddb(void)
5622 PyObject* m;
5623 PyObject* d;
5624 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
5625 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
5626 PyObject* cvsid_s = PyString_FromString( rcs_id );
5628 /* Initialize the type of the new type objects here; doing it here
5629 is required for portability to Windows without requiring C++. */
5630 DB_Type.ob_type = &PyType_Type;
5631 DBCursor_Type.ob_type = &PyType_Type;
5632 DBEnv_Type.ob_type = &PyType_Type;
5633 DBTxn_Type.ob_type = &PyType_Type;
5634 DBLock_Type.ob_type = &PyType_Type;
5635 #if (DBVER >= 43)
5636 DBSequence_Type.ob_type = &PyType_Type;
5637 #endif
5640 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5641 /* Save the current interpreter, so callbacks can do the right thing. */
5642 _db_interpreterState = PyThreadState_GET()->interp;
5643 #endif
5645 /* Create the module and add the functions */
5646 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
5647 if (m == NULL)
5648 return;
5650 /* Add some symbolic constants to the module */
5651 d = PyModule_GetDict(m);
5652 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
5653 PyDict_SetItemString(d, "cvsid", cvsid_s);
5654 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
5655 Py_DECREF(pybsddb_version_s);
5656 pybsddb_version_s = NULL;
5657 Py_DECREF(cvsid_s);
5658 cvsid_s = NULL;
5659 Py_DECREF(db_version_s);
5660 db_version_s = NULL;
5662 ADD_INT(d, DB_VERSION_MAJOR);
5663 ADD_INT(d, DB_VERSION_MINOR);
5664 ADD_INT(d, DB_VERSION_PATCH);
5666 ADD_INT(d, DB_MAX_PAGES);
5667 ADD_INT(d, DB_MAX_RECORDS);
5669 #if (DBVER >= 42)
5670 ADD_INT(d, DB_RPCCLIENT);
5671 #else
5672 ADD_INT(d, DB_CLIENT);
5673 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5674 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
5675 #endif
5676 ADD_INT(d, DB_XA_CREATE);
5678 ADD_INT(d, DB_CREATE);
5679 ADD_INT(d, DB_NOMMAP);
5680 ADD_INT(d, DB_THREAD);
5682 ADD_INT(d, DB_FORCE);
5683 ADD_INT(d, DB_INIT_CDB);
5684 ADD_INT(d, DB_INIT_LOCK);
5685 ADD_INT(d, DB_INIT_LOG);
5686 ADD_INT(d, DB_INIT_MPOOL);
5687 ADD_INT(d, DB_INIT_TXN);
5688 #if (DBVER >= 32)
5689 ADD_INT(d, DB_JOINENV);
5690 #endif
5692 ADD_INT(d, DB_RECOVER);
5693 ADD_INT(d, DB_RECOVER_FATAL);
5694 ADD_INT(d, DB_TXN_NOSYNC);
5695 ADD_INT(d, DB_USE_ENVIRON);
5696 ADD_INT(d, DB_USE_ENVIRON_ROOT);
5698 ADD_INT(d, DB_LOCKDOWN);
5699 ADD_INT(d, DB_PRIVATE);
5700 ADD_INT(d, DB_SYSTEM_MEM);
5702 ADD_INT(d, DB_TXN_SYNC);
5703 ADD_INT(d, DB_TXN_NOWAIT);
5705 ADD_INT(d, DB_EXCL);
5706 ADD_INT(d, DB_FCNTL_LOCKING);
5707 ADD_INT(d, DB_ODDFILESIZE);
5708 ADD_INT(d, DB_RDWRMASTER);
5709 ADD_INT(d, DB_RDONLY);
5710 ADD_INT(d, DB_TRUNCATE);
5711 #if (DBVER >= 32)
5712 ADD_INT(d, DB_EXTENT);
5713 ADD_INT(d, DB_CDB_ALLDB);
5714 ADD_INT(d, DB_VERIFY);
5715 #endif
5716 ADD_INT(d, DB_UPGRADE);
5718 ADD_INT(d, DB_AGGRESSIVE);
5719 ADD_INT(d, DB_NOORDERCHK);
5720 ADD_INT(d, DB_ORDERCHKONLY);
5721 ADD_INT(d, DB_PR_PAGE);
5722 #if ! (DBVER >= 33)
5723 ADD_INT(d, DB_VRFY_FLAGMASK);
5724 ADD_INT(d, DB_PR_HEADERS);
5725 #endif
5726 ADD_INT(d, DB_PR_RECOVERYTEST);
5727 ADD_INT(d, DB_SALVAGE);
5729 ADD_INT(d, DB_LOCK_NORUN);
5730 ADD_INT(d, DB_LOCK_DEFAULT);
5731 ADD_INT(d, DB_LOCK_OLDEST);
5732 ADD_INT(d, DB_LOCK_RANDOM);
5733 ADD_INT(d, DB_LOCK_YOUNGEST);
5734 #if (DBVER >= 33)
5735 ADD_INT(d, DB_LOCK_MAXLOCKS);
5736 ADD_INT(d, DB_LOCK_MINLOCKS);
5737 ADD_INT(d, DB_LOCK_MINWRITE);
5738 #endif
5741 #if (DBVER >= 33)
5742 /* docs say to use zero instead */
5743 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
5744 #else
5745 ADD_INT(d, DB_LOCK_CONFLICT);
5746 #endif
5748 ADD_INT(d, DB_LOCK_DUMP);
5749 ADD_INT(d, DB_LOCK_GET);
5750 ADD_INT(d, DB_LOCK_INHERIT);
5751 ADD_INT(d, DB_LOCK_PUT);
5752 ADD_INT(d, DB_LOCK_PUT_ALL);
5753 ADD_INT(d, DB_LOCK_PUT_OBJ);
5755 ADD_INT(d, DB_LOCK_NG);
5756 ADD_INT(d, DB_LOCK_READ);
5757 ADD_INT(d, DB_LOCK_WRITE);
5758 ADD_INT(d, DB_LOCK_NOWAIT);
5759 #if (DBVER >= 32)
5760 ADD_INT(d, DB_LOCK_WAIT);
5761 #endif
5762 ADD_INT(d, DB_LOCK_IWRITE);
5763 ADD_INT(d, DB_LOCK_IREAD);
5764 ADD_INT(d, DB_LOCK_IWR);
5765 #if (DBVER >= 33)
5766 #if (DBVER < 44)
5767 ADD_INT(d, DB_LOCK_DIRTY);
5768 #else
5769 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
5770 #endif
5771 ADD_INT(d, DB_LOCK_WWRITE);
5772 #endif
5774 ADD_INT(d, DB_LOCK_RECORD);
5775 ADD_INT(d, DB_LOCK_UPGRADE);
5776 #if (DBVER >= 32)
5777 ADD_INT(d, DB_LOCK_SWITCH);
5778 #endif
5779 #if (DBVER >= 33)
5780 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
5781 #endif
5783 ADD_INT(d, DB_LOCK_NOWAIT);
5784 ADD_INT(d, DB_LOCK_RECORD);
5785 ADD_INT(d, DB_LOCK_UPGRADE);
5787 #if (DBVER >= 33)
5788 ADD_INT(d, DB_LSTAT_ABORTED);
5789 #if (DBVER < 43)
5790 ADD_INT(d, DB_LSTAT_ERR);
5791 #endif
5792 ADD_INT(d, DB_LSTAT_FREE);
5793 ADD_INT(d, DB_LSTAT_HELD);
5794 #if (DBVER == 33)
5795 ADD_INT(d, DB_LSTAT_NOGRANT);
5796 #endif
5797 ADD_INT(d, DB_LSTAT_PENDING);
5798 ADD_INT(d, DB_LSTAT_WAITING);
5799 #endif
5801 ADD_INT(d, DB_ARCH_ABS);
5802 ADD_INT(d, DB_ARCH_DATA);
5803 ADD_INT(d, DB_ARCH_LOG);
5804 #if (DBVER >= 42)
5805 ADD_INT(d, DB_ARCH_REMOVE);
5806 #endif
5808 ADD_INT(d, DB_BTREE);
5809 ADD_INT(d, DB_HASH);
5810 ADD_INT(d, DB_RECNO);
5811 ADD_INT(d, DB_QUEUE);
5812 ADD_INT(d, DB_UNKNOWN);
5814 ADD_INT(d, DB_DUP);
5815 ADD_INT(d, DB_DUPSORT);
5816 ADD_INT(d, DB_RECNUM);
5817 ADD_INT(d, DB_RENUMBER);
5818 ADD_INT(d, DB_REVSPLITOFF);
5819 ADD_INT(d, DB_SNAPSHOT);
5821 ADD_INT(d, DB_JOIN_NOSORT);
5823 ADD_INT(d, DB_AFTER);
5824 ADD_INT(d, DB_APPEND);
5825 ADD_INT(d, DB_BEFORE);
5826 ADD_INT(d, DB_CACHED_COUNTS);
5827 #if (DBVER >= 41)
5828 _addIntToDict(d, "DB_CHECKPOINT", 0);
5829 #else
5830 ADD_INT(d, DB_CHECKPOINT);
5831 ADD_INT(d, DB_CURLSN);
5832 #endif
5833 #if ((DBVER >= 33) && (DBVER <= 41))
5834 ADD_INT(d, DB_COMMIT);
5835 #endif
5836 ADD_INT(d, DB_CONSUME);
5837 #if (DBVER >= 32)
5838 ADD_INT(d, DB_CONSUME_WAIT);
5839 #endif
5840 ADD_INT(d, DB_CURRENT);
5841 #if (DBVER >= 33)
5842 ADD_INT(d, DB_FAST_STAT);
5843 #endif
5844 ADD_INT(d, DB_FIRST);
5845 ADD_INT(d, DB_FLUSH);
5846 ADD_INT(d, DB_GET_BOTH);
5847 ADD_INT(d, DB_GET_RECNO);
5848 ADD_INT(d, DB_JOIN_ITEM);
5849 ADD_INT(d, DB_KEYFIRST);
5850 ADD_INT(d, DB_KEYLAST);
5851 ADD_INT(d, DB_LAST);
5852 ADD_INT(d, DB_NEXT);
5853 ADD_INT(d, DB_NEXT_DUP);
5854 ADD_INT(d, DB_NEXT_NODUP);
5855 ADD_INT(d, DB_NODUPDATA);
5856 ADD_INT(d, DB_NOOVERWRITE);
5857 ADD_INT(d, DB_NOSYNC);
5858 ADD_INT(d, DB_POSITION);
5859 ADD_INT(d, DB_PREV);
5860 ADD_INT(d, DB_PREV_NODUP);
5861 ADD_INT(d, DB_RECORDCOUNT);
5862 ADD_INT(d, DB_SET);
5863 ADD_INT(d, DB_SET_RANGE);
5864 ADD_INT(d, DB_SET_RECNO);
5865 ADD_INT(d, DB_WRITECURSOR);
5867 ADD_INT(d, DB_OPFLAGS_MASK);
5868 ADD_INT(d, DB_RMW);
5869 #if (DBVER >= 33)
5870 ADD_INT(d, DB_DIRTY_READ);
5871 ADD_INT(d, DB_MULTIPLE);
5872 ADD_INT(d, DB_MULTIPLE_KEY);
5873 #endif
5875 #if (DBVER >= 44)
5876 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
5877 ADD_INT(d, DB_READ_COMMITTED);
5878 #endif
5880 #if (DBVER >= 33)
5881 ADD_INT(d, DB_DONOTINDEX);
5882 #endif
5884 #if (DBVER >= 41)
5885 _addIntToDict(d, "DB_INCOMPLETE", 0);
5886 #else
5887 ADD_INT(d, DB_INCOMPLETE);
5888 #endif
5889 ADD_INT(d, DB_KEYEMPTY);
5890 ADD_INT(d, DB_KEYEXIST);
5891 ADD_INT(d, DB_LOCK_DEADLOCK);
5892 ADD_INT(d, DB_LOCK_NOTGRANTED);
5893 ADD_INT(d, DB_NOSERVER);
5894 ADD_INT(d, DB_NOSERVER_HOME);
5895 ADD_INT(d, DB_NOSERVER_ID);
5896 ADD_INT(d, DB_NOTFOUND);
5897 ADD_INT(d, DB_OLD_VERSION);
5898 ADD_INT(d, DB_RUNRECOVERY);
5899 ADD_INT(d, DB_VERIFY_BAD);
5900 #if (DBVER >= 33)
5901 ADD_INT(d, DB_PAGE_NOTFOUND);
5902 ADD_INT(d, DB_SECONDARY_BAD);
5903 #endif
5904 #if (DBVER >= 40)
5905 ADD_INT(d, DB_STAT_CLEAR);
5906 ADD_INT(d, DB_REGION_INIT);
5907 ADD_INT(d, DB_NOLOCKING);
5908 ADD_INT(d, DB_YIELDCPU);
5909 ADD_INT(d, DB_PANIC_ENVIRONMENT);
5910 ADD_INT(d, DB_NOPANIC);
5911 #endif
5913 #if (DBVER >= 42)
5914 ADD_INT(d, DB_TIME_NOTGRANTED);
5915 ADD_INT(d, DB_TXN_NOT_DURABLE);
5916 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
5917 ADD_INT(d, DB_LOG_AUTOREMOVE);
5918 ADD_INT(d, DB_DIRECT_LOG);
5919 ADD_INT(d, DB_DIRECT_DB);
5920 ADD_INT(d, DB_INIT_REP);
5921 ADD_INT(d, DB_ENCRYPT);
5922 ADD_INT(d, DB_CHKSUM);
5923 #endif
5925 #if (DBVER >= 43)
5926 ADD_INT(d, DB_LOG_INMEMORY);
5927 ADD_INT(d, DB_BUFFER_SMALL);
5928 ADD_INT(d, DB_SEQ_DEC);
5929 ADD_INT(d, DB_SEQ_INC);
5930 ADD_INT(d, DB_SEQ_WRAP);
5931 #endif
5933 #if (DBVER >= 41)
5934 ADD_INT(d, DB_ENCRYPT_AES);
5935 ADD_INT(d, DB_AUTO_COMMIT);
5936 #else
5937 /* allow berkeleydb 4.1 aware apps to run on older versions */
5938 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
5939 #endif
5941 ADD_INT(d, EINVAL);
5942 ADD_INT(d, EACCES);
5943 ADD_INT(d, ENOSPC);
5944 ADD_INT(d, ENOMEM);
5945 ADD_INT(d, EAGAIN);
5946 ADD_INT(d, EBUSY);
5947 ADD_INT(d, EEXIST);
5948 ADD_INT(d, ENOENT);
5949 ADD_INT(d, EPERM);
5951 #if (DBVER >= 40)
5952 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
5953 ADD_INT(d, DB_SET_TXN_TIMEOUT);
5954 #endif
5956 /* The exception name must be correct for pickled exception *
5957 * objects to unpickle properly. */
5958 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5959 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5960 #else
5961 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5962 #endif
5964 /* All the rest of the exceptions derive only from DBError */
5965 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5966 PyDict_SetItemString(d, #name, name)
5968 /* The base exception class is DBError */
5969 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
5970 MAKE_EX(DBError);
5972 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5973 * from both DBError and KeyError, since the API only supports
5974 * using one base class. */
5975 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
5976 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5977 "class DBKeyEmptyError(DBError, KeyError): pass",
5978 Py_file_input, d, d);
5979 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
5980 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
5981 PyDict_DelItemString(d, "KeyError");
5984 #if !INCOMPLETE_IS_WARNING
5985 MAKE_EX(DBIncompleteError);
5986 #endif
5987 MAKE_EX(DBCursorClosedError);
5988 MAKE_EX(DBKeyEmptyError);
5989 MAKE_EX(DBKeyExistError);
5990 MAKE_EX(DBLockDeadlockError);
5991 MAKE_EX(DBLockNotGrantedError);
5992 MAKE_EX(DBOldVersionError);
5993 MAKE_EX(DBRunRecoveryError);
5994 MAKE_EX(DBVerifyBadError);
5995 MAKE_EX(DBNoServerError);
5996 MAKE_EX(DBNoServerHomeError);
5997 MAKE_EX(DBNoServerIDError);
5998 #if (DBVER >= 33)
5999 MAKE_EX(DBPageNotFoundError);
6000 MAKE_EX(DBSecondaryBadError);
6001 #endif
6003 MAKE_EX(DBInvalidArgError);
6004 MAKE_EX(DBAccessError);
6005 MAKE_EX(DBNoSpaceError);
6006 MAKE_EX(DBNoMemoryError);
6007 MAKE_EX(DBAgainError);
6008 MAKE_EX(DBBusyError);
6009 MAKE_EX(DBFileExistsError);
6010 MAKE_EX(DBNoSuchFileError);
6011 MAKE_EX(DBPermissionsError);
6013 #undef MAKE_EX
6015 /* Check for errors */
6016 if (PyErr_Occurred()) {
6017 PyErr_Print();
6018 Py_FatalError("can't initialize module _bsddb");
6022 /* allow this module to be named _pybsddb so that it can be installed
6023 * and imported on top of python >= 2.3 that includes its own older
6024 * copy of the library named _bsddb without importing the old version. */
6025 DL_EXPORT(void) init_pybsddb(void)
6027 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
6028 init_bsddb();