This commit was manufactured by cvs2svn to create tag 'r234'.
[python/dscho.git] / Modules / _bsddb.c
blobef6e2928e81f2730f23353cacded3a901acf80e6
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 5 types:
66 * DB (Database)
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
74 /* --------------------------------------------------------------------- */
77 * Portions of this module, associated unit tests and build scripts are the
78 * result of a contract with The Written Word (http://thewrittenword.com/)
79 * Many thanks go out to them for causing me to raise the bar on quality and
80 * functionality, resulting in a better bsddb3 package for all of us to use.
82 * --Robin
85 /* --------------------------------------------------------------------- */
87 #include <Python.h>
88 #include <db.h>
90 /* --------------------------------------------------------------------- */
91 /* Various macro definitions */
93 /* 40 = 4.0, 33 = 3.3; this will break if the second number is > 9 */
94 #define DBVER (DB_VERSION_MAJOR * 10 + DB_VERSION_MINOR)
96 #define PY_BSDDB_VERSION "4.2.0.2"
97 static char *rcs_id = "$Id$";
100 #ifdef WITH_THREAD
102 /* These are for when calling Python --> C */
103 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
104 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
106 /* For 2.3, use the PyGILState_ calls */
107 #if (PY_VERSION_HEX >= 0x02030000)
108 #define MYDB_USE_GILSTATE
109 #endif
111 /* and these are for calling C --> Python */
112 #if defined(MYDB_USE_GILSTATE)
113 #define MYDB_BEGIN_BLOCK_THREADS \
114 PyGILState_STATE __savestate = PyGILState_Ensure();
115 #define MYDB_END_BLOCK_THREADS \
116 PyGILState_Release(__savestate);
117 #else /* MYDB_USE_GILSTATE */
118 /* Pre GILState API - do it the long old way */
119 static PyInterpreterState* _db_interpreterState = NULL;
120 #define MYDB_BEGIN_BLOCK_THREADS { \
121 PyThreadState* prevState; \
122 PyThreadState* newState; \
123 PyEval_AcquireLock(); \
124 newState = PyThreadState_New(_db_interpreterState); \
125 prevState = PyThreadState_Swap(newState);
127 #define MYDB_END_BLOCK_THREADS \
128 newState = PyThreadState_Swap(prevState); \
129 PyThreadState_Clear(newState); \
130 PyEval_ReleaseLock(); \
131 PyThreadState_Delete(newState); \
133 #endif /* MYDB_USE_GILSTATE */
135 #else
136 /* Compiled without threads - avoid all this cruft */
137 #define MYDB_BEGIN_ALLOW_THREADS
138 #define MYDB_END_ALLOW_THREADS
139 #define MYDB_BEGIN_BLOCK_THREADS
140 #define MYDB_END_BLOCK_THREADS
142 #endif
144 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
145 #define INCOMPLETE_IS_WARNING 1
147 /* --------------------------------------------------------------------- */
148 /* Exceptions */
150 static PyObject* DBError; /* Base class, all others derive from this */
151 static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */
152 static PyObject* DBKeyExistError; /* DB_KEYEXIST */
153 static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
154 static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
155 static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
156 static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
157 static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
158 static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
159 static PyObject* DBNoServerError; /* DB_NOSERVER */
160 static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
161 static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
162 #if (DBVER >= 33)
163 static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
164 static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
165 #endif
167 #if !INCOMPLETE_IS_WARNING
168 static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
169 #endif
171 static PyObject* DBInvalidArgError; /* EINVAL */
172 static PyObject* DBAccessError; /* EACCES */
173 static PyObject* DBNoSpaceError; /* ENOSPC */
174 static PyObject* DBNoMemoryError; /* ENOMEM */
175 static PyObject* DBAgainError; /* EAGAIN */
176 static PyObject* DBBusyError; /* EBUSY */
177 static PyObject* DBFileExistsError; /* EEXIST */
178 static PyObject* DBNoSuchFileError; /* ENOENT */
179 static PyObject* DBPermissionsError; /* EPERM */
183 /* --------------------------------------------------------------------- */
184 /* Structure definitions */
186 struct behaviourFlags {
187 /* What is the default behaviour when DB->get or DBCursor->get returns a
188 DB_NOTFOUND error? Return None or raise an exception? */
189 unsigned int getReturnsNone : 1;
190 /* What is the default behaviour for DBCursor.set* methods when DBCursor->get
191 * returns a DB_NOTFOUND error? Return None or raise an exception? */
192 unsigned int cursorSetReturnsNone : 1;
195 #define DEFAULT_GET_RETURNS_NONE 1
196 #define DEFAULT_CURSOR_SET_RETURNS_NONE 0 /* 0 in pybsddb < 4.2, python < 2.4 */
198 typedef struct {
199 PyObject_HEAD
200 DB_ENV* db_env;
201 u_int32_t flags; /* saved flags from open() */
202 int closed;
203 struct behaviourFlags moduleFlags;
204 } DBEnvObject;
207 typedef struct {
208 PyObject_HEAD
209 DB* db;
210 DBEnvObject* myenvobj; /* PyObject containing the DB_ENV */
211 u_int32_t flags; /* saved flags from open() */
212 u_int32_t setflags; /* saved flags from set_flags() */
213 int haveStat;
214 struct behaviourFlags moduleFlags;
215 #if (DBVER >= 33)
216 PyObject* associateCallback;
217 int primaryDBType;
218 #endif
219 } DBObject;
222 typedef struct {
223 PyObject_HEAD
224 DBC* dbc;
225 DBObject* mydb;
226 } DBCursorObject;
229 typedef struct {
230 PyObject_HEAD
231 DB_TXN* txn;
232 } DBTxnObject;
235 typedef struct {
236 PyObject_HEAD
237 DB_LOCK lock;
238 } DBLockObject;
242 staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
244 #define DBObject_Check(v) ((v)->ob_type == &DB_Type)
245 #define DBCursorObject_Check(v) ((v)->ob_type == &DBCursor_Type)
246 #define DBEnvObject_Check(v) ((v)->ob_type == &DBEnv_Type)
247 #define DBTxnObject_Check(v) ((v)->ob_type == &DBTxn_Type)
248 #define DBLockObject_Check(v) ((v)->ob_type == &DBLock_Type)
251 /* --------------------------------------------------------------------- */
252 /* Utility macros and functions */
254 #define RETURN_IF_ERR() \
255 if (makeDBError(err)) { \
256 return NULL; \
259 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
261 #define CHECK_DB_NOT_CLOSED(dbobj) \
262 if (dbobj->db == NULL) { \
263 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
264 "DB object has been closed")); \
265 return NULL; \
268 #define CHECK_ENV_NOT_CLOSED(env) \
269 if (env->db_env == NULL) { \
270 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
271 "DBEnv object has been closed"));\
272 return NULL; \
275 #define CHECK_CURSOR_NOT_CLOSED(curs) \
276 if (curs->dbc == NULL) { \
277 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
278 "DBCursor object has been closed"));\
279 return NULL; \
284 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
285 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
287 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
289 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
290 dbt.data != NULL) { free(dbt.data); }
293 static int makeDBError(int err);
296 /* Return the access method type of the DBObject */
297 static int _DB_get_type(DBObject* self)
299 #if (DBVER >= 33)
300 DBTYPE type;
301 int err;
302 err = self->db->get_type(self->db, &type);
303 if (makeDBError(err)) {
304 return -1;
306 return type;
307 #else
308 return self->db->get_type(self->db);
309 #endif
313 /* Create a DBT structure (containing key and data values) from Python
314 strings. Returns 1 on success, 0 on an error. */
315 static int make_dbt(PyObject* obj, DBT* dbt)
317 CLEAR_DBT(*dbt);
318 if (obj == Py_None) {
319 /* no need to do anything, the structure has already been zeroed */
321 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
322 PyErr_SetString(PyExc_TypeError,
323 "Key and Data values must be of type string or None.");
324 return 0;
326 return 1;
330 /* Recno and Queue DBs can have integer keys. This function figures out
331 what's been given, verifies that it's allowed, and then makes the DBT.
333 Caller should call FREE_DBT(key) when done. */
334 static int
335 make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
337 db_recno_t recno;
338 int type;
340 CLEAR_DBT(*key);
341 if (keyobj == Py_None) { /* TODO: is None really okay for keys? */
342 /* no need to do anything, the structure has already been zeroed */
345 else if (PyString_Check(keyobj)) {
346 /* verify access method type */
347 type = _DB_get_type(self);
348 if (type == -1)
349 return 0;
350 if (type == DB_RECNO || type == DB_QUEUE) {
351 PyErr_SetString(
352 PyExc_TypeError,
353 "String keys not allowed for Recno and Queue DB's");
354 return 0;
357 key->data = PyString_AS_STRING(keyobj);
358 key->size = PyString_GET_SIZE(keyobj);
361 else if (PyInt_Check(keyobj)) {
362 /* verify access method type */
363 type = _DB_get_type(self);
364 if (type == -1)
365 return 0;
366 if (type == DB_BTREE && pflags != NULL) {
367 /* if BTREE then an Integer key is allowed with the
368 * DB_SET_RECNO flag */
369 *pflags |= DB_SET_RECNO;
371 else if (type != DB_RECNO && type != DB_QUEUE) {
372 PyErr_SetString(
373 PyExc_TypeError,
374 "Integer keys only allowed for Recno and Queue DB's");
375 return 0;
378 /* Make a key out of the requested recno, use allocated space so DB
379 * will be able to realloc room for the real key if needed. */
380 recno = PyInt_AS_LONG(keyobj);
381 key->data = malloc(sizeof(db_recno_t));
382 if (key->data == NULL) {
383 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
384 return 0;
386 key->ulen = key->size = sizeof(db_recno_t);
387 memcpy(key->data, &recno, sizeof(db_recno_t));
388 key->flags = DB_DBT_REALLOC;
390 else {
391 PyErr_Format(PyExc_TypeError,
392 "String or Integer object expected for key, %s found",
393 keyobj->ob_type->tp_name);
394 return 0;
397 return 1;
401 /* Add partial record access to an existing DBT data struct.
402 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
403 and the data storage/retrieval will be done using dlen and doff. */
404 static int add_partial_dbt(DBT* d, int dlen, int doff) {
405 /* if neither were set we do nothing (-1 is the default value) */
406 if ((dlen == -1) && (doff == -1)) {
407 return 1;
410 if ((dlen < 0) || (doff < 0)) {
411 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
412 return 0;
415 d->flags = d->flags | DB_DBT_PARTIAL;
416 d->dlen = (unsigned int) dlen;
417 d->doff = (unsigned int) doff;
418 return 1;
422 /* Callback used to save away more information about errors from the DB
423 * library. */
424 static char _db_errmsg[1024];
425 static void _db_errorCallback(const char* prefix, char* msg)
427 strcpy(_db_errmsg, msg);
431 /* make a nice exception object to raise for errors. */
432 static int makeDBError(int err)
434 char errTxt[2048]; /* really big, just in case... */
435 PyObject *errObj = NULL;
436 PyObject *errTuple = NULL;
437 int exceptionRaised = 0;
439 switch (err) {
440 case 0: /* successful, no error */ break;
442 #if (DBVER < 41)
443 case DB_INCOMPLETE:
444 #if INCOMPLETE_IS_WARNING
445 strcpy(errTxt, db_strerror(err));
446 if (_db_errmsg[0]) {
447 strcat(errTxt, " -- ");
448 strcat(errTxt, _db_errmsg);
449 _db_errmsg[0] = 0;
451 /* if Python 2.1 or better use warning framework */
452 #if PYTHON_API_VERSION >= 1010
453 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
454 #else
455 fprintf(stderr, errTxt);
456 fprintf(stderr, "\n");
457 #endif
459 #else /* do an exception instead */
460 errObj = DBIncompleteError;
461 #endif
462 break;
463 #endif /* DBVER < 41 */
465 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
466 case DB_KEYEXIST: errObj = DBKeyExistError; break;
467 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
468 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
469 case DB_NOTFOUND: errObj = DBNotFoundError; break;
470 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
471 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
472 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
473 case DB_NOSERVER: errObj = DBNoServerError; break;
474 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
475 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
476 #if (DBVER >= 33)
477 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
478 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
479 #endif
481 case EINVAL: errObj = DBInvalidArgError; break;
482 case EACCES: errObj = DBAccessError; break;
483 case ENOSPC: errObj = DBNoSpaceError; break;
484 case ENOMEM: errObj = DBNoMemoryError; break;
485 case EAGAIN: errObj = DBAgainError; break;
486 case EBUSY : errObj = DBBusyError; break;
487 case EEXIST: errObj = DBFileExistsError; break;
488 case ENOENT: errObj = DBNoSuchFileError; break;
489 case EPERM : errObj = DBPermissionsError; break;
491 default: errObj = DBError; break;
494 if (errObj != NULL) {
495 /* FIXME this needs proper bounds checking on errTxt */
496 strcpy(errTxt, db_strerror(err));
497 if (_db_errmsg[0]) {
498 strcat(errTxt, " -- ");
499 strcat(errTxt, _db_errmsg);
500 _db_errmsg[0] = 0;
503 errTuple = Py_BuildValue("(is)", err, errTxt);
504 PyErr_SetObject(errObj, errTuple);
505 Py_DECREF(errTuple);
508 return ((errObj != NULL) || exceptionRaised);
513 /* set a type exception */
514 static void makeTypeError(char* expected, PyObject* found)
516 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
517 expected, found->ob_type->tp_name);
521 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
522 static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
524 if (txnobj == Py_None || txnobj == NULL) {
525 *txn = NULL;
526 return 1;
528 if (DBTxnObject_Check(txnobj)) {
529 *txn = ((DBTxnObject*)txnobj)->txn;
530 return 1;
532 else
533 makeTypeError("DBTxn", txnobj);
534 return 0;
538 /* Delete a key from a database
539 Returns 0 on success, -1 on an error. */
540 static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
542 int err;
544 MYDB_BEGIN_ALLOW_THREADS;
545 err = self->db->del(self->db, txn, key, 0);
546 MYDB_END_ALLOW_THREADS;
547 if (makeDBError(err)) {
548 return -1;
550 self->haveStat = 0;
551 return 0;
555 /* Store a key into a database
556 Returns 0 on success, -1 on an error. */
557 static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
559 int err;
561 MYDB_BEGIN_ALLOW_THREADS;
562 err = self->db->put(self->db, txn, key, data, flags);
563 MYDB_END_ALLOW_THREADS;
564 if (makeDBError(err)) {
565 return -1;
567 self->haveStat = 0;
568 return 0;
571 /* Get a key/data pair from a cursor */
572 static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
573 PyObject *args, PyObject *kwargs, char *format)
575 int err;
576 PyObject* retval = NULL;
577 DBT key, data;
578 int dlen = -1;
579 int doff = -1;
580 int flags = 0;
581 char* kwnames[] = { "flags", "dlen", "doff", NULL };
583 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
584 &flags, &dlen, &doff))
585 return NULL;
587 CHECK_CURSOR_NOT_CLOSED(self);
589 flags |= extra_flags;
590 CLEAR_DBT(key);
591 CLEAR_DBT(data);
592 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
593 /* Tell BerkeleyDB to malloc the return value (thread safe) */
594 data.flags = DB_DBT_MALLOC;
595 key.flags = DB_DBT_MALLOC;
597 if (!add_partial_dbt(&data, dlen, doff))
598 return NULL;
600 MYDB_BEGIN_ALLOW_THREADS;
601 err = self->dbc->c_get(self->dbc, &key, &data, flags);
602 MYDB_END_ALLOW_THREADS;
604 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
605 Py_INCREF(Py_None);
606 retval = Py_None;
608 else if (makeDBError(err)) {
609 retval = NULL;
611 else { /* otherwise, success! */
613 /* if Recno or Queue, return the key as an Int */
614 switch (_DB_get_type(self->mydb)) {
615 case -1:
616 retval = NULL;
617 break;
619 case DB_RECNO:
620 case DB_QUEUE:
621 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
622 data.data, data.size);
623 break;
624 case DB_HASH:
625 case DB_BTREE:
626 default:
627 retval = Py_BuildValue("s#s#", key.data, key.size,
628 data.data, data.size);
629 break;
632 if (!err) {
633 FREE_DBT(key);
634 FREE_DBT(data);
636 return retval;
640 /* add an integer to a dictionary using the given name as a key */
641 static void _addIntToDict(PyObject* dict, char *name, int value)
643 PyObject* v = PyInt_FromLong((long) value);
644 if (!v || PyDict_SetItemString(dict, name, v))
645 PyErr_Clear();
647 Py_XDECREF(v);
653 /* --------------------------------------------------------------------- */
654 /* Allocators and deallocators */
656 static DBObject*
657 newDBObject(DBEnvObject* arg, int flags)
659 DBObject* self;
660 DB_ENV* db_env = NULL;
661 int err;
663 #if PYTHON_API_VERSION <= 1007
664 /* 1.5 compatibility */
665 self = PyObject_NEW(DBObject, &DB_Type);
666 #else
667 self = PyObject_New(DBObject, &DB_Type);
668 #endif
670 if (self == NULL)
671 return NULL;
673 self->haveStat = 0;
674 self->flags = 0;
675 self->setflags = 0;
676 self->myenvobj = NULL;
677 #if (DBVER >= 33)
678 self->associateCallback = NULL;
679 self->primaryDBType = 0;
680 #endif
682 /* keep a reference to our python DBEnv object */
683 if (arg) {
684 Py_INCREF(arg);
685 self->myenvobj = arg;
686 db_env = arg->db_env;
689 if (self->myenvobj)
690 self->moduleFlags = self->myenvobj->moduleFlags;
691 else
692 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
693 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
695 MYDB_BEGIN_ALLOW_THREADS;
696 err = db_create(&self->db, db_env, flags);
697 self->db->set_errcall(self->db, _db_errorCallback);
698 #if (DBVER >= 33)
699 self->db->app_private = (void*)self;
700 #endif
701 MYDB_END_ALLOW_THREADS;
702 if (makeDBError(err)) {
703 if (self->myenvobj) {
704 Py_DECREF(self->myenvobj);
705 self->myenvobj = NULL;
707 self = NULL;
709 return self;
713 static void
714 DB_dealloc(DBObject* self)
716 if (self->db != NULL) {
717 /* avoid closing a DB when its DBEnv has been closed out from under
718 * it */
719 if (!self->myenvobj ||
720 (self->myenvobj && self->myenvobj->db_env))
722 MYDB_BEGIN_ALLOW_THREADS;
723 self->db->close(self->db, 0);
724 MYDB_END_ALLOW_THREADS;
725 /* if Python 2.1 or better use warning framework */
726 #if PYTHON_API_VERSION >= 1010
727 } else {
728 PyErr_Warn(PyExc_RuntimeWarning,
729 "DB could not be closed in destructor: DBEnv already closed");
730 #endif
732 self->db = NULL;
734 if (self->myenvobj) {
735 Py_DECREF(self->myenvobj);
736 self->myenvobj = NULL;
738 #if (DBVER >= 33)
739 if (self->associateCallback != NULL) {
740 Py_DECREF(self->associateCallback);
741 self->associateCallback = NULL;
743 #endif
744 #if PYTHON_API_VERSION <= 1007
745 PyMem_DEL(self);
746 #else
747 PyObject_Del(self);
748 #endif
752 static DBCursorObject*
753 newDBCursorObject(DBC* dbc, DBObject* db)
755 DBCursorObject* self;
756 #if PYTHON_API_VERSION <= 1007
757 self = PyObject_NEW(DBCursorObject, &DBCursor_Type);
758 #else
759 self = PyObject_New(DBCursorObject, &DBCursor_Type);
760 #endif
761 if (self == NULL)
762 return NULL;
764 self->dbc = dbc;
765 self->mydb = db;
766 Py_INCREF(self->mydb);
767 return self;
771 static void
772 DBCursor_dealloc(DBCursorObject* self)
774 int err;
775 if (self->dbc != NULL) {
776 MYDB_BEGIN_ALLOW_THREADS;
777 /* If the underlying database has been closed, we don't
778 need to do anything. If the environment has been closed
779 we need to leak, as BerkeleyDB will crash trying to access
780 the environment. There was an exception when the
781 user closed the environment even though there still was
782 a database open. */
783 if (self->mydb->db && self->mydb->myenvobj &&
784 !self->mydb->myenvobj->closed)
785 err = self->dbc->c_close(self->dbc);
786 self->dbc = NULL;
787 MYDB_END_ALLOW_THREADS;
789 Py_XDECREF( self->mydb );
790 #if PYTHON_API_VERSION <= 1007
791 PyMem_DEL(self);
792 #else
793 PyObject_Del(self);
794 #endif
798 static DBEnvObject*
799 newDBEnvObject(int flags)
801 int err;
802 DBEnvObject* self;
803 #if PYTHON_API_VERSION <= 1007
804 self = PyObject_NEW(DBEnvObject, &DBEnv_Type);
805 #else
806 self = PyObject_New(DBEnvObject, &DBEnv_Type);
807 #endif
809 if (self == NULL)
810 return NULL;
812 self->closed = 1;
813 self->flags = flags;
814 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
815 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
817 MYDB_BEGIN_ALLOW_THREADS;
818 err = db_env_create(&self->db_env, flags);
819 MYDB_END_ALLOW_THREADS;
820 if (makeDBError(err)) {
821 self = NULL;
823 else {
824 self->db_env->set_errcall(self->db_env, _db_errorCallback);
826 return self;
830 static void
831 DBEnv_dealloc(DBEnvObject* self)
833 if (!self->closed) {
834 MYDB_BEGIN_ALLOW_THREADS;
835 self->db_env->close(self->db_env, 0);
836 MYDB_END_ALLOW_THREADS;
838 #if PYTHON_API_VERSION <= 1007
839 PyMem_DEL(self);
840 #else
841 PyObject_Del(self);
842 #endif
846 static DBTxnObject*
847 newDBTxnObject(DBEnvObject* myenv, DB_TXN *parent, int flags)
849 int err;
850 DBTxnObject* self;
852 #if PYTHON_API_VERSION <= 1007
853 self = PyObject_NEW(DBTxnObject, &DBTxn_Type);
854 #else
855 self = PyObject_New(DBTxnObject, &DBTxn_Type);
856 #endif
857 if (self == NULL)
858 return NULL;
860 MYDB_BEGIN_ALLOW_THREADS;
861 #if (DBVER >= 40)
862 err = myenv->db_env->txn_begin(myenv->db_env, parent, &(self->txn), flags);
863 #else
864 err = txn_begin(myenv->db_env, parent, &(self->txn), flags);
865 #endif
866 MYDB_END_ALLOW_THREADS;
867 if (makeDBError(err)) {
868 self = NULL;
870 return self;
874 static void
875 DBTxn_dealloc(DBTxnObject* self)
877 /* XXX nothing to do for transaction objects?!? */
879 /* TODO: if it hasn't been commited, should we abort it? */
881 #if PYTHON_API_VERSION <= 1007
882 PyMem_DEL(self);
883 #else
884 PyObject_Del(self);
885 #endif
889 static DBLockObject*
890 newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
891 db_lockmode_t lock_mode, int flags)
893 int err;
894 DBLockObject* self;
896 #if PYTHON_API_VERSION <= 1007
897 self = PyObject_NEW(DBLockObject, &DBLock_Type);
898 #else
899 self = PyObject_New(DBLockObject, &DBLock_Type);
900 #endif
901 if (self == NULL)
902 return NULL;
904 MYDB_BEGIN_ALLOW_THREADS;
905 #if (DBVER >= 40)
906 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
907 &self->lock);
908 #else
909 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
910 #endif
911 MYDB_END_ALLOW_THREADS;
912 if (makeDBError(err)) {
913 self = NULL;
916 return self;
920 static void
921 DBLock_dealloc(DBLockObject* self)
923 /* TODO: if it hasn't been released, should we do it? */
925 #if PYTHON_API_VERSION <= 1007
926 PyMem_DEL(self);
927 #else
928 PyObject_Del(self);
929 #endif
933 /* --------------------------------------------------------------------- */
934 /* DB methods */
936 static PyObject*
937 DB_append(DBObject* self, PyObject* args)
939 PyObject* txnobj = NULL;
940 PyObject* dataobj;
941 db_recno_t recno;
942 DBT key, data;
943 DB_TXN *txn = NULL;
945 if (!PyArg_ParseTuple(args, "O|O:append", &dataobj, &txnobj))
946 return NULL;
948 CHECK_DB_NOT_CLOSED(self);
950 /* make a dummy key out of a recno */
951 recno = 0;
952 CLEAR_DBT(key);
953 key.data = &recno;
954 key.size = sizeof(recno);
955 key.ulen = key.size;
956 key.flags = DB_DBT_USERMEM;
958 if (!make_dbt(dataobj, &data)) return NULL;
959 if (!checkTxnObj(txnobj, &txn)) return NULL;
961 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
962 return NULL;
964 return PyInt_FromLong(recno);
968 #if (DBVER >= 33)
970 static int
971 _db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
972 DBT* secKey)
974 int retval = DB_DONOTINDEX;
975 DBObject* secondaryDB = (DBObject*)db->app_private;
976 PyObject* callback = secondaryDB->associateCallback;
977 int type = secondaryDB->primaryDBType;
978 PyObject* key;
979 PyObject* data;
980 PyObject* args;
981 PyObject* result;
984 if (callback != NULL) {
985 MYDB_BEGIN_BLOCK_THREADS;
987 if (type == DB_RECNO || type == DB_QUEUE) {
988 key = PyInt_FromLong( *((db_recno_t*)priKey->data));
990 else {
991 key = PyString_FromStringAndSize(priKey->data, priKey->size);
993 data = PyString_FromStringAndSize(priData->data, priData->size);
994 args = PyTuple_New(2);
995 PyTuple_SET_ITEM(args, 0, key); /* steals reference */
996 PyTuple_SET_ITEM(args, 1, data); /* steals reference */
998 result = PyEval_CallObject(callback, args);
1000 if (result == NULL) {
1001 PyErr_Print();
1003 else if (result == Py_None) {
1004 retval = DB_DONOTINDEX;
1006 else if (PyInt_Check(result)) {
1007 retval = PyInt_AsLong(result);
1009 else if (PyString_Check(result)) {
1010 char* data;
1011 int size;
1013 CLEAR_DBT(*secKey);
1014 #if PYTHON_API_VERSION <= 1007
1015 /* 1.5 compatibility */
1016 size = PyString_Size(result);
1017 data = PyString_AsString(result);
1018 #else
1019 PyString_AsStringAndSize(result, &data, &size);
1020 #endif
1021 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1022 secKey->data = malloc(size); /* TODO, check this */
1023 if (secKey->data) {
1024 memcpy(secKey->data, data, size);
1025 secKey->size = size;
1026 retval = 0;
1028 else {
1029 PyErr_SetString(PyExc_MemoryError,
1030 "malloc failed in _db_associateCallback");
1031 PyErr_Print();
1034 else {
1035 PyErr_SetString(
1036 PyExc_TypeError,
1037 "DB associate callback should return DB_DONOTINDEX or string.");
1038 PyErr_Print();
1041 Py_DECREF(args);
1042 if (result) {
1043 Py_DECREF(result);
1046 MYDB_END_BLOCK_THREADS;
1048 return retval;
1052 static PyObject*
1053 DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1055 int err, flags=0;
1056 DBObject* secondaryDB;
1057 PyObject* callback;
1058 #if (DBVER >= 41)
1059 PyObject *txnobj = NULL;
1060 DB_TXN *txn = NULL;
1061 char* kwnames[] = {"secondaryDB", "callback", "flags", "txn", NULL};
1062 #else
1063 char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
1064 #endif
1066 #if (DBVER >= 41)
1067 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1068 &secondaryDB, &callback, &flags,
1069 &txnobj)) {
1070 #else
1071 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
1072 &secondaryDB, &callback, &flags)) {
1073 #endif
1074 return NULL;
1077 #if (DBVER >= 41)
1078 if (!checkTxnObj(txnobj, &txn)) return NULL;
1079 #endif
1081 CHECK_DB_NOT_CLOSED(self);
1082 if (!DBObject_Check(secondaryDB)) {
1083 makeTypeError("DB", (PyObject*)secondaryDB);
1084 return NULL;
1086 if (callback == Py_None) {
1087 callback = NULL;
1089 else if (!PyCallable_Check(callback)) {
1090 makeTypeError("Callable", callback);
1091 return NULL;
1094 /* Save a reference to the callback in the secondary DB. */
1095 if (self->associateCallback != NULL) {
1096 Py_DECREF(self->associateCallback);
1098 Py_INCREF(callback);
1099 secondaryDB->associateCallback = callback;
1100 secondaryDB->primaryDBType = _DB_get_type(self);
1102 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1103 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1104 * The global interepreter lock is not initialized until the first
1105 * thread is created using thread.start_new_thread() or fork() is
1106 * called. that would cause the ALLOW_THREADS here to segfault due
1107 * to a null pointer reference if no threads or child processes
1108 * have been created. This works around that and is a no-op if
1109 * threads have already been initialized.
1110 * (see pybsddb-users mailing list post on 2002-08-07)
1112 #ifdef WITH_THREAD
1113 PyEval_InitThreads();
1114 #endif
1115 MYDB_BEGIN_ALLOW_THREADS;
1116 #if (DBVER >= 41)
1117 err = self->db->associate(self->db,
1118 txn,
1119 secondaryDB->db,
1120 _db_associateCallback,
1121 flags);
1122 #else
1123 err = self->db->associate(self->db,
1124 secondaryDB->db,
1125 _db_associateCallback,
1126 flags);
1127 #endif
1128 MYDB_END_ALLOW_THREADS;
1130 if (err) {
1131 Py_DECREF(self->associateCallback);
1132 self->associateCallback = NULL;
1133 secondaryDB->primaryDBType = 0;
1136 RETURN_IF_ERR();
1137 RETURN_NONE();
1141 #endif
1144 static PyObject*
1145 DB_close(DBObject* self, PyObject* args)
1147 int err, flags=0;
1148 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1149 return NULL;
1150 if (self->db != NULL) {
1151 if (self->myenvobj)
1152 CHECK_ENV_NOT_CLOSED(self->myenvobj);
1153 err = self->db->close(self->db, flags);
1154 self->db = NULL;
1155 RETURN_IF_ERR();
1157 RETURN_NONE();
1161 #if (DBVER >= 32)
1162 static PyObject*
1163 _DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1165 int err, flags=0, type;
1166 PyObject* txnobj = NULL;
1167 PyObject* retval = NULL;
1168 DBT key, data;
1169 DB_TXN *txn = NULL;
1170 char* kwnames[] = { "txn", "flags", NULL };
1172 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1173 &txnobj, &flags))
1174 return NULL;
1176 CHECK_DB_NOT_CLOSED(self);
1177 type = _DB_get_type(self);
1178 if (type == -1)
1179 return NULL;
1180 if (type != DB_QUEUE) {
1181 PyErr_SetString(PyExc_TypeError,
1182 "Consume methods only allowed for Queue DB's");
1183 return NULL;
1185 if (!checkTxnObj(txnobj, &txn))
1186 return NULL;
1188 CLEAR_DBT(key);
1189 CLEAR_DBT(data);
1190 if (CHECK_DBFLAG(self, DB_THREAD)) {
1191 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1192 data.flags = DB_DBT_MALLOC;
1193 key.flags = DB_DBT_MALLOC;
1196 MYDB_BEGIN_ALLOW_THREADS;
1197 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1198 MYDB_END_ALLOW_THREADS;
1200 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1201 err = 0;
1202 Py_INCREF(Py_None);
1203 retval = Py_None;
1205 else if (!err) {
1206 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1207 data.size);
1208 FREE_DBT(key);
1209 FREE_DBT(data);
1212 RETURN_IF_ERR();
1213 return retval;
1216 static PyObject*
1217 DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1219 return _DB_consume(self, args, kwargs, DB_CONSUME);
1222 static PyObject*
1223 DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1224 int consume_flag)
1226 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1228 #endif
1232 static PyObject*
1233 DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1235 int err, flags=0;
1236 DBC* dbc;
1237 PyObject* txnobj = NULL;
1238 DB_TXN *txn = NULL;
1239 char* kwnames[] = { "txn", "flags", NULL };
1241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1242 &txnobj, &flags))
1243 return NULL;
1244 CHECK_DB_NOT_CLOSED(self);
1245 if (!checkTxnObj(txnobj, &txn))
1246 return NULL;
1248 MYDB_BEGIN_ALLOW_THREADS;
1249 err = self->db->cursor(self->db, txn, &dbc, flags);
1250 MYDB_END_ALLOW_THREADS;
1251 RETURN_IF_ERR();
1252 return (PyObject*) newDBCursorObject(dbc, self);
1256 static PyObject*
1257 DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1259 PyObject* txnobj = NULL;
1260 int flags = 0;
1261 PyObject* keyobj;
1262 DBT key;
1263 DB_TXN *txn = NULL;
1264 char* kwnames[] = { "key", "txn", "flags", NULL };
1266 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1267 &keyobj, &txnobj, &flags))
1268 return NULL;
1269 CHECK_DB_NOT_CLOSED(self);
1270 if (!make_key_dbt(self, keyobj, &key, NULL))
1271 return NULL;
1272 if (!checkTxnObj(txnobj, &txn))
1273 return NULL;
1275 if (-1 == _DB_delete(self, txn, &key, 0))
1276 return NULL;
1278 FREE_DBT(key);
1279 RETURN_NONE();
1283 static PyObject*
1284 DB_fd(DBObject* self, PyObject* args)
1286 int err, the_fd;
1288 if (!PyArg_ParseTuple(args,":fd"))
1289 return NULL;
1290 CHECK_DB_NOT_CLOSED(self);
1292 MYDB_BEGIN_ALLOW_THREADS;
1293 err = self->db->fd(self->db, &the_fd);
1294 MYDB_END_ALLOW_THREADS;
1295 RETURN_IF_ERR();
1296 return PyInt_FromLong(the_fd);
1300 static PyObject*
1301 DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1303 int err, flags=0;
1304 PyObject* txnobj = NULL;
1305 PyObject* keyobj;
1306 PyObject* dfltobj = NULL;
1307 PyObject* retval = NULL;
1308 int dlen = -1;
1309 int doff = -1;
1310 DBT key, data;
1311 DB_TXN *txn = NULL;
1312 char* kwnames[] = {"key", "default", "txn", "flags", "dlen", "doff", NULL};
1314 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
1315 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1316 &doff))
1317 return NULL;
1319 CHECK_DB_NOT_CLOSED(self);
1320 if (!make_key_dbt(self, keyobj, &key, &flags))
1321 return NULL;
1322 if (!checkTxnObj(txnobj, &txn))
1323 return NULL;
1325 CLEAR_DBT(data);
1326 if (CHECK_DBFLAG(self, DB_THREAD)) {
1327 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1328 data.flags = DB_DBT_MALLOC;
1330 if (!add_partial_dbt(&data, dlen, doff))
1331 return NULL;
1333 MYDB_BEGIN_ALLOW_THREADS;
1334 err = self->db->get(self->db, txn, &key, &data, flags);
1335 MYDB_END_ALLOW_THREADS;
1337 if ((err == DB_NOTFOUND) && (dfltobj != NULL)) {
1338 err = 0;
1339 Py_INCREF(dfltobj);
1340 retval = dfltobj;
1342 else if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1343 err = 0;
1344 Py_INCREF(Py_None);
1345 retval = Py_None;
1347 else if (!err) {
1348 if (flags & DB_SET_RECNO) /* return both key and data */
1349 retval = Py_BuildValue("s#s#", key.data, key.size, data.data,
1350 data.size);
1351 else /* return just the data */
1352 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1353 FREE_DBT(key);
1354 FREE_DBT(data);
1357 RETURN_IF_ERR();
1358 return retval;
1362 /* Return size of entry */
1363 static PyObject*
1364 DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1366 int err, flags=0;
1367 PyObject* txnobj = NULL;
1368 PyObject* keyobj;
1369 PyObject* retval = NULL;
1370 DBT key, data;
1371 DB_TXN *txn = NULL;
1372 char* kwnames[] = { "key", "txn", NULL };
1374 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1375 &keyobj, &txnobj))
1376 return NULL;
1377 CHECK_DB_NOT_CLOSED(self);
1378 if (!make_key_dbt(self, keyobj, &key, &flags))
1379 return NULL;
1380 if (!checkTxnObj(txnobj, &txn))
1381 return NULL;
1382 CLEAR_DBT(data);
1384 /* We don't allocate any memory, forcing a ENOMEM error and thus
1385 getting the record size. */
1386 data.flags = DB_DBT_USERMEM;
1387 data.ulen = 0;
1388 MYDB_BEGIN_ALLOW_THREADS;
1389 err = self->db->get(self->db, txn, &key, &data, flags);
1390 MYDB_END_ALLOW_THREADS;
1391 if (err == ENOMEM) {
1392 retval = PyInt_FromLong((long)data.size);
1393 err = 0;
1396 FREE_DBT(key);
1397 FREE_DBT(data);
1398 RETURN_IF_ERR();
1399 return retval;
1403 static PyObject*
1404 DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1406 int err, flags=0;
1407 PyObject* txnobj = NULL;
1408 PyObject* keyobj;
1409 PyObject* dataobj;
1410 PyObject* retval = NULL;
1411 DBT key, data;
1412 DB_TXN *txn = NULL;
1413 char* kwnames[] = { "key", "data", "txn", "flags", NULL };
1416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1417 &keyobj, &dataobj, &txnobj, &flags))
1418 return NULL;
1420 CHECK_DB_NOT_CLOSED(self);
1421 if (!make_key_dbt(self, keyobj, &key, NULL))
1422 return NULL;
1423 if (!make_dbt(dataobj, &data))
1424 return NULL;
1425 if (!checkTxnObj(txnobj, &txn))
1426 return NULL;
1428 flags |= DB_GET_BOTH;
1430 if (CHECK_DBFLAG(self, DB_THREAD)) {
1431 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1432 data.flags = DB_DBT_MALLOC;
1433 /* TODO: Is this flag needed? We're passing a data object that should
1434 match what's in the DB, so there should be no need to malloc.
1435 We run the risk of freeing something twice! Check this. */
1438 MYDB_BEGIN_ALLOW_THREADS;
1439 err = self->db->get(self->db, txn, &key, &data, flags);
1440 MYDB_END_ALLOW_THREADS;
1442 if ((err == DB_NOTFOUND) && self->moduleFlags.getReturnsNone) {
1443 err = 0;
1444 Py_INCREF(Py_None);
1445 retval = Py_None;
1447 else if (!err) {
1448 retval = PyString_FromStringAndSize((char*)data.data, data.size);
1449 FREE_DBT(data); /* Only if retrieval was successful */
1452 FREE_DBT(key);
1453 RETURN_IF_ERR();
1454 return retval;
1458 static PyObject*
1459 DB_get_byteswapped(DBObject* self, PyObject* args)
1461 #if (DBVER >= 33)
1462 int err = 0;
1463 #endif
1464 int retval = -1;
1466 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1467 return NULL;
1468 CHECK_DB_NOT_CLOSED(self);
1470 #if (DBVER >= 33)
1471 MYDB_BEGIN_ALLOW_THREADS;
1472 err = self->db->get_byteswapped(self->db, &retval);
1473 MYDB_END_ALLOW_THREADS;
1474 RETURN_IF_ERR();
1475 #else
1476 MYDB_BEGIN_ALLOW_THREADS;
1477 retval = self->db->get_byteswapped(self->db);
1478 MYDB_END_ALLOW_THREADS;
1479 #endif
1480 return PyInt_FromLong(retval);
1484 static PyObject*
1485 DB_get_type(DBObject* self, PyObject* args)
1487 int type;
1489 if (!PyArg_ParseTuple(args,":get_type"))
1490 return NULL;
1491 CHECK_DB_NOT_CLOSED(self);
1493 MYDB_BEGIN_ALLOW_THREADS;
1494 type = _DB_get_type(self);
1495 MYDB_END_ALLOW_THREADS;
1496 if (type == -1)
1497 return NULL;
1498 return PyInt_FromLong(type);
1502 static PyObject*
1503 DB_join(DBObject* self, PyObject* args)
1505 int err, flags=0;
1506 int length, x;
1507 PyObject* cursorsObj;
1508 DBC** cursors;
1509 DBC* dbc;
1512 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1513 return NULL;
1515 CHECK_DB_NOT_CLOSED(self);
1517 if (!PySequence_Check(cursorsObj)) {
1518 PyErr_SetString(PyExc_TypeError,
1519 "Sequence of DBCursor objects expected");
1520 return NULL;
1523 length = PyObject_Length(cursorsObj);
1524 cursors = malloc((length+1) * sizeof(DBC*));
1525 cursors[length] = NULL;
1526 for (x=0; x<length; x++) {
1527 PyObject* item = PySequence_GetItem(cursorsObj, x);
1528 if (!DBCursorObject_Check(item)) {
1529 PyErr_SetString(PyExc_TypeError,
1530 "Sequence of DBCursor objects expected");
1531 free(cursors);
1532 return NULL;
1534 cursors[x] = ((DBCursorObject*)item)->dbc;
1537 MYDB_BEGIN_ALLOW_THREADS;
1538 err = self->db->join(self->db, cursors, &dbc, flags);
1539 MYDB_END_ALLOW_THREADS;
1540 free(cursors);
1541 RETURN_IF_ERR();
1543 // FIXME: this is a buggy interface. The returned cursor
1544 // contains internal references to the passed in cursors
1545 // but does not hold python references to them or prevent
1546 // them from being closed prematurely. This can cause
1547 // python to crash when things are done in the wrong order.
1548 return (PyObject*) newDBCursorObject(dbc, self);
1552 static PyObject*
1553 DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1555 int err, flags=0;
1556 PyObject* txnobj = NULL;
1557 PyObject* keyobj;
1558 DBT key;
1559 DB_TXN *txn = NULL;
1560 DB_KEY_RANGE range;
1561 char* kwnames[] = { "key", "txn", "flags", NULL };
1563 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1564 &keyobj, &txnobj, &flags))
1565 return NULL;
1566 CHECK_DB_NOT_CLOSED(self);
1567 if (!make_dbt(keyobj, &key))
1568 /* BTree only, don't need to allow for an int key */
1569 return NULL;
1570 if (!checkTxnObj(txnobj, &txn))
1571 return NULL;
1573 MYDB_BEGIN_ALLOW_THREADS;
1574 err = self->db->key_range(self->db, txn, &key, &range, flags);
1575 MYDB_END_ALLOW_THREADS;
1577 RETURN_IF_ERR();
1578 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
1582 static PyObject*
1583 DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
1585 int err, type = DB_UNKNOWN, flags=0, mode=0660;
1586 char* filename = NULL;
1587 char* dbname = NULL;
1588 #if (DBVER >= 41)
1589 PyObject *txnobj = NULL;
1590 DB_TXN *txn = NULL;
1591 /* with dbname */
1592 char* kwnames[] = {
1593 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
1594 /* without dbname */
1595 char* kwnames_basic[] = {
1596 "filename", "dbtype", "flags", "mode", "txn", NULL};
1597 #else
1598 /* with dbname */
1599 char* kwnames[] = {
1600 "filename", "dbname", "dbtype", "flags", "mode", NULL};
1601 /* without dbname */
1602 char* kwnames_basic[] = {
1603 "filename", "dbtype", "flags", "mode", NULL};
1604 #endif
1606 #if (DBVER >= 41)
1607 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
1608 &filename, &dbname, &type, &flags, &mode,
1609 &txnobj))
1610 #else
1611 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
1612 &filename, &dbname, &type, &flags,
1613 &mode))
1614 #endif
1616 PyErr_Clear();
1617 type = DB_UNKNOWN; flags = 0; mode = 0660;
1618 filename = NULL; dbname = NULL;
1619 #if (DBVER >= 41)
1620 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
1621 kwnames_basic,
1622 &filename, &type, &flags, &mode,
1623 &txnobj))
1624 return NULL;
1625 #else
1626 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
1627 kwnames_basic,
1628 &filename, &type, &flags, &mode))
1629 return NULL;
1630 #endif
1633 #if (DBVER >= 41)
1634 if (!checkTxnObj(txnobj, &txn)) return NULL;
1635 #endif
1637 if (NULL == self->db) {
1638 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
1639 "Cannot call open() twice for DB object"));
1640 return NULL;
1643 #if 0 && (DBVER >= 41)
1644 if ((!txn) && (txnobj != Py_None) && self->myenvobj
1645 && (self->myenvobj->flags & DB_INIT_TXN))
1647 /* If no 'txn' parameter was supplied (no DbTxn object and None was not
1648 * explicitly passed) but we are in a transaction ready environment:
1649 * add DB_AUTO_COMMIT to allow for older pybsddb apps using transactions
1650 * to work on BerkeleyDB 4.1 without needing to modify their
1651 * DBEnv or DB open calls.
1652 * TODO make this behaviour of the library configurable.
1654 flags |= DB_AUTO_COMMIT;
1656 #endif
1658 MYDB_BEGIN_ALLOW_THREADS;
1659 #if (DBVER >= 41)
1660 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
1661 #else
1662 err = self->db->open(self->db, filename, dbname, type, flags, mode);
1663 #endif
1664 MYDB_END_ALLOW_THREADS;
1665 if (makeDBError(err)) {
1666 self->db->close(self->db, 0);
1667 self->db = NULL;
1668 return NULL;
1671 self->flags = flags;
1672 RETURN_NONE();
1676 static PyObject*
1677 DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
1679 int flags=0;
1680 PyObject* txnobj = NULL;
1681 int dlen = -1;
1682 int doff = -1;
1683 PyObject* keyobj, *dataobj, *retval;
1684 DBT key, data;
1685 DB_TXN *txn = NULL;
1686 char* kwnames[] = { "key", "data", "txn", "flags", "dlen", "doff", NULL };
1688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
1689 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
1690 return NULL;
1692 CHECK_DB_NOT_CLOSED(self);
1693 if (!make_key_dbt(self, keyobj, &key, NULL)) return NULL;
1694 if (!make_dbt(dataobj, &data)) return NULL;
1695 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
1696 if (!checkTxnObj(txnobj, &txn)) return NULL;
1698 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
1699 FREE_DBT(key);
1700 return NULL;
1703 if (flags & DB_APPEND)
1704 retval = PyInt_FromLong(*((db_recno_t*)key.data));
1705 else {
1706 retval = Py_None;
1707 Py_INCREF(retval);
1709 FREE_DBT(key);
1710 return retval;
1715 static PyObject*
1716 DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
1718 char* filename;
1719 char* database = NULL;
1720 int err, flags=0;
1721 char* kwnames[] = { "filename", "dbname", "flags", NULL};
1723 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
1724 &filename, &database, &flags))
1725 return NULL;
1726 CHECK_DB_NOT_CLOSED(self);
1728 err = self->db->remove(self->db, filename, database, flags);
1729 self->db = NULL;
1730 RETURN_IF_ERR();
1731 RETURN_NONE();
1736 static PyObject*
1737 DB_rename(DBObject* self, PyObject* args)
1739 char* filename;
1740 char* database;
1741 char* newname;
1742 int err, flags=0;
1744 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
1745 &flags))
1746 return NULL;
1747 CHECK_DB_NOT_CLOSED(self);
1749 MYDB_BEGIN_ALLOW_THREADS;
1750 err = self->db->rename(self->db, filename, database, newname, flags);
1751 MYDB_END_ALLOW_THREADS;
1752 RETURN_IF_ERR();
1753 RETURN_NONE();
1757 static PyObject*
1758 DB_set_bt_minkey(DBObject* self, PyObject* args)
1760 int err, minkey;
1762 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
1763 return NULL;
1764 CHECK_DB_NOT_CLOSED(self);
1766 MYDB_BEGIN_ALLOW_THREADS;
1767 err = self->db->set_bt_minkey(self->db, minkey);
1768 MYDB_END_ALLOW_THREADS;
1769 RETURN_IF_ERR();
1770 RETURN_NONE();
1774 static PyObject*
1775 DB_set_cachesize(DBObject* self, PyObject* args)
1777 int err;
1778 int gbytes = 0, bytes = 0, ncache = 0;
1780 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
1781 &gbytes,&bytes,&ncache))
1782 return NULL;
1783 CHECK_DB_NOT_CLOSED(self);
1785 MYDB_BEGIN_ALLOW_THREADS;
1786 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
1787 MYDB_END_ALLOW_THREADS;
1788 RETURN_IF_ERR();
1789 RETURN_NONE();
1793 static PyObject*
1794 DB_set_flags(DBObject* self, PyObject* args)
1796 int err, flags;
1798 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
1799 return NULL;
1800 CHECK_DB_NOT_CLOSED(self);
1802 MYDB_BEGIN_ALLOW_THREADS;
1803 err = self->db->set_flags(self->db, flags);
1804 MYDB_END_ALLOW_THREADS;
1805 RETURN_IF_ERR();
1807 self->setflags |= flags;
1808 RETURN_NONE();
1812 static PyObject*
1813 DB_set_h_ffactor(DBObject* self, PyObject* args)
1815 int err, ffactor;
1817 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
1818 return NULL;
1819 CHECK_DB_NOT_CLOSED(self);
1821 MYDB_BEGIN_ALLOW_THREADS;
1822 err = self->db->set_h_ffactor(self->db, ffactor);
1823 MYDB_END_ALLOW_THREADS;
1824 RETURN_IF_ERR();
1825 RETURN_NONE();
1829 static PyObject*
1830 DB_set_h_nelem(DBObject* self, PyObject* args)
1832 int err, nelem;
1834 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
1835 return NULL;
1836 CHECK_DB_NOT_CLOSED(self);
1838 MYDB_BEGIN_ALLOW_THREADS;
1839 err = self->db->set_h_nelem(self->db, nelem);
1840 MYDB_END_ALLOW_THREADS;
1841 RETURN_IF_ERR();
1842 RETURN_NONE();
1846 static PyObject*
1847 DB_set_lorder(DBObject* self, PyObject* args)
1849 int err, lorder;
1851 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
1852 return NULL;
1853 CHECK_DB_NOT_CLOSED(self);
1855 MYDB_BEGIN_ALLOW_THREADS;
1856 err = self->db->set_lorder(self->db, lorder);
1857 MYDB_END_ALLOW_THREADS;
1858 RETURN_IF_ERR();
1859 RETURN_NONE();
1863 static PyObject*
1864 DB_set_pagesize(DBObject* self, PyObject* args)
1866 int err, pagesize;
1868 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
1869 return NULL;
1870 CHECK_DB_NOT_CLOSED(self);
1872 MYDB_BEGIN_ALLOW_THREADS;
1873 err = self->db->set_pagesize(self->db, pagesize);
1874 MYDB_END_ALLOW_THREADS;
1875 RETURN_IF_ERR();
1876 RETURN_NONE();
1880 static PyObject*
1881 DB_set_re_delim(DBObject* self, PyObject* args)
1883 int err;
1884 char delim;
1886 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
1887 PyErr_Clear();
1888 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
1889 return NULL;
1892 CHECK_DB_NOT_CLOSED(self);
1894 MYDB_BEGIN_ALLOW_THREADS;
1895 err = self->db->set_re_delim(self->db, delim);
1896 MYDB_END_ALLOW_THREADS;
1897 RETURN_IF_ERR();
1898 RETURN_NONE();
1901 static PyObject*
1902 DB_set_re_len(DBObject* self, PyObject* args)
1904 int err, len;
1906 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
1907 return NULL;
1908 CHECK_DB_NOT_CLOSED(self);
1910 MYDB_BEGIN_ALLOW_THREADS;
1911 err = self->db->set_re_len(self->db, len);
1912 MYDB_END_ALLOW_THREADS;
1913 RETURN_IF_ERR();
1914 RETURN_NONE();
1918 static PyObject*
1919 DB_set_re_pad(DBObject* self, PyObject* args)
1921 int err;
1922 char pad;
1924 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
1925 PyErr_Clear();
1926 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
1927 return NULL;
1929 CHECK_DB_NOT_CLOSED(self);
1931 MYDB_BEGIN_ALLOW_THREADS;
1932 err = self->db->set_re_pad(self->db, pad);
1933 MYDB_END_ALLOW_THREADS;
1934 RETURN_IF_ERR();
1935 RETURN_NONE();
1939 static PyObject*
1940 DB_set_re_source(DBObject* self, PyObject* args)
1942 int err;
1943 char *re_source;
1945 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
1946 return NULL;
1947 CHECK_DB_NOT_CLOSED(self);
1949 MYDB_BEGIN_ALLOW_THREADS;
1950 err = self->db->set_re_source(self->db, re_source);
1951 MYDB_END_ALLOW_THREADS;
1952 RETURN_IF_ERR();
1953 RETURN_NONE();
1957 #if (DBVER >= 32)
1958 static PyObject*
1959 DB_set_q_extentsize(DBObject* self, PyObject* args)
1961 int err;
1962 int extentsize;
1964 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
1965 return NULL;
1966 CHECK_DB_NOT_CLOSED(self);
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->set_q_extentsize(self->db, extentsize);
1970 MYDB_END_ALLOW_THREADS;
1971 RETURN_IF_ERR();
1972 RETURN_NONE();
1974 #endif
1976 static PyObject*
1977 DB_stat(DBObject* self, PyObject* args)
1979 int err, flags = 0, type;
1980 void* sp;
1981 PyObject* d;
1984 if (!PyArg_ParseTuple(args, "|i:stat", &flags))
1985 return NULL;
1986 CHECK_DB_NOT_CLOSED(self);
1988 MYDB_BEGIN_ALLOW_THREADS;
1989 #if (DBVER >= 33)
1990 err = self->db->stat(self->db, &sp, flags);
1991 #else
1992 err = self->db->stat(self->db, &sp, NULL, flags);
1993 #endif
1994 MYDB_END_ALLOW_THREADS;
1995 RETURN_IF_ERR();
1997 self->haveStat = 1;
1999 /* Turn the stat structure into a dictionary */
2000 type = _DB_get_type(self);
2001 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2002 free(sp);
2003 return NULL;
2006 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2007 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2008 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2010 switch (type) {
2011 case DB_HASH:
2012 MAKE_HASH_ENTRY(magic);
2013 MAKE_HASH_ENTRY(version);
2014 MAKE_HASH_ENTRY(nkeys);
2015 MAKE_HASH_ENTRY(ndata);
2016 MAKE_HASH_ENTRY(pagesize);
2017 #if (DBVER < 41)
2018 MAKE_HASH_ENTRY(nelem);
2019 #endif
2020 MAKE_HASH_ENTRY(ffactor);
2021 MAKE_HASH_ENTRY(buckets);
2022 MAKE_HASH_ENTRY(free);
2023 MAKE_HASH_ENTRY(bfree);
2024 MAKE_HASH_ENTRY(bigpages);
2025 MAKE_HASH_ENTRY(big_bfree);
2026 MAKE_HASH_ENTRY(overflows);
2027 MAKE_HASH_ENTRY(ovfl_free);
2028 MAKE_HASH_ENTRY(dup);
2029 MAKE_HASH_ENTRY(dup_free);
2030 break;
2032 case DB_BTREE:
2033 case DB_RECNO:
2034 MAKE_BT_ENTRY(magic);
2035 MAKE_BT_ENTRY(version);
2036 MAKE_BT_ENTRY(nkeys);
2037 MAKE_BT_ENTRY(ndata);
2038 MAKE_BT_ENTRY(pagesize);
2039 MAKE_BT_ENTRY(minkey);
2040 MAKE_BT_ENTRY(re_len);
2041 MAKE_BT_ENTRY(re_pad);
2042 MAKE_BT_ENTRY(levels);
2043 MAKE_BT_ENTRY(int_pg);
2044 MAKE_BT_ENTRY(leaf_pg);
2045 MAKE_BT_ENTRY(dup_pg);
2046 MAKE_BT_ENTRY(over_pg);
2047 MAKE_BT_ENTRY(free);
2048 MAKE_BT_ENTRY(int_pgfree);
2049 MAKE_BT_ENTRY(leaf_pgfree);
2050 MAKE_BT_ENTRY(dup_pgfree);
2051 MAKE_BT_ENTRY(over_pgfree);
2052 break;
2054 case DB_QUEUE:
2055 MAKE_QUEUE_ENTRY(magic);
2056 MAKE_QUEUE_ENTRY(version);
2057 MAKE_QUEUE_ENTRY(nkeys);
2058 MAKE_QUEUE_ENTRY(ndata);
2059 MAKE_QUEUE_ENTRY(pagesize);
2060 MAKE_QUEUE_ENTRY(pages);
2061 MAKE_QUEUE_ENTRY(re_len);
2062 MAKE_QUEUE_ENTRY(re_pad);
2063 MAKE_QUEUE_ENTRY(pgfree);
2064 #if (DBVER == 31)
2065 MAKE_QUEUE_ENTRY(start);
2066 #endif
2067 MAKE_QUEUE_ENTRY(first_recno);
2068 MAKE_QUEUE_ENTRY(cur_recno);
2069 break;
2071 default:
2072 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2073 Py_DECREF(d);
2074 d = NULL;
2077 #undef MAKE_HASH_ENTRY
2078 #undef MAKE_BT_ENTRY
2079 #undef MAKE_QUEUE_ENTRY
2081 free(sp);
2082 return d;
2085 static PyObject*
2086 DB_sync(DBObject* self, PyObject* args)
2088 int err;
2089 int flags = 0;
2091 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2092 return NULL;
2093 CHECK_DB_NOT_CLOSED(self);
2095 MYDB_BEGIN_ALLOW_THREADS;
2096 err = self->db->sync(self->db, flags);
2097 MYDB_END_ALLOW_THREADS;
2098 RETURN_IF_ERR();
2099 RETURN_NONE();
2103 #if (DBVER >= 33)
2104 static PyObject*
2105 DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2107 int err, flags=0;
2108 u_int32_t count=0;
2109 PyObject* txnobj = NULL;
2110 DB_TXN *txn = NULL;
2111 char* kwnames[] = { "txn", "flags", NULL };
2113 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2114 &txnobj, &flags))
2115 return NULL;
2116 CHECK_DB_NOT_CLOSED(self);
2117 if (!checkTxnObj(txnobj, &txn))
2118 return NULL;
2120 MYDB_BEGIN_ALLOW_THREADS;
2121 err = self->db->truncate(self->db, txn, &count, flags);
2122 MYDB_END_ALLOW_THREADS;
2123 RETURN_IF_ERR();
2124 return PyInt_FromLong(count);
2126 #endif
2129 static PyObject*
2130 DB_upgrade(DBObject* self, PyObject* args)
2132 int err, flags=0;
2133 char *filename;
2135 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2136 return NULL;
2137 CHECK_DB_NOT_CLOSED(self);
2139 MYDB_BEGIN_ALLOW_THREADS;
2140 err = self->db->upgrade(self->db, filename, flags);
2141 MYDB_END_ALLOW_THREADS;
2142 RETURN_IF_ERR();
2143 RETURN_NONE();
2147 static PyObject*
2148 DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2150 int err, flags=0;
2151 char* fileName;
2152 char* dbName=NULL;
2153 char* outFileName=NULL;
2154 FILE* outFile=NULL;
2155 char* kwnames[] = { "filename", "dbname", "outfile", "flags", NULL };
2157 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2158 &fileName, &dbName, &outFileName, &flags))
2159 return NULL;
2161 CHECK_DB_NOT_CLOSED(self);
2162 if (outFileName)
2163 outFile = fopen(outFileName, "w");
2165 MYDB_BEGIN_ALLOW_THREADS;
2166 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2167 MYDB_END_ALLOW_THREADS;
2168 if (outFileName)
2169 fclose(outFile);
2171 /* DB.verify acts as a DB handle destructor (like close); this was
2172 * documented in BerkeleyDB 4.2 but had the undocumented effect
2173 * of not being safe in prior versions while still requiring an explicit
2174 * DB.close call afterwards. Lets call close for the user to emulate
2175 * the safe 4.2 behaviour. */
2176 #if (DBVER <= 41)
2177 self->db->close(self->db, 0);
2178 #endif
2179 self->db = NULL;
2181 RETURN_IF_ERR();
2182 RETURN_NONE();
2186 static PyObject*
2187 DB_set_get_returns_none(DBObject* self, PyObject* args)
2189 int flags=0;
2190 int oldValue=0;
2192 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2193 return NULL;
2194 CHECK_DB_NOT_CLOSED(self);
2196 if (self->moduleFlags.getReturnsNone)
2197 ++oldValue;
2198 if (self->moduleFlags.cursorSetReturnsNone)
2199 ++oldValue;
2200 self->moduleFlags.getReturnsNone = (flags >= 1);
2201 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
2202 return PyInt_FromLong(oldValue);
2205 #if (DBVER >= 41)
2206 static PyObject*
2207 DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2209 int err;
2210 u_int32_t flags=0;
2211 char *passwd = NULL;
2212 char* kwnames[] = { "passwd", "flags", NULL };
2214 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2215 &passwd, &flags)) {
2216 return NULL;
2219 MYDB_BEGIN_ALLOW_THREADS;
2220 err = self->db->set_encrypt(self->db, passwd, flags);
2221 MYDB_END_ALLOW_THREADS;
2223 RETURN_IF_ERR();
2224 RETURN_NONE();
2226 #endif /* DBVER >= 41 */
2229 /*-------------------------------------------------------------- */
2230 /* Mapping and Dictionary-like access routines */
2232 int DB_length(DBObject* self)
2234 int err;
2235 long size = 0;
2236 int flags = 0;
2237 void* sp;
2239 if (self->db == NULL) {
2240 PyErr_SetObject(DBError,
2241 Py_BuildValue("(is)", 0, "DB object has been closed"));
2242 return -1;
2245 if (self->haveStat) { /* Has the stat function been called recently? If
2246 so, we can use the cached value. */
2247 flags = DB_CACHED_COUNTS;
2250 MYDB_BEGIN_ALLOW_THREADS;
2251 #if (DBVER >= 33)
2252 err = self->db->stat(self->db, &sp, flags);
2253 #else
2254 err = self->db->stat(self->db, &sp, NULL, flags);
2255 #endif
2256 MYDB_END_ALLOW_THREADS;
2258 if (err)
2259 return -1;
2261 self->haveStat = 1;
2263 /* All the stat structures have matching fields upto the ndata field,
2264 so we can use any of them for the type cast */
2265 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2266 free(sp);
2267 return size;
2271 PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2273 int err;
2274 PyObject* retval;
2275 DBT key;
2276 DBT data;
2278 CHECK_DB_NOT_CLOSED(self);
2279 if (!make_key_dbt(self, keyobj, &key, NULL))
2280 return NULL;
2282 CLEAR_DBT(data);
2283 if (CHECK_DBFLAG(self, DB_THREAD)) {
2284 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2285 data.flags = DB_DBT_MALLOC;
2287 MYDB_BEGIN_ALLOW_THREADS;
2288 err = self->db->get(self->db, NULL, &key, &data, 0);
2289 MYDB_END_ALLOW_THREADS;
2290 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2291 PyErr_SetObject(PyExc_KeyError, keyobj);
2292 retval = NULL;
2294 else if (makeDBError(err)) {
2295 retval = NULL;
2297 else {
2298 retval = PyString_FromStringAndSize((char*)data.data, data.size);
2299 FREE_DBT(data);
2302 FREE_DBT(key);
2303 return retval;
2307 static int
2308 DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2310 DBT key, data;
2311 int retval;
2312 int flags = 0;
2314 if (self->db == NULL) {
2315 PyErr_SetObject(DBError,
2316 Py_BuildValue("(is)", 0, "DB object has been closed"));
2317 return -1;
2320 if (!make_key_dbt(self, keyobj, &key, NULL))
2321 return -1;
2323 if (dataobj != NULL) {
2324 if (!make_dbt(dataobj, &data))
2325 retval = -1;
2326 else {
2327 if (self->setflags & (DB_DUP|DB_DUPSORT))
2328 /* dictionaries shouldn't have duplicate keys */
2329 flags = DB_NOOVERWRITE;
2330 retval = _DB_put(self, NULL, &key, &data, flags);
2332 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
2333 /* try deleting any old record that matches and then PUT it
2334 * again... */
2335 _DB_delete(self, NULL, &key, 0);
2336 PyErr_Clear();
2337 retval = _DB_put(self, NULL, &key, &data, flags);
2341 else {
2342 /* dataobj == NULL, so delete the key */
2343 retval = _DB_delete(self, NULL, &key, 0);
2345 FREE_DBT(key);
2346 return retval;
2350 static PyObject*
2351 DB_has_key(DBObject* self, PyObject* args)
2353 int err;
2354 PyObject* keyobj;
2355 DBT key, data;
2356 PyObject* txnobj = NULL;
2357 DB_TXN *txn = NULL;
2359 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
2360 return NULL;
2361 CHECK_DB_NOT_CLOSED(self);
2362 if (!make_key_dbt(self, keyobj, &key, NULL))
2363 return NULL;
2364 if (!checkTxnObj(txnobj, &txn))
2365 return NULL;
2367 /* This causes ENOMEM to be returned when the db has the key because
2368 it has a record but can't allocate a buffer for the data. This saves
2369 having to deal with data we won't be using.
2371 CLEAR_DBT(data);
2372 data.flags = DB_DBT_USERMEM;
2374 MYDB_BEGIN_ALLOW_THREADS;
2375 err = self->db->get(self->db, txn, &key, &data, 0);
2376 MYDB_END_ALLOW_THREADS;
2377 FREE_DBT(key);
2378 return PyInt_FromLong((err == ENOMEM) || (err == 0));
2382 #define _KEYS_LIST 1
2383 #define _VALUES_LIST 2
2384 #define _ITEMS_LIST 3
2386 static PyObject*
2387 _DB_make_list(DBObject* self, DB_TXN* txn, int type)
2389 int err, dbtype;
2390 DBT key;
2391 DBT data;
2392 DBC *cursor;
2393 PyObject* list;
2394 PyObject* item = NULL;
2396 CHECK_DB_NOT_CLOSED(self);
2397 CLEAR_DBT(key);
2398 CLEAR_DBT(data);
2400 dbtype = _DB_get_type(self);
2401 if (dbtype == -1)
2402 return NULL;
2404 list = PyList_New(0);
2405 if (list == NULL) {
2406 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
2407 return NULL;
2410 /* get a cursor */
2411 MYDB_BEGIN_ALLOW_THREADS;
2412 err = self->db->cursor(self->db, NULL, &cursor, 0);
2413 MYDB_END_ALLOW_THREADS;
2414 RETURN_IF_ERR();
2416 if (CHECK_DBFLAG(self, DB_THREAD)) {
2417 key.flags = DB_DBT_REALLOC;
2418 data.flags = DB_DBT_REALLOC;
2421 while (1) { /* use the cursor to traverse the DB, collecting items */
2422 MYDB_BEGIN_ALLOW_THREADS;
2423 err = cursor->c_get(cursor, &key, &data, DB_NEXT);
2424 MYDB_END_ALLOW_THREADS;
2426 if (err) {
2427 /* for any error, break out of the loop */
2428 break;
2431 switch (type) {
2432 case _KEYS_LIST:
2433 switch(dbtype) {
2434 case DB_BTREE:
2435 case DB_HASH:
2436 default:
2437 item = PyString_FromStringAndSize((char*)key.data, key.size);
2438 break;
2439 case DB_RECNO:
2440 case DB_QUEUE:
2441 item = PyInt_FromLong(*((db_recno_t*)key.data));
2442 break;
2444 break;
2446 case _VALUES_LIST:
2447 item = PyString_FromStringAndSize((char*)data.data, data.size);
2448 break;
2450 case _ITEMS_LIST:
2451 switch(dbtype) {
2452 case DB_BTREE:
2453 case DB_HASH:
2454 default:
2455 item = Py_BuildValue("s#s#", key.data, key.size, data.data,
2456 data.size);
2457 break;
2458 case DB_RECNO:
2459 case DB_QUEUE:
2460 item = Py_BuildValue("is#", *((db_recno_t*)key.data),
2461 data.data, data.size);
2462 break;
2464 break;
2466 if (item == NULL) {
2467 Py_DECREF(list);
2468 PyErr_SetString(PyExc_MemoryError, "List item creation failed");
2469 list = NULL;
2470 goto done;
2472 PyList_Append(list, item);
2473 Py_DECREF(item);
2476 /* DB_NOTFOUND is okay, it just means we got to the end */
2477 if (err != DB_NOTFOUND && makeDBError(err)) {
2478 Py_DECREF(list);
2479 list = NULL;
2482 done:
2483 FREE_DBT(key);
2484 FREE_DBT(data);
2485 MYDB_BEGIN_ALLOW_THREADS;
2486 cursor->c_close(cursor);
2487 MYDB_END_ALLOW_THREADS;
2488 return list;
2492 static PyObject*
2493 DB_keys(DBObject* self, PyObject* args)
2495 PyObject* txnobj = NULL;
2496 DB_TXN *txn = NULL;
2498 if (!PyArg_ParseTuple(args,"|O:keys", &txnobj))
2499 return NULL;
2500 if (!checkTxnObj(txnobj, &txn))
2501 return NULL;
2502 return _DB_make_list(self, txn, _KEYS_LIST);
2506 static PyObject*
2507 DB_items(DBObject* self, PyObject* args)
2509 PyObject* txnobj = NULL;
2510 DB_TXN *txn = NULL;
2512 if (!PyArg_ParseTuple(args,"|O:items", &txnobj))
2513 return NULL;
2514 if (!checkTxnObj(txnobj, &txn))
2515 return NULL;
2516 return _DB_make_list(self, txn, _ITEMS_LIST);
2520 static PyObject*
2521 DB_values(DBObject* self, PyObject* args)
2523 PyObject* txnobj = NULL;
2524 DB_TXN *txn = NULL;
2526 if (!PyArg_ParseTuple(args,"|O:values", &txnobj))
2527 return NULL;
2528 if (!checkTxnObj(txnobj, &txn))
2529 return NULL;
2530 return _DB_make_list(self, txn, _VALUES_LIST);
2533 /* --------------------------------------------------------------------- */
2534 /* DBCursor methods */
2537 static PyObject*
2538 DBC_close(DBCursorObject* self, PyObject* args)
2540 int err = 0;
2542 if (!PyArg_ParseTuple(args, ":close"))
2543 return NULL;
2545 if (self->dbc != NULL) {
2546 MYDB_BEGIN_ALLOW_THREADS;
2547 err = self->dbc->c_close(self->dbc);
2548 self->dbc = NULL;
2549 MYDB_END_ALLOW_THREADS;
2551 RETURN_IF_ERR();
2552 RETURN_NONE();
2556 static PyObject*
2557 DBC_count(DBCursorObject* self, PyObject* args)
2559 int err = 0;
2560 db_recno_t count;
2561 int flags = 0;
2563 if (!PyArg_ParseTuple(args, "|i:count", &flags))
2564 return NULL;
2566 CHECK_CURSOR_NOT_CLOSED(self);
2568 MYDB_BEGIN_ALLOW_THREADS;
2569 err = self->dbc->c_count(self->dbc, &count, flags);
2570 MYDB_END_ALLOW_THREADS;
2571 RETURN_IF_ERR();
2573 return PyInt_FromLong(count);
2577 static PyObject*
2578 DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2580 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
2584 static PyObject*
2585 DBC_delete(DBCursorObject* self, PyObject* args)
2587 int err, flags=0;
2589 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
2590 return NULL;
2592 CHECK_CURSOR_NOT_CLOSED(self);
2594 MYDB_BEGIN_ALLOW_THREADS;
2595 err = self->dbc->c_del(self->dbc, flags);
2596 MYDB_END_ALLOW_THREADS;
2597 RETURN_IF_ERR();
2599 self->mydb->haveStat = 0;
2600 RETURN_NONE();
2604 static PyObject*
2605 DBC_dup(DBCursorObject* self, PyObject* args)
2607 int err, flags =0;
2608 DBC* dbc = NULL;
2610 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
2611 return NULL;
2613 CHECK_CURSOR_NOT_CLOSED(self);
2615 MYDB_BEGIN_ALLOW_THREADS;
2616 err = self->dbc->c_dup(self->dbc, &dbc, flags);
2617 MYDB_END_ALLOW_THREADS;
2618 RETURN_IF_ERR();
2620 return (PyObject*) newDBCursorObject(dbc, self->mydb);
2623 static PyObject*
2624 DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2626 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
2630 static PyObject*
2631 DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2633 int err, flags=0;
2634 PyObject* keyobj = NULL;
2635 PyObject* dataobj = NULL;
2636 PyObject* retval = NULL;
2637 int dlen = -1;
2638 int doff = -1;
2639 DBT key, data;
2640 char* kwnames[] = { "key","data", "flags", "dlen", "doff", NULL };
2642 CLEAR_DBT(key);
2643 CLEAR_DBT(data);
2644 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
2645 &flags, &dlen, &doff))
2647 PyErr_Clear();
2648 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
2649 &kwnames[1],
2650 &keyobj, &flags, &dlen, &doff))
2652 PyErr_Clear();
2653 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
2654 kwnames, &keyobj, &dataobj,
2655 &flags, &dlen, &doff))
2657 return NULL;
2662 CHECK_CURSOR_NOT_CLOSED(self);
2664 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
2665 return NULL;
2666 if (dataobj && !make_dbt(dataobj, &data))
2667 return NULL;
2668 if (!add_partial_dbt(&data, dlen, doff))
2669 return NULL;
2671 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2672 data.flags = DB_DBT_MALLOC;
2673 key.flags = DB_DBT_MALLOC;
2676 MYDB_BEGIN_ALLOW_THREADS;
2677 err = self->dbc->c_get(self->dbc, &key, &data, flags);
2678 MYDB_END_ALLOW_THREADS;
2681 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
2682 Py_INCREF(Py_None);
2683 retval = Py_None;
2685 else if (makeDBError(err)) {
2686 retval = NULL;
2688 else {
2689 switch (_DB_get_type(self->mydb)) {
2690 case -1:
2691 retval = NULL;
2692 break;
2693 case DB_BTREE:
2694 case DB_HASH:
2695 default:
2696 retval = Py_BuildValue("s#s#", key.data, key.size,
2697 data.data, data.size);
2698 break;
2699 case DB_RECNO:
2700 case DB_QUEUE:
2701 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2702 data.data, data.size);
2703 break;
2705 FREE_DBT(key);
2706 FREE_DBT(data);
2708 return retval;
2712 static PyObject*
2713 DBC_get_recno(DBCursorObject* self, PyObject* args)
2715 int err;
2716 db_recno_t recno;
2717 DBT key;
2718 DBT data;
2720 if (!PyArg_ParseTuple(args, ":get_recno"))
2721 return NULL;
2723 CHECK_CURSOR_NOT_CLOSED(self);
2725 CLEAR_DBT(key);
2726 CLEAR_DBT(data);
2727 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2728 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2729 data.flags = DB_DBT_MALLOC;
2730 key.flags = DB_DBT_MALLOC;
2733 MYDB_BEGIN_ALLOW_THREADS;
2734 err = self->dbc->c_get(self->dbc, &key, &data, DB_GET_RECNO);
2735 MYDB_END_ALLOW_THREADS;
2736 RETURN_IF_ERR();
2738 recno = *((db_recno_t*)data.data);
2739 FREE_DBT(key);
2740 FREE_DBT(data);
2741 return PyInt_FromLong(recno);
2745 static PyObject*
2746 DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2748 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
2752 static PyObject*
2753 DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2755 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
2759 static PyObject*
2760 DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2762 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
2766 static PyObject*
2767 DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2769 int err, flags = 0;
2770 PyObject* keyobj, *dataobj;
2771 DBT key, data;
2772 char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
2773 int dlen = -1;
2774 int doff = -1;
2776 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
2777 &keyobj, &dataobj, &flags, &dlen, &doff))
2778 return NULL;
2780 CHECK_CURSOR_NOT_CLOSED(self);
2782 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2783 return NULL;
2784 if (!make_dbt(dataobj, &data))
2785 return NULL;
2786 if (!add_partial_dbt(&data, dlen, doff)) return NULL;
2788 MYDB_BEGIN_ALLOW_THREADS;
2789 err = self->dbc->c_put(self->dbc, &key, &data, flags);
2790 MYDB_END_ALLOW_THREADS;
2791 FREE_DBT(key);
2792 RETURN_IF_ERR();
2793 self->mydb->haveStat = 0;
2794 RETURN_NONE();
2798 static PyObject*
2799 DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
2801 int err, flags = 0;
2802 DBT key, data;
2803 PyObject* retval, *keyobj;
2804 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2805 int dlen = -1;
2806 int doff = -1;
2808 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
2809 &keyobj, &flags, &dlen, &doff))
2810 return NULL;
2812 CHECK_CURSOR_NOT_CLOSED(self);
2814 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2815 return NULL;
2817 CLEAR_DBT(data);
2818 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2819 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2820 data.flags = DB_DBT_MALLOC;
2822 if (!add_partial_dbt(&data, dlen, doff))
2823 return NULL;
2825 MYDB_BEGIN_ALLOW_THREADS;
2826 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET);
2827 MYDB_END_ALLOW_THREADS;
2828 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2829 Py_INCREF(Py_None);
2830 retval = Py_None;
2832 else if (makeDBError(err)) {
2833 retval = NULL;
2835 else {
2836 switch (_DB_get_type(self->mydb)) {
2837 case -1:
2838 retval = NULL;
2839 break;
2840 case DB_BTREE:
2841 case DB_HASH:
2842 default:
2843 retval = Py_BuildValue("s#s#", key.data, key.size,
2844 data.data, data.size);
2845 break;
2846 case DB_RECNO:
2847 case DB_QUEUE:
2848 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2849 data.data, data.size);
2850 break;
2852 if (_DB_get_type(self->mydb) == DB_BTREE) {
2853 /* the only time a malloced key is returned is when we
2854 * call this on a BTree database because it performs
2855 * partial matching and needs to return the real key.
2856 * All others leave key untouched [where calling free()
2857 * on it would often segfault].
2859 FREE_DBT(key);
2861 FREE_DBT(data);
2864 return retval;
2868 static PyObject*
2869 DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
2871 int err, flags = 0;
2872 DBT key, data;
2873 PyObject* retval, *keyobj;
2874 char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
2875 int dlen = -1;
2876 int doff = -1;
2878 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
2879 &keyobj, &flags, &dlen, &doff))
2880 return NULL;
2882 CHECK_CURSOR_NOT_CLOSED(self);
2884 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2885 return NULL;
2887 CLEAR_DBT(data);
2888 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
2889 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2890 data.flags = DB_DBT_MALLOC;
2891 key.flags = DB_DBT_MALLOC;
2893 if (!add_partial_dbt(&data, dlen, doff))
2894 return NULL;
2895 MYDB_BEGIN_ALLOW_THREADS;
2896 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
2897 MYDB_END_ALLOW_THREADS;
2898 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
2899 Py_INCREF(Py_None);
2900 retval = Py_None;
2902 else if (makeDBError(err)) {
2903 retval = NULL;
2905 else {
2906 switch (_DB_get_type(self->mydb)) {
2907 case -1:
2908 retval = NULL;
2909 break;
2910 case DB_BTREE:
2911 case DB_HASH:
2912 default:
2913 retval = Py_BuildValue("s#s#", key.data, key.size,
2914 data.data, data.size);
2915 break;
2916 case DB_RECNO:
2917 case DB_QUEUE:
2918 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2919 data.data, data.size);
2920 break;
2922 if (_DB_get_type(self->mydb) == DB_BTREE) {
2923 /* the only time a malloced key is returned is when we
2924 * call this on a BTree database because it performs
2925 * partial matching and needs to return the real key.
2926 * All others leave key untouched [where calling free()
2927 * on it would often segfault].
2929 FREE_DBT(key);
2931 FREE_DBT(data);
2934 return retval;
2937 static PyObject*
2938 _DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
2939 int flags, unsigned int returnsNone)
2941 int err;
2942 DBT key, data;
2943 PyObject* retval;
2945 // the caller did this: CHECK_CURSOR_NOT_CLOSED(self);
2946 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
2947 return NULL;
2948 if (!make_dbt(dataobj, &data))
2949 return NULL;
2951 MYDB_BEGIN_ALLOW_THREADS;
2952 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
2953 MYDB_END_ALLOW_THREADS;
2954 if ((err == DB_NOTFOUND) && returnsNone) {
2955 Py_INCREF(Py_None);
2956 retval = Py_None;
2958 else if (makeDBError(err)) {
2959 retval = NULL;
2961 else {
2962 switch (_DB_get_type(self->mydb)) {
2963 case -1:
2964 retval = NULL;
2965 break;
2966 case DB_BTREE:
2967 case DB_HASH:
2968 default:
2969 retval = Py_BuildValue("s#s#", key.data, key.size,
2970 data.data, data.size);
2971 break;
2972 case DB_RECNO:
2973 case DB_QUEUE:
2974 retval = Py_BuildValue("is#", *((db_recno_t*)key.data),
2975 data.data, data.size);
2976 break;
2980 FREE_DBT(key);
2981 return retval;
2984 static PyObject*
2985 DBC_get_both(DBCursorObject* self, PyObject* args)
2987 int flags=0;
2988 PyObject *keyobj, *dataobj;
2990 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
2991 return NULL;
2993 // if the cursor is closed, self->mydb may be invalid
2994 CHECK_CURSOR_NOT_CLOSED(self);
2996 return _DBC_get_set_both(self, keyobj, dataobj, flags,
2997 self->mydb->moduleFlags.getReturnsNone);
3000 static PyObject*
3001 DBC_set_both(DBCursorObject* self, PyObject* args)
3003 int flags=0;
3004 PyObject *keyobj, *dataobj;
3006 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3007 return NULL;
3009 // if the cursor is closed, self->mydb may be invalid
3010 CHECK_CURSOR_NOT_CLOSED(self);
3012 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3013 self->mydb->moduleFlags.cursorSetReturnsNone);
3017 static PyObject*
3018 DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3020 int err, irecno, flags=0;
3021 db_recno_t recno;
3022 DBT key, data;
3023 PyObject* retval;
3024 int dlen = -1;
3025 int doff = -1;
3026 char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
3028 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3029 &irecno, &flags, &dlen, &doff))
3030 return NULL;
3032 CHECK_CURSOR_NOT_CLOSED(self);
3034 CLEAR_DBT(key);
3035 recno = (db_recno_t) irecno;
3036 /* use allocated space so DB will be able to realloc room for the real
3037 * key */
3038 key.data = malloc(sizeof(db_recno_t));
3039 if (key.data == NULL) {
3040 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3041 return NULL;
3043 key.size = sizeof(db_recno_t);
3044 key.ulen = key.size;
3045 memcpy(key.data, &recno, sizeof(db_recno_t));
3046 key.flags = DB_DBT_REALLOC;
3048 CLEAR_DBT(data);
3049 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3050 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3051 data.flags = DB_DBT_MALLOC;
3053 if (!add_partial_dbt(&data, dlen, doff))
3054 return NULL;
3056 MYDB_BEGIN_ALLOW_THREADS;
3057 err = self->dbc->c_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
3058 MYDB_END_ALLOW_THREADS;
3059 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.cursorSetReturnsNone) {
3060 Py_INCREF(Py_None);
3061 retval = Py_None;
3063 else if (makeDBError(err)) {
3064 retval = NULL;
3066 else { /* Can only be used for BTrees, so no need to return int key */
3067 retval = Py_BuildValue("s#s#", key.data, key.size,
3068 data.data, data.size);
3069 FREE_DBT(key);
3070 FREE_DBT(data);
3073 return retval;
3077 static PyObject*
3078 DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3080 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3084 static PyObject*
3085 DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3087 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3091 static PyObject*
3092 DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3094 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3098 static PyObject*
3099 DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3101 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3105 static PyObject*
3106 DBC_join_item(DBCursorObject* self, PyObject* args)
3108 int err, flags=0;
3109 DBT key, data;
3110 PyObject* retval;
3112 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
3113 return NULL;
3115 CHECK_CURSOR_NOT_CLOSED(self);
3117 CLEAR_DBT(key);
3118 CLEAR_DBT(data);
3119 if (CHECK_DBFLAG(self->mydb, DB_THREAD)) {
3120 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3121 key.flags = DB_DBT_MALLOC;
3124 MYDB_BEGIN_ALLOW_THREADS;
3125 err = self->dbc->c_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
3126 MYDB_END_ALLOW_THREADS;
3127 if ((err == DB_NOTFOUND) && self->mydb->moduleFlags.getReturnsNone) {
3128 Py_INCREF(Py_None);
3129 retval = Py_None;
3131 else if (makeDBError(err)) {
3132 retval = NULL;
3134 else {
3135 retval = Py_BuildValue("s#", key.data, key.size);
3136 FREE_DBT(key);
3139 return retval;
3144 /* --------------------------------------------------------------------- */
3145 /* DBEnv methods */
3148 static PyObject*
3149 DBEnv_close(DBEnvObject* self, PyObject* args)
3151 int err, flags = 0;
3153 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3154 return NULL;
3155 if (!self->closed) { /* Don't close more than once */
3156 MYDB_BEGIN_ALLOW_THREADS;
3157 err = self->db_env->close(self->db_env, flags);
3158 MYDB_END_ALLOW_THREADS;
3159 /* after calling DBEnv->close, regardless of error, this DBEnv
3160 * may not be accessed again (BerkeleyDB docs). */
3161 self->closed = 1;
3162 self->db_env = NULL;
3163 RETURN_IF_ERR();
3165 RETURN_NONE();
3169 static PyObject*
3170 DBEnv_open(DBEnvObject* self, PyObject* args)
3172 int err, flags=0, mode=0660;
3173 char *db_home;
3175 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3176 return NULL;
3178 CHECK_ENV_NOT_CLOSED(self);
3180 MYDB_BEGIN_ALLOW_THREADS;
3181 err = self->db_env->open(self->db_env, db_home, flags, mode);
3182 MYDB_END_ALLOW_THREADS;
3183 RETURN_IF_ERR();
3184 self->closed = 0;
3185 self->flags = flags;
3186 RETURN_NONE();
3190 static PyObject*
3191 DBEnv_remove(DBEnvObject* self, PyObject* args)
3193 int err, flags=0;
3194 char *db_home;
3196 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3197 return NULL;
3198 CHECK_ENV_NOT_CLOSED(self);
3199 MYDB_BEGIN_ALLOW_THREADS;
3200 err = self->db_env->remove(self->db_env, db_home, flags);
3201 MYDB_END_ALLOW_THREADS;
3202 RETURN_IF_ERR();
3203 RETURN_NONE();
3206 #if (DBVER >= 41)
3207 static PyObject*
3208 DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3210 int err;
3211 u_int32_t flags=0;
3212 char *file = NULL;
3213 char *database = NULL;
3214 PyObject *txnobj = NULL;
3215 DB_TXN *txn = NULL;
3216 char* kwnames[] = { "file", "database", "txn", "flags", NULL };
3218 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ss|Oi:dbremove", kwnames,
3219 &file, &database, &txnobj, &flags)) {
3220 return NULL;
3222 if (!checkTxnObj(txnobj, &txn)) {
3223 return NULL;
3225 CHECK_ENV_NOT_CLOSED(self);
3226 MYDB_BEGIN_ALLOW_THREADS;
3227 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
3228 MYDB_END_ALLOW_THREADS;
3229 RETURN_IF_ERR();
3230 RETURN_NONE();
3233 static PyObject*
3234 DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3236 int err;
3237 u_int32_t flags=0;
3238 char *file = NULL;
3239 char *database = NULL;
3240 char *newname = NULL;
3241 PyObject *txnobj = NULL;
3242 DB_TXN *txn = NULL;
3243 char* kwnames[] = { "file", "database", "newname", "txn", "flags", NULL };
3245 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sss|Oi:dbrename", kwnames,
3246 &file, &database, &newname, &txnobj, &flags)) {
3247 return NULL;
3249 if (!checkTxnObj(txnobj, &txn)) {
3250 return NULL;
3252 CHECK_ENV_NOT_CLOSED(self);
3253 MYDB_BEGIN_ALLOW_THREADS;
3254 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
3255 flags);
3256 MYDB_END_ALLOW_THREADS;
3257 RETURN_IF_ERR();
3258 RETURN_NONE();
3261 static PyObject*
3262 DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3264 int err;
3265 u_int32_t flags=0;
3266 char *passwd = NULL;
3267 char* kwnames[] = { "passwd", "flags", NULL };
3269 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
3270 &passwd, &flags)) {
3271 return NULL;
3274 MYDB_BEGIN_ALLOW_THREADS;
3275 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
3276 MYDB_END_ALLOW_THREADS;
3278 RETURN_IF_ERR();
3279 RETURN_NONE();
3281 #endif /* DBVER >= 41 */
3283 #if (DBVER >= 40)
3284 static PyObject*
3285 DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3287 int err;
3288 u_int32_t flags=0;
3289 u_int32_t timeout = 0;
3290 char* kwnames[] = { "timeout", "flags", NULL };
3292 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
3293 &timeout, &flags)) {
3294 return NULL;
3297 MYDB_BEGIN_ALLOW_THREADS;
3298 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
3299 MYDB_END_ALLOW_THREADS;
3301 RETURN_IF_ERR();
3302 RETURN_NONE();
3304 #endif /* DBVER >= 40 */
3306 static PyObject*
3307 DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
3309 int err;
3310 long shm_key = 0;
3312 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
3313 return NULL;
3314 CHECK_ENV_NOT_CLOSED(self);
3316 err = self->db_env->set_shm_key(self->db_env, shm_key);
3317 RETURN_IF_ERR();
3318 RETURN_NONE();
3321 static PyObject*
3322 DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
3324 int err, gbytes=0, bytes=0, ncache=0;
3326 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
3327 &gbytes, &bytes, &ncache))
3328 return NULL;
3329 CHECK_ENV_NOT_CLOSED(self);
3331 MYDB_BEGIN_ALLOW_THREADS;
3332 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
3333 MYDB_END_ALLOW_THREADS;
3334 RETURN_IF_ERR();
3335 RETURN_NONE();
3339 #if (DBVER >= 32)
3340 static PyObject*
3341 DBEnv_set_flags(DBEnvObject* self, PyObject* args)
3343 int err, flags=0, onoff=0;
3345 if (!PyArg_ParseTuple(args, "ii:set_flags",
3346 &flags, &onoff))
3347 return NULL;
3348 CHECK_ENV_NOT_CLOSED(self);
3350 MYDB_BEGIN_ALLOW_THREADS;
3351 err = self->db_env->set_flags(self->db_env, flags, onoff);
3352 MYDB_END_ALLOW_THREADS;
3353 RETURN_IF_ERR();
3354 RETURN_NONE();
3356 #endif
3359 static PyObject*
3360 DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
3362 int err;
3363 char *dir;
3365 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
3366 return NULL;
3367 CHECK_ENV_NOT_CLOSED(self);
3369 MYDB_BEGIN_ALLOW_THREADS;
3370 err = self->db_env->set_data_dir(self->db_env, dir);
3371 MYDB_END_ALLOW_THREADS;
3372 RETURN_IF_ERR();
3373 RETURN_NONE();
3377 static PyObject*
3378 DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
3380 int err, lg_bsize;
3382 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
3383 return NULL;
3384 CHECK_ENV_NOT_CLOSED(self);
3386 MYDB_BEGIN_ALLOW_THREADS;
3387 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
3388 MYDB_END_ALLOW_THREADS;
3389 RETURN_IF_ERR();
3390 RETURN_NONE();
3394 static PyObject*
3395 DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
3397 int err;
3398 char *dir;
3400 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
3401 return NULL;
3402 CHECK_ENV_NOT_CLOSED(self);
3404 MYDB_BEGIN_ALLOW_THREADS;
3405 err = self->db_env->set_lg_dir(self->db_env, dir);
3406 MYDB_END_ALLOW_THREADS;
3407 RETURN_IF_ERR();
3408 RETURN_NONE();
3411 static PyObject*
3412 DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
3414 int err, lg_max;
3416 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
3417 return NULL;
3418 CHECK_ENV_NOT_CLOSED(self);
3420 MYDB_BEGIN_ALLOW_THREADS;
3421 err = self->db_env->set_lg_max(self->db_env, lg_max);
3422 MYDB_END_ALLOW_THREADS;
3423 RETURN_IF_ERR();
3424 RETURN_NONE();
3428 static PyObject*
3429 DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
3431 int err, lk_detect;
3433 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
3434 return NULL;
3435 CHECK_ENV_NOT_CLOSED(self);
3437 MYDB_BEGIN_ALLOW_THREADS;
3438 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
3439 MYDB_END_ALLOW_THREADS;
3440 RETURN_IF_ERR();
3441 RETURN_NONE();
3445 static PyObject*
3446 DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
3448 int err, max;
3450 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
3451 return NULL;
3452 CHECK_ENV_NOT_CLOSED(self);
3454 MYDB_BEGIN_ALLOW_THREADS;
3455 err = self->db_env->set_lk_max(self->db_env, max);
3456 MYDB_END_ALLOW_THREADS;
3457 RETURN_IF_ERR();
3458 RETURN_NONE();
3462 #if (DBVER >= 32)
3464 static PyObject*
3465 DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
3467 int err, max;
3469 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
3470 return NULL;
3471 CHECK_ENV_NOT_CLOSED(self);
3473 MYDB_BEGIN_ALLOW_THREADS;
3474 err = self->db_env->set_lk_max_locks(self->db_env, max);
3475 MYDB_END_ALLOW_THREADS;
3476 RETURN_IF_ERR();
3477 RETURN_NONE();
3481 static PyObject*
3482 DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
3484 int err, max;
3486 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
3487 return NULL;
3488 CHECK_ENV_NOT_CLOSED(self);
3490 MYDB_BEGIN_ALLOW_THREADS;
3491 err = self->db_env->set_lk_max_lockers(self->db_env, max);
3492 MYDB_END_ALLOW_THREADS;
3493 RETURN_IF_ERR();
3494 RETURN_NONE();
3498 static PyObject*
3499 DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
3501 int err, max;
3503 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
3504 return NULL;
3505 CHECK_ENV_NOT_CLOSED(self);
3507 MYDB_BEGIN_ALLOW_THREADS;
3508 err = self->db_env->set_lk_max_objects(self->db_env, max);
3509 MYDB_END_ALLOW_THREADS;
3510 RETURN_IF_ERR();
3511 RETURN_NONE();
3514 #endif
3517 static PyObject*
3518 DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
3520 int err, mp_mmapsize;
3522 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
3523 return NULL;
3524 CHECK_ENV_NOT_CLOSED(self);
3526 MYDB_BEGIN_ALLOW_THREADS;
3527 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
3528 MYDB_END_ALLOW_THREADS;
3529 RETURN_IF_ERR();
3530 RETURN_NONE();
3534 static PyObject*
3535 DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
3537 int err;
3538 char *dir;
3540 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
3541 return NULL;
3542 CHECK_ENV_NOT_CLOSED(self);
3544 MYDB_BEGIN_ALLOW_THREADS;
3545 err = self->db_env->set_tmp_dir(self->db_env, dir);
3546 MYDB_END_ALLOW_THREADS;
3547 RETURN_IF_ERR();
3548 RETURN_NONE();
3552 static PyObject*
3553 DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3555 int flags = 0;
3556 PyObject* txnobj = NULL;
3557 DB_TXN *txn = NULL;
3558 char* kwnames[] = { "parent", "flags", NULL };
3560 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
3561 &txnobj, &flags))
3562 return NULL;
3564 if (!checkTxnObj(txnobj, &txn))
3565 return NULL;
3566 CHECK_ENV_NOT_CLOSED(self);
3568 return (PyObject*)newDBTxnObject(self, txn, flags);
3572 static PyObject*
3573 DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
3575 int err, kbyte=0, min=0, flags=0;
3577 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
3578 return NULL;
3579 CHECK_ENV_NOT_CLOSED(self);
3581 MYDB_BEGIN_ALLOW_THREADS;
3582 #if (DBVER >= 40)
3583 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
3584 #else
3585 err = txn_checkpoint(self->db_env, kbyte, min, flags);
3586 #endif
3587 MYDB_END_ALLOW_THREADS;
3588 RETURN_IF_ERR();
3589 RETURN_NONE();
3593 static PyObject*
3594 DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
3596 int err, max;
3598 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
3599 return NULL;
3600 CHECK_ENV_NOT_CLOSED(self);
3602 MYDB_BEGIN_ALLOW_THREADS;
3603 err = self->db_env->set_tx_max(self->db_env, max);
3604 MYDB_END_ALLOW_THREADS;
3605 RETURN_IF_ERR();
3606 RETURN_NONE();
3610 static PyObject*
3611 DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
3613 int err, atype, flags=0;
3614 int aborted = 0;
3616 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
3617 return NULL;
3618 CHECK_ENV_NOT_CLOSED(self);
3620 MYDB_BEGIN_ALLOW_THREADS;
3621 #if (DBVER >= 40)
3622 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
3623 #else
3624 err = lock_detect(self->db_env, flags, atype, &aborted);
3625 #endif
3626 MYDB_END_ALLOW_THREADS;
3627 RETURN_IF_ERR();
3628 return PyInt_FromLong(aborted);
3632 static PyObject*
3633 DBEnv_lock_get(DBEnvObject* self, PyObject* args)
3635 int flags=0;
3636 int locker, lock_mode;
3637 DBT obj;
3638 PyObject* objobj;
3640 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
3641 return NULL;
3644 if (!make_dbt(objobj, &obj))
3645 return NULL;
3647 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
3651 static PyObject*
3652 DBEnv_lock_id(DBEnvObject* self, PyObject* args)
3654 int err;
3655 u_int32_t theID;
3657 if (!PyArg_ParseTuple(args, ":lock_id"))
3658 return NULL;
3660 CHECK_ENV_NOT_CLOSED(self);
3661 MYDB_BEGIN_ALLOW_THREADS;
3662 #if (DBVER >= 40)
3663 err = self->db_env->lock_id(self->db_env, &theID);
3664 #else
3665 err = lock_id(self->db_env, &theID);
3666 #endif
3667 MYDB_END_ALLOW_THREADS;
3668 RETURN_IF_ERR();
3670 return PyInt_FromLong((long)theID);
3674 static PyObject*
3675 DBEnv_lock_put(DBEnvObject* self, PyObject* args)
3677 int err;
3678 DBLockObject* dblockobj;
3680 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
3681 return NULL;
3683 CHECK_ENV_NOT_CLOSED(self);
3684 MYDB_BEGIN_ALLOW_THREADS;
3685 #if (DBVER >= 40)
3686 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
3687 #else
3688 err = lock_put(self->db_env, &dblockobj->lock);
3689 #endif
3690 MYDB_END_ALLOW_THREADS;
3691 RETURN_IF_ERR();
3692 RETURN_NONE();
3696 static PyObject*
3697 DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
3699 int err;
3700 DB_LOCK_STAT* sp;
3701 PyObject* d = NULL;
3702 u_int32_t flags = 0;
3704 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
3705 return NULL;
3706 CHECK_ENV_NOT_CLOSED(self);
3708 MYDB_BEGIN_ALLOW_THREADS;
3709 #if (DBVER >= 40)
3710 err = self->db_env->lock_stat(self->db_env, &sp, flags);
3711 #else
3712 #if (DBVER >= 33)
3713 err = lock_stat(self->db_env, &sp);
3714 #else
3715 err = lock_stat(self->db_env, &sp, NULL);
3716 #endif
3717 #endif
3718 MYDB_END_ALLOW_THREADS;
3719 RETURN_IF_ERR();
3721 /* Turn the stat structure into a dictionary */
3722 d = PyDict_New();
3723 if (d == NULL) {
3724 free(sp);
3725 return NULL;
3728 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3730 #if (DBVER < 41)
3731 MAKE_ENTRY(lastid);
3732 #endif
3733 MAKE_ENTRY(nmodes);
3734 #if (DBVER >= 32)
3735 MAKE_ENTRY(maxlocks);
3736 MAKE_ENTRY(maxlockers);
3737 MAKE_ENTRY(maxobjects);
3738 MAKE_ENTRY(nlocks);
3739 MAKE_ENTRY(maxnlocks);
3740 #endif
3741 MAKE_ENTRY(nlockers);
3742 MAKE_ENTRY(maxnlockers);
3743 #if (DBVER >= 32)
3744 MAKE_ENTRY(nobjects);
3745 MAKE_ENTRY(maxnobjects);
3746 #endif
3747 MAKE_ENTRY(nrequests);
3748 MAKE_ENTRY(nreleases);
3749 MAKE_ENTRY(nnowaits);
3750 MAKE_ENTRY(nconflicts);
3751 MAKE_ENTRY(ndeadlocks);
3752 MAKE_ENTRY(regsize);
3753 MAKE_ENTRY(region_wait);
3754 MAKE_ENTRY(region_nowait);
3756 #undef MAKE_ENTRY
3757 free(sp);
3758 return d;
3762 static PyObject*
3763 DBEnv_log_archive(DBEnvObject* self, PyObject* args)
3765 int flags=0;
3766 int err;
3767 char **log_list_start, **log_list;
3768 PyObject* list;
3769 PyObject* item = NULL;
3771 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
3772 return NULL;
3774 CHECK_ENV_NOT_CLOSED(self);
3775 MYDB_BEGIN_ALLOW_THREADS;
3776 #if (DBVER >= 40)
3777 err = self->db_env->log_archive(self->db_env, &log_list, flags);
3778 #elif (DBVER == 33)
3779 err = log_archive(self->db_env, &log_list, flags);
3780 #else
3781 err = log_archive(self->db_env, &log_list, flags, NULL);
3782 #endif
3783 MYDB_END_ALLOW_THREADS;
3784 RETURN_IF_ERR();
3786 list = PyList_New(0);
3787 if (list == NULL) {
3788 PyErr_SetString(PyExc_MemoryError, "PyList_New failed");
3789 return NULL;
3792 if (log_list) {
3793 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
3794 item = PyString_FromString (*log_list);
3795 if (item == NULL) {
3796 Py_DECREF(list);
3797 PyErr_SetString(PyExc_MemoryError,
3798 "List item creation failed");
3799 list = NULL;
3800 break;
3802 PyList_Append(list, item);
3803 Py_DECREF(item);
3805 free(log_list_start);
3807 return list;
3811 static PyObject*
3812 DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
3814 int err;
3815 DB_TXN_STAT* sp;
3816 PyObject* d = NULL;
3817 u_int32_t flags=0;
3819 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
3820 return NULL;
3821 CHECK_ENV_NOT_CLOSED(self);
3823 MYDB_BEGIN_ALLOW_THREADS;
3824 #if (DBVER >= 40)
3825 err = self->db_env->txn_stat(self->db_env, &sp, flags);
3826 #elif (DBVER == 33)
3827 err = txn_stat(self->db_env, &sp);
3828 #else
3829 err = txn_stat(self->db_env, &sp, NULL);
3830 #endif
3831 MYDB_END_ALLOW_THREADS;
3832 RETURN_IF_ERR();
3834 /* Turn the stat structure into a dictionary */
3835 d = PyDict_New();
3836 if (d == NULL) {
3837 free(sp);
3838 return NULL;
3841 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
3843 MAKE_ENTRY(time_ckp);
3844 MAKE_ENTRY(last_txnid);
3845 MAKE_ENTRY(maxtxns);
3846 MAKE_ENTRY(nactive);
3847 MAKE_ENTRY(maxnactive);
3848 MAKE_ENTRY(nbegins);
3849 MAKE_ENTRY(naborts);
3850 MAKE_ENTRY(ncommits);
3851 MAKE_ENTRY(regsize);
3852 MAKE_ENTRY(region_wait);
3853 MAKE_ENTRY(region_nowait);
3855 #undef MAKE_ENTRY
3856 free(sp);
3857 return d;
3861 static PyObject*
3862 DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
3864 int flags=0;
3865 int oldValue=0;
3867 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
3868 return NULL;
3869 CHECK_ENV_NOT_CLOSED(self);
3871 if (self->moduleFlags.getReturnsNone)
3872 ++oldValue;
3873 if (self->moduleFlags.cursorSetReturnsNone)
3874 ++oldValue;
3875 self->moduleFlags.getReturnsNone = (flags >= 1);
3876 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
3877 return PyInt_FromLong(oldValue);
3881 /* --------------------------------------------------------------------- */
3882 /* DBTxn methods */
3885 static PyObject*
3886 DBTxn_commit(DBTxnObject* self, PyObject* args)
3888 int flags=0, err;
3889 DB_TXN *txn;
3891 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
3892 return NULL;
3894 if (!self->txn) {
3895 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3896 "DBTxn must not be used after txn_commit or txn_abort"));
3897 return NULL;
3899 txn = self->txn;
3900 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
3901 MYDB_BEGIN_ALLOW_THREADS;
3902 #if (DBVER >= 40)
3903 err = txn->commit(txn, flags);
3904 #else
3905 err = txn_commit(txn, flags);
3906 #endif
3907 MYDB_END_ALLOW_THREADS;
3908 RETURN_IF_ERR();
3909 RETURN_NONE();
3912 static PyObject*
3913 DBTxn_prepare(DBTxnObject* self, PyObject* args)
3915 #if (DBVER >= 33)
3916 int err;
3917 char* gid=NULL;
3918 int gid_size=0;
3920 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
3921 return NULL;
3923 if (gid_size != DB_XIDDATASIZE) {
3924 PyErr_SetString(PyExc_TypeError,
3925 "gid must be DB_XIDDATASIZE bytes long");
3926 return NULL;
3929 if (!self->txn) {
3930 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3931 "DBTxn must not be used after txn_commit or txn_abort"));
3932 return NULL;
3934 MYDB_BEGIN_ALLOW_THREADS;
3935 #if (DBVER >= 40)
3936 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
3937 #else
3938 err = txn_prepare(self->txn, (u_int8_t*)gid);
3939 #endif
3940 MYDB_END_ALLOW_THREADS;
3941 RETURN_IF_ERR();
3942 RETURN_NONE();
3943 #else
3944 int err;
3946 if (!PyArg_ParseTuple(args, ":prepare"))
3947 return NULL;
3949 if (!self->txn) {
3950 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3951 "DBTxn must not be used after txn_commit or txn_abort"));
3952 return NULL;
3954 MYDB_BEGIN_ALLOW_THREADS;
3955 err = txn_prepare(self->txn);
3956 MYDB_END_ALLOW_THREADS;
3957 RETURN_IF_ERR();
3958 RETURN_NONE();
3959 #endif
3963 static PyObject*
3964 DBTxn_abort(DBTxnObject* self, PyObject* args)
3966 int err;
3967 DB_TXN *txn;
3969 if (!PyArg_ParseTuple(args, ":abort"))
3970 return NULL;
3972 if (!self->txn) {
3973 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
3974 "DBTxn must not be used after txn_commit or txn_abort"));
3975 return NULL;
3977 txn = self->txn;
3978 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
3979 MYDB_BEGIN_ALLOW_THREADS;
3980 #if (DBVER >= 40)
3981 err = txn->abort(txn);
3982 #else
3983 err = txn_abort(txn);
3984 #endif
3985 MYDB_END_ALLOW_THREADS;
3986 RETURN_IF_ERR();
3987 RETURN_NONE();
3991 static PyObject*
3992 DBTxn_id(DBTxnObject* self, PyObject* args)
3994 int id;
3996 if (!PyArg_ParseTuple(args, ":id"))
3997 return NULL;
3999 if (!self->txn) {
4000 PyErr_SetObject(DBError, Py_BuildValue("(is)", 0,
4001 "DBTxn must not be used after txn_commit or txn_abort"));
4002 return NULL;
4004 MYDB_BEGIN_ALLOW_THREADS;
4005 #if (DBVER >= 40)
4006 id = self->txn->id(self->txn);
4007 #else
4008 id = txn_id(self->txn);
4009 #endif
4010 MYDB_END_ALLOW_THREADS;
4011 return PyInt_FromLong(id);
4014 /* --------------------------------------------------------------------- */
4015 /* Method definition tables and type objects */
4017 static PyMethodDef DB_methods[] = {
4018 {"append", (PyCFunction)DB_append, METH_VARARGS},
4019 #if (DBVER >= 33)
4020 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
4021 #endif
4022 {"close", (PyCFunction)DB_close, METH_VARARGS},
4023 #if (DBVER >= 32)
4024 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
4025 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
4026 #endif
4027 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
4028 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
4029 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
4030 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
4031 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
4032 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
4033 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
4034 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
4035 {"join", (PyCFunction)DB_join, METH_VARARGS},
4036 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
4037 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
4038 {"items", (PyCFunction)DB_items, METH_VARARGS},
4039 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
4040 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
4041 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
4042 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
4043 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
4044 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
4045 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
4046 #if (DBVER >= 41)
4047 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4048 #endif
4049 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
4050 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
4051 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
4052 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
4053 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
4054 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
4055 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
4056 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
4057 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
4058 #if (DBVER >= 32)
4059 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
4060 #endif
4061 {"stat", (PyCFunction)DB_stat, METH_VARARGS},
4062 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
4063 #if (DBVER >= 33)
4064 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
4065 #endif
4066 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
4067 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
4068 {"values", (PyCFunction)DB_values, METH_VARARGS},
4069 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
4070 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
4071 {NULL, NULL} /* sentinel */
4075 static PyMappingMethods DB_mapping = {
4076 (inquiry)DB_length, /*mp_length*/
4077 (binaryfunc)DB_subscript, /*mp_subscript*/
4078 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
4082 static PyMethodDef DBCursor_methods[] = {
4083 {"close", (PyCFunction)DBC_close, METH_VARARGS},
4084 {"count", (PyCFunction)DBC_count, METH_VARARGS},
4085 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
4086 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
4087 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
4088 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
4089 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
4090 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
4091 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
4092 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
4093 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
4094 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
4095 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
4096 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
4097 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
4098 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
4099 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
4100 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
4101 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
4102 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
4103 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
4104 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
4105 {NULL, NULL} /* sentinel */
4109 static PyMethodDef DBEnv_methods[] = {
4110 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
4111 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
4112 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
4113 #if (DBVER >= 41)
4114 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
4115 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
4116 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
4117 #endif
4118 #if (DBVER >= 40)
4119 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
4120 #endif
4121 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
4122 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
4123 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
4124 #if (DBVER >= 32)
4125 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
4126 #endif
4127 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
4128 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
4129 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
4130 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
4131 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
4132 #if (DBVER >= 32)
4133 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
4134 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
4135 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
4136 #endif
4137 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
4138 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
4139 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
4140 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
4141 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
4142 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
4143 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
4144 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
4145 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
4146 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
4147 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
4148 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
4149 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
4150 {NULL, NULL} /* sentinel */
4154 static PyMethodDef DBTxn_methods[] = {
4155 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
4156 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
4157 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
4158 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
4159 {NULL, NULL} /* sentinel */
4163 static PyObject*
4164 DB_getattr(DBObject* self, char *name)
4166 return Py_FindMethod(DB_methods, (PyObject* )self, name);
4170 static PyObject*
4171 DBEnv_getattr(DBEnvObject* self, char *name)
4173 if (!strcmp(name, "db_home")) {
4174 CHECK_ENV_NOT_CLOSED(self);
4175 if (self->db_env->db_home == NULL) {
4176 RETURN_NONE();
4178 return PyString_FromString(self->db_env->db_home);
4181 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
4185 static PyObject*
4186 DBCursor_getattr(DBCursorObject* self, char *name)
4188 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
4191 static PyObject*
4192 DBTxn_getattr(DBTxnObject* self, char *name)
4194 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
4197 static PyObject*
4198 DBLock_getattr(DBLockObject* self, char *name)
4200 return NULL;
4203 statichere PyTypeObject DB_Type = {
4204 PyObject_HEAD_INIT(NULL)
4205 0, /*ob_size*/
4206 "DB", /*tp_name*/
4207 sizeof(DBObject), /*tp_basicsize*/
4208 0, /*tp_itemsize*/
4209 /* methods */
4210 (destructor)DB_dealloc, /*tp_dealloc*/
4211 0, /*tp_print*/
4212 (getattrfunc)DB_getattr, /*tp_getattr*/
4213 0, /*tp_setattr*/
4214 0, /*tp_compare*/
4215 0, /*tp_repr*/
4216 0, /*tp_as_number*/
4217 0, /*tp_as_sequence*/
4218 &DB_mapping,/*tp_as_mapping*/
4219 0, /*tp_hash*/
4223 statichere PyTypeObject DBCursor_Type = {
4224 PyObject_HEAD_INIT(NULL)
4225 0, /*ob_size*/
4226 "DBCursor", /*tp_name*/
4227 sizeof(DBCursorObject), /*tp_basicsize*/
4228 0, /*tp_itemsize*/
4229 /* methods */
4230 (destructor)DBCursor_dealloc,/*tp_dealloc*/
4231 0, /*tp_print*/
4232 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
4233 0, /*tp_setattr*/
4234 0, /*tp_compare*/
4235 0, /*tp_repr*/
4236 0, /*tp_as_number*/
4237 0, /*tp_as_sequence*/
4238 0, /*tp_as_mapping*/
4239 0, /*tp_hash*/
4243 statichere PyTypeObject DBEnv_Type = {
4244 PyObject_HEAD_INIT(NULL)
4245 0, /*ob_size*/
4246 "DBEnv", /*tp_name*/
4247 sizeof(DBEnvObject), /*tp_basicsize*/
4248 0, /*tp_itemsize*/
4249 /* methods */
4250 (destructor)DBEnv_dealloc, /*tp_dealloc*/
4251 0, /*tp_print*/
4252 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
4253 0, /*tp_setattr*/
4254 0, /*tp_compare*/
4255 0, /*tp_repr*/
4256 0, /*tp_as_number*/
4257 0, /*tp_as_sequence*/
4258 0, /*tp_as_mapping*/
4259 0, /*tp_hash*/
4262 statichere PyTypeObject DBTxn_Type = {
4263 PyObject_HEAD_INIT(NULL)
4264 0, /*ob_size*/
4265 "DBTxn", /*tp_name*/
4266 sizeof(DBTxnObject), /*tp_basicsize*/
4267 0, /*tp_itemsize*/
4268 /* methods */
4269 (destructor)DBTxn_dealloc, /*tp_dealloc*/
4270 0, /*tp_print*/
4271 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
4272 0, /*tp_setattr*/
4273 0, /*tp_compare*/
4274 0, /*tp_repr*/
4275 0, /*tp_as_number*/
4276 0, /*tp_as_sequence*/
4277 0, /*tp_as_mapping*/
4278 0, /*tp_hash*/
4282 statichere PyTypeObject DBLock_Type = {
4283 PyObject_HEAD_INIT(NULL)
4284 0, /*ob_size*/
4285 "DBLock", /*tp_name*/
4286 sizeof(DBLockObject), /*tp_basicsize*/
4287 0, /*tp_itemsize*/
4288 /* methods */
4289 (destructor)DBLock_dealloc, /*tp_dealloc*/
4290 0, /*tp_print*/
4291 (getattrfunc)DBLock_getattr, /*tp_getattr*/
4292 0, /*tp_setattr*/
4293 0, /*tp_compare*/
4294 0, /*tp_repr*/
4295 0, /*tp_as_number*/
4296 0, /*tp_as_sequence*/
4297 0, /*tp_as_mapping*/
4298 0, /*tp_hash*/
4302 /* --------------------------------------------------------------------- */
4303 /* Module-level functions */
4305 static PyObject*
4306 DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
4308 PyObject* dbenvobj = NULL;
4309 int flags = 0;
4310 char* kwnames[] = { "dbEnv", "flags", NULL};
4312 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
4313 &dbenvobj, &flags))
4314 return NULL;
4315 if (dbenvobj == Py_None)
4316 dbenvobj = NULL;
4317 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
4318 makeTypeError("DBEnv", dbenvobj);
4319 return NULL;
4322 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
4326 static PyObject*
4327 DBEnv_construct(PyObject* self, PyObject* args)
4329 int flags = 0;
4330 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
4331 return (PyObject* )newDBEnvObject(flags);
4335 static char bsddb_version_doc[] =
4336 "Returns a tuple of major, minor, and patch release numbers of the\n\
4337 underlying DB library.";
4339 static PyObject*
4340 bsddb_version(PyObject* self, PyObject* args)
4342 int major, minor, patch;
4344 if (!PyArg_ParseTuple(args, ":version"))
4345 return NULL;
4346 db_version(&major, &minor, &patch);
4347 return Py_BuildValue("(iii)", major, minor, patch);
4351 /* List of functions defined in the module */
4353 static PyMethodDef bsddb_methods[] = {
4354 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
4355 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
4356 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
4357 {NULL, NULL} /* sentinel */
4361 /* --------------------------------------------------------------------- */
4362 /* Module initialization */
4365 /* Convenience routine to export an integer value.
4366 * Errors are silently ignored, for better or for worse...
4368 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
4370 DL_EXPORT(void) init_bsddb(void)
4372 PyObject* m;
4373 PyObject* d;
4374 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
4375 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
4376 PyObject* cvsid_s = PyString_FromString( rcs_id );
4378 /* Initialize the type of the new type objects here; doing it here
4379 is required for portability to Windows without requiring C++. */
4380 DB_Type.ob_type = &PyType_Type;
4381 DBCursor_Type.ob_type = &PyType_Type;
4382 DBEnv_Type.ob_type = &PyType_Type;
4383 DBTxn_Type.ob_type = &PyType_Type;
4384 DBLock_Type.ob_type = &PyType_Type;
4387 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
4388 /* Save the current interpreter, so callbacks can do the right thing. */
4389 _db_interpreterState = PyThreadState_Get()->interp;
4390 #endif
4392 /* Create the module and add the functions */
4393 m = Py_InitModule("_bsddb", bsddb_methods);
4395 /* Add some symbolic constants to the module */
4396 d = PyModule_GetDict(m);
4397 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
4398 PyDict_SetItemString(d, "cvsid", cvsid_s);
4399 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
4400 Py_DECREF(pybsddb_version_s);
4401 pybsddb_version_s = NULL;
4402 Py_DECREF(cvsid_s);
4403 cvsid_s = NULL;
4404 Py_DECREF(db_version_s);
4405 db_version_s = NULL;
4407 ADD_INT(d, DB_VERSION_MAJOR);
4408 ADD_INT(d, DB_VERSION_MINOR);
4409 ADD_INT(d, DB_VERSION_PATCH);
4411 ADD_INT(d, DB_MAX_PAGES);
4412 ADD_INT(d, DB_MAX_RECORDS);
4414 #if (DBVER >= 42)
4415 ADD_INT(d, DB_RPCCLIENT);
4416 #else
4417 ADD_INT(d, DB_CLIENT);
4418 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
4419 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
4420 #endif
4421 ADD_INT(d, DB_XA_CREATE);
4423 ADD_INT(d, DB_CREATE);
4424 ADD_INT(d, DB_NOMMAP);
4425 ADD_INT(d, DB_THREAD);
4427 ADD_INT(d, DB_FORCE);
4428 ADD_INT(d, DB_INIT_CDB);
4429 ADD_INT(d, DB_INIT_LOCK);
4430 ADD_INT(d, DB_INIT_LOG);
4431 ADD_INT(d, DB_INIT_MPOOL);
4432 ADD_INT(d, DB_INIT_TXN);
4433 #if (DBVER >= 32)
4434 ADD_INT(d, DB_JOINENV);
4435 #endif
4437 ADD_INT(d, DB_RECOVER);
4438 ADD_INT(d, DB_RECOVER_FATAL);
4439 ADD_INT(d, DB_TXN_NOSYNC);
4440 ADD_INT(d, DB_USE_ENVIRON);
4441 ADD_INT(d, DB_USE_ENVIRON_ROOT);
4443 ADD_INT(d, DB_LOCKDOWN);
4444 ADD_INT(d, DB_PRIVATE);
4445 ADD_INT(d, DB_SYSTEM_MEM);
4447 ADD_INT(d, DB_TXN_SYNC);
4448 ADD_INT(d, DB_TXN_NOWAIT);
4450 ADD_INT(d, DB_EXCL);
4451 ADD_INT(d, DB_FCNTL_LOCKING);
4452 ADD_INT(d, DB_ODDFILESIZE);
4453 ADD_INT(d, DB_RDWRMASTER);
4454 ADD_INT(d, DB_RDONLY);
4455 ADD_INT(d, DB_TRUNCATE);
4456 #if (DBVER >= 32)
4457 ADD_INT(d, DB_EXTENT);
4458 ADD_INT(d, DB_CDB_ALLDB);
4459 ADD_INT(d, DB_VERIFY);
4460 #endif
4461 ADD_INT(d, DB_UPGRADE);
4463 ADD_INT(d, DB_AGGRESSIVE);
4464 ADD_INT(d, DB_NOORDERCHK);
4465 ADD_INT(d, DB_ORDERCHKONLY);
4466 ADD_INT(d, DB_PR_PAGE);
4467 #if ! (DBVER >= 33)
4468 ADD_INT(d, DB_VRFY_FLAGMASK);
4469 ADD_INT(d, DB_PR_HEADERS);
4470 #endif
4471 ADD_INT(d, DB_PR_RECOVERYTEST);
4472 ADD_INT(d, DB_SALVAGE);
4474 ADD_INT(d, DB_LOCK_NORUN);
4475 ADD_INT(d, DB_LOCK_DEFAULT);
4476 ADD_INT(d, DB_LOCK_OLDEST);
4477 ADD_INT(d, DB_LOCK_RANDOM);
4478 ADD_INT(d, DB_LOCK_YOUNGEST);
4479 #if (DBVER >= 33)
4480 ADD_INT(d, DB_LOCK_MAXLOCKS);
4481 ADD_INT(d, DB_LOCK_MINLOCKS);
4482 ADD_INT(d, DB_LOCK_MINWRITE);
4483 #endif
4486 #if (DBVER >= 33)
4487 /* docs say to use zero instead */
4488 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
4489 #else
4490 ADD_INT(d, DB_LOCK_CONFLICT);
4491 #endif
4493 ADD_INT(d, DB_LOCK_DUMP);
4494 ADD_INT(d, DB_LOCK_GET);
4495 ADD_INT(d, DB_LOCK_INHERIT);
4496 ADD_INT(d, DB_LOCK_PUT);
4497 ADD_INT(d, DB_LOCK_PUT_ALL);
4498 ADD_INT(d, DB_LOCK_PUT_OBJ);
4500 ADD_INT(d, DB_LOCK_NG);
4501 ADD_INT(d, DB_LOCK_READ);
4502 ADD_INT(d, DB_LOCK_WRITE);
4503 ADD_INT(d, DB_LOCK_NOWAIT);
4504 #if (DBVER >= 32)
4505 ADD_INT(d, DB_LOCK_WAIT);
4506 #endif
4507 ADD_INT(d, DB_LOCK_IWRITE);
4508 ADD_INT(d, DB_LOCK_IREAD);
4509 ADD_INT(d, DB_LOCK_IWR);
4510 #if (DBVER >= 33)
4511 ADD_INT(d, DB_LOCK_DIRTY);
4512 ADD_INT(d, DB_LOCK_WWRITE);
4513 #endif
4515 ADD_INT(d, DB_LOCK_RECORD);
4516 ADD_INT(d, DB_LOCK_UPGRADE);
4517 #if (DBVER >= 32)
4518 ADD_INT(d, DB_LOCK_SWITCH);
4519 #endif
4520 #if (DBVER >= 33)
4521 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
4522 #endif
4524 ADD_INT(d, DB_LOCK_NOWAIT);
4525 ADD_INT(d, DB_LOCK_RECORD);
4526 ADD_INT(d, DB_LOCK_UPGRADE);
4528 #if (DBVER >= 33)
4529 ADD_INT(d, DB_LSTAT_ABORTED);
4530 ADD_INT(d, DB_LSTAT_ERR);
4531 ADD_INT(d, DB_LSTAT_FREE);
4532 ADD_INT(d, DB_LSTAT_HELD);
4533 #if (DBVER == 33)
4534 ADD_INT(d, DB_LSTAT_NOGRANT);
4535 #endif
4536 ADD_INT(d, DB_LSTAT_PENDING);
4537 ADD_INT(d, DB_LSTAT_WAITING);
4538 #endif
4540 ADD_INT(d, DB_ARCH_ABS);
4541 ADD_INT(d, DB_ARCH_DATA);
4542 ADD_INT(d, DB_ARCH_LOG);
4544 ADD_INT(d, DB_BTREE);
4545 ADD_INT(d, DB_HASH);
4546 ADD_INT(d, DB_RECNO);
4547 ADD_INT(d, DB_QUEUE);
4548 ADD_INT(d, DB_UNKNOWN);
4550 ADD_INT(d, DB_DUP);
4551 ADD_INT(d, DB_DUPSORT);
4552 ADD_INT(d, DB_RECNUM);
4553 ADD_INT(d, DB_RENUMBER);
4554 ADD_INT(d, DB_REVSPLITOFF);
4555 ADD_INT(d, DB_SNAPSHOT);
4557 ADD_INT(d, DB_JOIN_NOSORT);
4559 ADD_INT(d, DB_AFTER);
4560 ADD_INT(d, DB_APPEND);
4561 ADD_INT(d, DB_BEFORE);
4562 ADD_INT(d, DB_CACHED_COUNTS);
4563 #if (DBVER >= 41)
4564 _addIntToDict(d, "DB_CHECKPOINT", 0);
4565 #else
4566 ADD_INT(d, DB_CHECKPOINT);
4567 ADD_INT(d, DB_CURLSN);
4568 #endif
4569 #if ((DBVER >= 33) && (DBVER <= 41))
4570 ADD_INT(d, DB_COMMIT);
4571 #endif
4572 ADD_INT(d, DB_CONSUME);
4573 #if (DBVER >= 32)
4574 ADD_INT(d, DB_CONSUME_WAIT);
4575 #endif
4576 ADD_INT(d, DB_CURRENT);
4577 #if (DBVER >= 33)
4578 ADD_INT(d, DB_FAST_STAT);
4579 #endif
4580 ADD_INT(d, DB_FIRST);
4581 ADD_INT(d, DB_FLUSH);
4582 ADD_INT(d, DB_GET_BOTH);
4583 ADD_INT(d, DB_GET_RECNO);
4584 ADD_INT(d, DB_JOIN_ITEM);
4585 ADD_INT(d, DB_KEYFIRST);
4586 ADD_INT(d, DB_KEYLAST);
4587 ADD_INT(d, DB_LAST);
4588 ADD_INT(d, DB_NEXT);
4589 ADD_INT(d, DB_NEXT_DUP);
4590 ADD_INT(d, DB_NEXT_NODUP);
4591 ADD_INT(d, DB_NODUPDATA);
4592 ADD_INT(d, DB_NOOVERWRITE);
4593 ADD_INT(d, DB_NOSYNC);
4594 ADD_INT(d, DB_POSITION);
4595 ADD_INT(d, DB_PREV);
4596 ADD_INT(d, DB_PREV_NODUP);
4597 ADD_INT(d, DB_RECORDCOUNT);
4598 ADD_INT(d, DB_SET);
4599 ADD_INT(d, DB_SET_RANGE);
4600 ADD_INT(d, DB_SET_RECNO);
4601 ADD_INT(d, DB_WRITECURSOR);
4603 ADD_INT(d, DB_OPFLAGS_MASK);
4604 ADD_INT(d, DB_RMW);
4605 #if (DBVER >= 33)
4606 ADD_INT(d, DB_DIRTY_READ);
4607 ADD_INT(d, DB_MULTIPLE);
4608 ADD_INT(d, DB_MULTIPLE_KEY);
4609 #endif
4611 #if (DBVER >= 33)
4612 ADD_INT(d, DB_DONOTINDEX);
4613 #endif
4615 #if (DBVER >= 41)
4616 _addIntToDict(d, "DB_INCOMPLETE", 0);
4617 #else
4618 ADD_INT(d, DB_INCOMPLETE);
4619 #endif
4620 ADD_INT(d, DB_KEYEMPTY);
4621 ADD_INT(d, DB_KEYEXIST);
4622 ADD_INT(d, DB_LOCK_DEADLOCK);
4623 ADD_INT(d, DB_LOCK_NOTGRANTED);
4624 ADD_INT(d, DB_NOSERVER);
4625 ADD_INT(d, DB_NOSERVER_HOME);
4626 ADD_INT(d, DB_NOSERVER_ID);
4627 ADD_INT(d, DB_NOTFOUND);
4628 ADD_INT(d, DB_OLD_VERSION);
4629 ADD_INT(d, DB_RUNRECOVERY);
4630 ADD_INT(d, DB_VERIFY_BAD);
4631 #if (DBVER >= 33)
4632 ADD_INT(d, DB_PAGE_NOTFOUND);
4633 ADD_INT(d, DB_SECONDARY_BAD);
4634 #endif
4635 #if (DBVER >= 40)
4636 ADD_INT(d, DB_STAT_CLEAR);
4637 ADD_INT(d, DB_REGION_INIT);
4638 ADD_INT(d, DB_NOLOCKING);
4639 ADD_INT(d, DB_YIELDCPU);
4640 ADD_INT(d, DB_PANIC_ENVIRONMENT);
4641 ADD_INT(d, DB_NOPANIC);
4642 #endif
4644 #if (DBVER >= 42)
4645 ADD_INT(d, DB_TIME_NOTGRANTED);
4646 ADD_INT(d, DB_TXN_NOT_DURABLE);
4647 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
4648 ADD_INT(d, DB_LOG_AUTOREMOVE);
4649 ADD_INT(d, DB_DIRECT_LOG);
4650 ADD_INT(d, DB_DIRECT_DB);
4651 ADD_INT(d, DB_INIT_REP);
4652 ADD_INT(d, DB_ENCRYPT);
4653 ADD_INT(d, DB_CHKSUM);
4654 #endif
4656 #if (DBVER >= 41)
4657 ADD_INT(d, DB_ENCRYPT_AES);
4658 ADD_INT(d, DB_AUTO_COMMIT);
4659 #else
4660 /* allow berkeleydb 4.1 aware apps to run on older versions */
4661 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
4662 #endif
4664 ADD_INT(d, EINVAL);
4665 ADD_INT(d, EACCES);
4666 ADD_INT(d, ENOSPC);
4667 ADD_INT(d, ENOMEM);
4668 ADD_INT(d, EAGAIN);
4669 ADD_INT(d, EBUSY);
4670 ADD_INT(d, EEXIST);
4671 ADD_INT(d, ENOENT);
4672 ADD_INT(d, EPERM);
4674 #if (DBVER >= 40)
4675 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
4676 ADD_INT(d, DB_SET_TXN_TIMEOUT);
4677 #endif
4679 /* The base exception class is DBError */
4680 DBError = PyErr_NewException("bsddb._db.DBError", NULL, NULL);
4681 PyDict_SetItemString(d, "DBError", DBError);
4683 /* Some magic to make DBNotFoundError derive from both DBError and
4684 KeyError, since the API only supports using one base class. */
4685 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
4686 PyRun_String("class DBNotFoundError(DBError, KeyError): pass",
4687 Py_file_input, d, d);
4688 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
4689 PyDict_DelItemString(d, "KeyError");
4692 /* All the rest of the exceptions derive only from DBError */
4693 #define MAKE_EX(name) name = PyErr_NewException("bsddb._db." #name, DBError, NULL); \
4694 PyDict_SetItemString(d, #name, name)
4696 #if !INCOMPLETE_IS_WARNING
4697 MAKE_EX(DBIncompleteError);
4698 #endif
4699 MAKE_EX(DBKeyEmptyError);
4700 MAKE_EX(DBKeyExistError);
4701 MAKE_EX(DBLockDeadlockError);
4702 MAKE_EX(DBLockNotGrantedError);
4703 MAKE_EX(DBOldVersionError);
4704 MAKE_EX(DBRunRecoveryError);
4705 MAKE_EX(DBVerifyBadError);
4706 MAKE_EX(DBNoServerError);
4707 MAKE_EX(DBNoServerHomeError);
4708 MAKE_EX(DBNoServerIDError);
4709 #if (DBVER >= 33)
4710 MAKE_EX(DBPageNotFoundError);
4711 MAKE_EX(DBSecondaryBadError);
4712 #endif
4714 MAKE_EX(DBInvalidArgError);
4715 MAKE_EX(DBAccessError);
4716 MAKE_EX(DBNoSpaceError);
4717 MAKE_EX(DBNoMemoryError);
4718 MAKE_EX(DBAgainError);
4719 MAKE_EX(DBBusyError);
4720 MAKE_EX(DBFileExistsError);
4721 MAKE_EX(DBNoSuchFileError);
4722 MAKE_EX(DBPermissionsError);
4724 #undef MAKE_EX
4726 /* Check for errors */
4727 if (PyErr_Occurred()) {
4728 PyErr_Print();
4729 Py_FatalError("can't initialize module _bsddb");