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
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
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
33 ------------------------------------------------------------------------*/
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
38 * written to replace a SWIG-generated file. It has since been updated
39 * to compile with BerkeleyDB versions 3.2 through 4.2.
41 * This module was started by Andrew Kuchling to remove the dependency
42 * on SWIG in a package by Gregory P. Smith who based his work on a
43 * similar package by Robin Dunn <robin@alldunn.com> which wrapped
46 * Development of this module then returned full circle back to Robin Dunn
47 * who worked on behalf of Digital Creations to complete the wrapping of
48 * the DB 3.x API and to build a solid unit test suite. Robin has
49 * since gone onto other projects (wxPython).
51 * Gregory P. Smith <greg@krypto.org> is once again the maintainer.
53 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
54 * Things can change faster than the header of this file is updated. This
55 * file is shared with the PyBSDDB project at SourceForge:
57 * http://pybsddb.sf.net
59 * This file should remain backward compatible with Python 2.1, but see PEP
60 * 291 for the most current backward compatibility requirements:
62 * http://www.python.org/peps/pep-0291.html
64 * This module contains 6 types:
67 * DBCursor (Database Cursor)
68 * DBEnv (database environment)
69 * DBTxn (An explicit database transaction)
70 * DBLock (A lock handle)
71 * DBSequence (Sequence)
75 /* --------------------------------------------------------------------- */
78 * Portions of this module, associated unit tests and build scripts are the
79 * result of a contract with The Written Word (http://thewrittenword.com/)
80 * Many thanks go out to them for causing me to raise the bar on quality and
81 * functionality, resulting in a better bsddb3 package for all of us to use.
86 /* --------------------------------------------------------------------- */
88 #include <stddef.h> /* for offsetof() */
91 #define COMPILING_BSDDB_C
93 #undef COMPILING_BSDDB_C
95 static char *rcs_id
= "$Id$";
97 /* --------------------------------------------------------------------- */
98 /* Various macro definitions */
100 #if (PY_VERSION_HEX < 0x02050000)
101 typedef int Py_ssize_t
;
106 /* These are for when calling Python --> C */
107 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
108 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
110 /* For 2.3, use the PyGILState_ calls */
111 #if (PY_VERSION_HEX >= 0x02030000)
112 #define MYDB_USE_GILSTATE
115 /* and these are for calling C --> Python */
116 #if defined(MYDB_USE_GILSTATE)
117 #define MYDB_BEGIN_BLOCK_THREADS \
118 PyGILState_STATE __savestate = PyGILState_Ensure();
119 #define MYDB_END_BLOCK_THREADS \
120 PyGILState_Release(__savestate);
121 #else /* MYDB_USE_GILSTATE */
122 /* Pre GILState API - do it the long old way */
123 static PyInterpreterState
* _db_interpreterState
= NULL
;
124 #define MYDB_BEGIN_BLOCK_THREADS { \
125 PyThreadState* prevState; \
126 PyThreadState* newState; \
127 PyEval_AcquireLock(); \
128 newState = PyThreadState_New(_db_interpreterState); \
129 prevState = PyThreadState_Swap(newState);
131 #define MYDB_END_BLOCK_THREADS \
132 newState = PyThreadState_Swap(prevState); \
133 PyThreadState_Clear(newState); \
134 PyEval_ReleaseLock(); \
135 PyThreadState_Delete(newState); \
137 #endif /* MYDB_USE_GILSTATE */
140 /* Compiled without threads - avoid all this cruft */
141 #define MYDB_BEGIN_ALLOW_THREADS
142 #define MYDB_END_ALLOW_THREADS
143 #define MYDB_BEGIN_BLOCK_THREADS
144 #define MYDB_END_BLOCK_THREADS
148 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
149 #define INCOMPLETE_IS_WARNING 1
151 /* --------------------------------------------------------------------- */
154 static PyObject
* DBError
; /* Base class, all others derive from this */
155 static PyObject
* DBCursorClosedError
; /* raised when trying to use a closed cursor object */
156 static PyObject
* DBKeyEmptyError
; /* DB_KEYEMPTY: also derives from KeyError */
157 static PyObject
* DBKeyExistError
; /* DB_KEYEXIST */
158 static PyObject
* DBLockDeadlockError
; /* DB_LOCK_DEADLOCK */
159 static PyObject
* DBLockNotGrantedError
; /* DB_LOCK_NOTGRANTED */
160 static PyObject
* DBNotFoundError
; /* DB_NOTFOUND: also derives from KeyError */
161 static PyObject
* DBOldVersionError
; /* DB_OLD_VERSION */
162 static PyObject
* DBRunRecoveryError
; /* DB_RUNRECOVERY */
163 static PyObject
* DBVerifyBadError
; /* DB_VERIFY_BAD */
164 static PyObject
* DBNoServerError
; /* DB_NOSERVER */
165 static PyObject
* DBNoServerHomeError
; /* DB_NOSERVER_HOME */
166 static PyObject
* DBNoServerIDError
; /* DB_NOSERVER_ID */
168 static PyObject
* DBPageNotFoundError
; /* DB_PAGE_NOTFOUND */
169 static PyObject
* DBSecondaryBadError
; /* DB_SECONDARY_BAD */
172 #if !INCOMPLETE_IS_WARNING
173 static PyObject
* DBIncompleteError
; /* DB_INCOMPLETE */
176 static PyObject
* DBInvalidArgError
; /* EINVAL */
177 static PyObject
* DBAccessError
; /* EACCES */
178 static PyObject
* DBNoSpaceError
; /* ENOSPC */
179 static PyObject
* DBNoMemoryError
; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
180 static PyObject
* DBAgainError
; /* EAGAIN */
181 static PyObject
* DBBusyError
; /* EBUSY */
182 static PyObject
* DBFileExistsError
; /* EEXIST */
183 static PyObject
* DBNoSuchFileError
; /* ENOENT */
184 static PyObject
* DBPermissionsError
; /* EPERM */
187 #define DB_BUFFER_SMALL ENOMEM
191 /* --------------------------------------------------------------------- */
192 /* Structure definitions */
194 #if PYTHON_API_VERSION < 1010
195 #error "Python 2.1 or later required"
199 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
200 #define DEFAULT_GET_RETURNS_NONE 1
201 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
204 staticforward PyTypeObject DB_Type
, DBCursor_Type
, DBEnv_Type
, DBTxn_Type
, DBLock_Type
;
207 /* for compatibility with Python 2.5 and earlier */
208 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
211 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
212 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
213 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
214 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
215 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
217 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
221 /* --------------------------------------------------------------------- */
222 /* Utility macros and functions */
224 #define RETURN_IF_ERR() \
225 if (makeDBError(err)) { \
229 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
231 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
232 if ((nonNull) == NULL) { \
233 PyObject *errTuple = NULL; \
234 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
235 PyErr_SetObject((pyErrObj), errTuple); \
236 Py_DECREF(errTuple); \
240 #define CHECK_DB_NOT_CLOSED(dbobj) \
241 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
243 #define CHECK_ENV_NOT_CLOSED(env) \
244 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
246 #define CHECK_CURSOR_NOT_CLOSED(curs) \
247 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
250 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
251 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
254 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
255 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
257 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
259 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
260 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
263 static int makeDBError(int err
);
266 /* Return the access method type of the DBObject */
267 static int _DB_get_type(DBObject
* self
)
272 err
= self
->db
->get_type(self
->db
, &type
);
273 if (makeDBError(err
)) {
278 return self
->db
->get_type(self
->db
);
283 /* Create a DBT structure (containing key and data values) from Python
284 strings. Returns 1 on success, 0 on an error. */
285 static int make_dbt(PyObject
* obj
, DBT
* dbt
)
288 if (obj
== Py_None
) {
289 /* no need to do anything, the structure has already been zeroed */
291 else if (!PyArg_Parse(obj
, "s#", &dbt
->data
, &dbt
->size
)) {
292 PyErr_SetString(PyExc_TypeError
,
293 "Data values must be of type string or None.");
300 /* Recno and Queue DBs can have integer keys. This function figures out
301 what's been given, verifies that it's allowed, and then makes the DBT.
303 Caller MUST call FREE_DBT(key) when done. */
305 make_key_dbt(DBObject
* self
, PyObject
* keyobj
, DBT
* key
, int* pflags
)
311 if (keyobj
== Py_None
) {
312 type
= _DB_get_type(self
);
315 if (type
== DB_RECNO
|| type
== DB_QUEUE
) {
318 "None keys not allowed for Recno and Queue DB's");
321 /* no need to do anything, the structure has already been zeroed */
324 else if (PyString_Check(keyobj
)) {
325 /* verify access method type */
326 type
= _DB_get_type(self
);
329 if (type
== DB_RECNO
|| type
== DB_QUEUE
) {
332 "String keys not allowed for Recno and Queue DB's");
337 * NOTE(gps): I don't like doing a data copy here, it seems
338 * wasteful. But without a clean way to tell FREE_DBT if it
339 * should free key->data or not we have to. Other places in
340 * the code check for DB_THREAD and forceably set DBT_MALLOC
341 * when we otherwise would leave flags 0 to indicate that.
343 key
->data
= malloc(PyString_GET_SIZE(keyobj
));
344 if (key
->data
== NULL
) {
345 PyErr_SetString(PyExc_MemoryError
, "Key memory allocation failed");
348 memcpy(key
->data
, PyString_AS_STRING(keyobj
),
349 PyString_GET_SIZE(keyobj
));
350 key
->flags
= DB_DBT_REALLOC
;
351 key
->size
= PyString_GET_SIZE(keyobj
);
354 else if (PyInt_Check(keyobj
)) {
355 /* verify access method type */
356 type
= _DB_get_type(self
);
359 if (type
== DB_BTREE
&& pflags
!= NULL
) {
360 /* if BTREE then an Integer key is allowed with the
361 * DB_SET_RECNO flag */
362 *pflags
|= DB_SET_RECNO
;
364 else if (type
!= DB_RECNO
&& type
!= DB_QUEUE
) {
367 "Integer keys only allowed for Recno and Queue DB's");
371 /* Make a key out of the requested recno, use allocated space so DB
372 * will be able to realloc room for the real key if needed. */
373 recno
= PyInt_AS_LONG(keyobj
);
374 key
->data
= malloc(sizeof(db_recno_t
));
375 if (key
->data
== NULL
) {
376 PyErr_SetString(PyExc_MemoryError
, "Key memory allocation failed");
379 key
->ulen
= key
->size
= sizeof(db_recno_t
);
380 memcpy(key
->data
, &recno
, sizeof(db_recno_t
));
381 key
->flags
= DB_DBT_REALLOC
;
384 PyErr_Format(PyExc_TypeError
,
385 "String or Integer object expected for key, %s found",
386 Py_TYPE(keyobj
)->tp_name
);
394 /* Add partial record access to an existing DBT data struct.
395 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
396 and the data storage/retrieval will be done using dlen and doff. */
397 static int add_partial_dbt(DBT
* d
, int dlen
, int doff
) {
398 /* if neither were set we do nothing (-1 is the default value) */
399 if ((dlen
== -1) && (doff
== -1)) {
403 if ((dlen
< 0) || (doff
< 0)) {
404 PyErr_SetString(PyExc_TypeError
, "dlen and doff must both be >= 0");
408 d
->flags
= d
->flags
| DB_DBT_PARTIAL
;
409 d
->dlen
= (unsigned int) dlen
;
410 d
->doff
= (unsigned int) doff
;
414 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
415 /* TODO: make this use the native libc strlcpy() when available (BSD) */
416 unsigned int our_strlcpy(char* dest
, const char* src
, unsigned int n
)
418 unsigned int srclen
, copylen
;
420 srclen
= strlen(src
);
423 copylen
= (srclen
> n
-1) ? n
-1 : srclen
;
424 /* populate dest[0] thru dest[copylen-1] */
425 memcpy(dest
, src
, copylen
);
426 /* guarantee null termination */
432 /* Callback used to save away more information about errors from the DB
434 static char _db_errmsg
[1024];
436 static void _db_errorCallback(const char* prefix
, char* msg
)
438 static void _db_errorCallback(const DB_ENV
*db_env
,
439 const char* prefix
, const char* msg
)
442 our_strlcpy(_db_errmsg
, msg
, sizeof(_db_errmsg
));
446 /* make a nice exception object to raise for errors. */
447 static int makeDBError(int err
)
449 char errTxt
[2048]; /* really big, just in case... */
450 PyObject
*errObj
= NULL
;
451 PyObject
*errTuple
= NULL
;
452 int exceptionRaised
= 0;
453 unsigned int bytes_left
;
456 case 0: /* successful, no error */ break;
460 #if INCOMPLETE_IS_WARNING
461 bytes_left
= our_strlcpy(errTxt
, db_strerror(err
), sizeof(errTxt
));
462 /* Ensure that bytes_left never goes negative */
463 if (_db_errmsg
[0] && bytes_left
< (sizeof(errTxt
) - 4)) {
464 bytes_left
= sizeof(errTxt
) - bytes_left
- 4 - 1;
465 assert(bytes_left
>= 0);
466 strcat(errTxt
, " -- ");
467 strncat(errTxt
, _db_errmsg
, bytes_left
);
470 exceptionRaised
= PyErr_Warn(PyExc_RuntimeWarning
, errTxt
);
472 #else /* do an exception instead */
473 errObj
= DBIncompleteError
;
476 #endif /* DBVER < 41 */
478 case DB_KEYEMPTY
: errObj
= DBKeyEmptyError
; break;
479 case DB_KEYEXIST
: errObj
= DBKeyExistError
; break;
480 case DB_LOCK_DEADLOCK
: errObj
= DBLockDeadlockError
; break;
481 case DB_LOCK_NOTGRANTED
: errObj
= DBLockNotGrantedError
; break;
482 case DB_NOTFOUND
: errObj
= DBNotFoundError
; break;
483 case DB_OLD_VERSION
: errObj
= DBOldVersionError
; break;
484 case DB_RUNRECOVERY
: errObj
= DBRunRecoveryError
; break;
485 case DB_VERIFY_BAD
: errObj
= DBVerifyBadError
; break;
486 case DB_NOSERVER
: errObj
= DBNoServerError
; break;
487 case DB_NOSERVER_HOME
: errObj
= DBNoServerHomeError
; break;
488 case DB_NOSERVER_ID
: errObj
= DBNoServerIDError
; break;
490 case DB_PAGE_NOTFOUND
: errObj
= DBPageNotFoundError
; break;
491 case DB_SECONDARY_BAD
: errObj
= DBSecondaryBadError
; break;
493 case DB_BUFFER_SMALL
: errObj
= DBNoMemoryError
; break;
496 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
497 case ENOMEM
: errObj
= PyExc_MemoryError
; break;
499 case EINVAL
: errObj
= DBInvalidArgError
; break;
500 case EACCES
: errObj
= DBAccessError
; break;
501 case ENOSPC
: errObj
= DBNoSpaceError
; break;
502 case EAGAIN
: errObj
= DBAgainError
; break;
503 case EBUSY
: errObj
= DBBusyError
; break;
504 case EEXIST
: errObj
= DBFileExistsError
; break;
505 case ENOENT
: errObj
= DBNoSuchFileError
; break;
506 case EPERM
: errObj
= DBPermissionsError
; break;
508 default: errObj
= DBError
; break;
511 if (errObj
!= NULL
) {
512 bytes_left
= our_strlcpy(errTxt
, db_strerror(err
), sizeof(errTxt
));
513 /* Ensure that bytes_left never goes negative */
514 if (_db_errmsg
[0] && bytes_left
< (sizeof(errTxt
) - 4)) {
515 bytes_left
= sizeof(errTxt
) - bytes_left
- 4 - 1;
516 assert(bytes_left
>= 0);
517 strcat(errTxt
, " -- ");
518 strncat(errTxt
, _db_errmsg
, bytes_left
);
522 errTuple
= Py_BuildValue("(is)", err
, errTxt
);
523 PyErr_SetObject(errObj
, errTuple
);
527 return ((errObj
!= NULL
) || exceptionRaised
);
532 /* set a type exception */
533 static void makeTypeError(char* expected
, PyObject
* found
)
535 PyErr_Format(PyExc_TypeError
, "Expected %s argument, %s found.",
536 expected
, Py_TYPE(found
)->tp_name
);
540 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
541 static int checkTxnObj(PyObject
* txnobj
, DB_TXN
** txn
)
543 if (txnobj
== Py_None
|| txnobj
== NULL
) {
547 if (DBTxnObject_Check(txnobj
)) {
548 *txn
= ((DBTxnObject
*)txnobj
)->txn
;
552 makeTypeError("DBTxn", txnobj
);
557 /* Delete a key from a database
558 Returns 0 on success, -1 on an error. */
559 static int _DB_delete(DBObject
* self
, DB_TXN
*txn
, DBT
*key
, int flags
)
563 MYDB_BEGIN_ALLOW_THREADS
;
564 err
= self
->db
->del(self
->db
, txn
, key
, 0);
565 MYDB_END_ALLOW_THREADS
;
566 if (makeDBError(err
)) {
574 /* Store a key into a database
575 Returns 0 on success, -1 on an error. */
576 static int _DB_put(DBObject
* self
, DB_TXN
*txn
, DBT
*key
, DBT
*data
, int flags
)
580 MYDB_BEGIN_ALLOW_THREADS
;
581 err
= self
->db
->put(self
->db
, txn
, key
, data
, flags
);
582 MYDB_END_ALLOW_THREADS
;
583 if (makeDBError(err
)) {
590 /* Get a key/data pair from a cursor */
591 static PyObject
* _DBCursor_get(DBCursorObject
* self
, int extra_flags
,
592 PyObject
*args
, PyObject
*kwargs
, char *format
)
595 PyObject
* retval
= NULL
;
600 static char* kwnames
[] = { "flags", "dlen", "doff", NULL
};
602 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, format
, kwnames
,
603 &flags
, &dlen
, &doff
))
606 CHECK_CURSOR_NOT_CLOSED(self
);
608 flags
|= extra_flags
;
611 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
612 /* Tell BerkeleyDB to malloc the return value (thread safe) */
613 data
.flags
= DB_DBT_MALLOC
;
614 key
.flags
= DB_DBT_MALLOC
;
616 if (!add_partial_dbt(&data
, dlen
, doff
))
619 MYDB_BEGIN_ALLOW_THREADS
;
620 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
);
621 MYDB_END_ALLOW_THREADS
;
623 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
624 && self
->mydb
->moduleFlags
.getReturnsNone
) {
628 else if (makeDBError(err
)) {
631 else { /* otherwise, success! */
633 /* if Recno or Queue, return the key as an Int */
634 switch (_DB_get_type(self
->mydb
)) {
641 retval
= Py_BuildValue("is#", *((db_recno_t
*)key
.data
),
642 data
.data
, data
.size
);
647 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
,
648 data
.data
, data
.size
);
660 /* add an integer to a dictionary using the given name as a key */
661 static void _addIntToDict(PyObject
* dict
, char *name
, int value
)
663 PyObject
* v
= PyInt_FromLong((long) value
);
664 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
670 /* The same, when the value is a time_t */
671 static void _addTimeTToDict(PyObject
* dict
, char *name
, time_t value
)
674 /* if the value fits in regular int, use that. */
675 #ifdef HAVE_LONG_LONG
676 if (sizeof(time_t) > sizeof(long))
677 v
= PyLong_FromLongLong((PY_LONG_LONG
) value
);
680 v
= PyInt_FromLong((long) value
);
681 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
688 /* add an db_seq_t to a dictionary using the given name as a key */
689 static void _addDb_seq_tToDict(PyObject
* dict
, char *name
, db_seq_t value
)
691 PyObject
* v
= PyLong_FromLongLong(value
);
692 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
701 /* --------------------------------------------------------------------- */
702 /* Allocators and deallocators */
705 newDBObject(DBEnvObject
* arg
, int flags
)
708 DB_ENV
* db_env
= NULL
;
711 self
= PyObject_New(DBObject
, &DB_Type
);
718 self
->myenvobj
= NULL
;
720 self
->associateCallback
= NULL
;
721 self
->btCompareCallback
= NULL
;
722 self
->primaryDBType
= 0;
724 self
->in_weakreflist
= NULL
;
726 /* keep a reference to our python DBEnv object */
729 self
->myenvobj
= arg
;
730 db_env
= arg
->db_env
;
734 self
->moduleFlags
= self
->myenvobj
->moduleFlags
;
736 self
->moduleFlags
.getReturnsNone
= DEFAULT_GET_RETURNS_NONE
;
737 self
->moduleFlags
.cursorSetReturnsNone
= DEFAULT_CURSOR_SET_RETURNS_NONE
;
739 MYDB_BEGIN_ALLOW_THREADS
;
740 err
= db_create(&self
->db
, db_env
, flags
);
741 if (self
->db
!= NULL
) {
742 self
->db
->set_errcall(self
->db
, _db_errorCallback
);
744 self
->db
->app_private
= (void*)self
;
747 MYDB_END_ALLOW_THREADS
;
748 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
749 * list so that a DBEnv can refuse to close without aborting any open
750 * DBTxns and closing any open DBs first. */
751 if (makeDBError(err
)) {
752 if (self
->myenvobj
) {
753 Py_DECREF(self
->myenvobj
);
754 self
->myenvobj
= NULL
;
764 DB_dealloc(DBObject
* self
)
766 if (self
->db
!= NULL
) {
767 /* avoid closing a DB when its DBEnv has been closed out from under
769 if (!self
->myenvobj
||
770 (self
->myenvobj
&& self
->myenvobj
->db_env
))
772 MYDB_BEGIN_ALLOW_THREADS
;
773 self
->db
->close(self
->db
, 0);
774 MYDB_END_ALLOW_THREADS
;
776 PyErr_Warn(PyExc_RuntimeWarning
,
777 "DB could not be closed in destructor: DBEnv already closed");
781 if (self
->in_weakreflist
!= NULL
) {
782 PyObject_ClearWeakRefs((PyObject
*) self
);
784 if (self
->myenvobj
) {
785 Py_DECREF(self
->myenvobj
);
786 self
->myenvobj
= NULL
;
789 if (self
->associateCallback
!= NULL
) {
790 Py_DECREF(self
->associateCallback
);
791 self
->associateCallback
= NULL
;
793 if (self
->btCompareCallback
!= NULL
) {
794 Py_DECREF(self
->btCompareCallback
);
795 self
->btCompareCallback
= NULL
;
802 static DBCursorObject
*
803 newDBCursorObject(DBC
* dbc
, DBObject
* db
)
805 DBCursorObject
* self
= PyObject_New(DBCursorObject
, &DBCursor_Type
);
811 self
->in_weakreflist
= NULL
;
812 Py_INCREF(self
->mydb
);
818 DBCursor_dealloc(DBCursorObject
* self
)
822 if (self
->in_weakreflist
!= NULL
) {
823 PyObject_ClearWeakRefs((PyObject
*) self
);
826 if (self
->dbc
!= NULL
) {
827 /* If the underlying database has been closed, we don't
828 need to do anything. If the environment has been closed
829 we need to leak, as BerkeleyDB will crash trying to access
830 the environment. There was an exception when the
831 user closed the environment even though there still was
833 if (self
->mydb
->db
&& self
->mydb
->myenvobj
&&
834 !self
->mydb
->myenvobj
->closed
)
835 /* test for: open db + no environment or non-closed environment */
836 if (self
->mydb
->db
&& (!self
->mydb
->myenvobj
|| (self
->mydb
->myenvobj
&&
837 !self
->mydb
->myenvobj
->closed
))) {
838 MYDB_BEGIN_ALLOW_THREADS
;
839 err
= self
->dbc
->c_close(self
->dbc
);
840 MYDB_END_ALLOW_THREADS
;
844 Py_XDECREF( self
->mydb
);
850 newDBEnvObject(int flags
)
853 DBEnvObject
* self
= PyObject_New(DBEnvObject
, &DBEnv_Type
);
859 self
->moduleFlags
.getReturnsNone
= DEFAULT_GET_RETURNS_NONE
;
860 self
->moduleFlags
.cursorSetReturnsNone
= DEFAULT_CURSOR_SET_RETURNS_NONE
;
861 self
->in_weakreflist
= NULL
;
863 MYDB_BEGIN_ALLOW_THREADS
;
864 err
= db_env_create(&self
->db_env
, flags
);
865 MYDB_END_ALLOW_THREADS
;
866 if (makeDBError(err
)) {
871 self
->db_env
->set_errcall(self
->db_env
, _db_errorCallback
);
878 DBEnv_dealloc(DBEnvObject
* self
)
880 if (self
->in_weakreflist
!= NULL
) {
881 PyObject_ClearWeakRefs((PyObject
*) self
);
884 if (self
->db_env
&& !self
->closed
) {
885 MYDB_BEGIN_ALLOW_THREADS
;
886 self
->db_env
->close(self
->db_env
, 0);
887 MYDB_END_ALLOW_THREADS
;
894 newDBTxnObject(DBEnvObject
* myenv
, DB_TXN
*parent
, int flags
)
897 DBTxnObject
* self
= PyObject_New(DBTxnObject
, &DBTxn_Type
);
901 self
->env
= (PyObject
*)myenv
;
902 self
->in_weakreflist
= NULL
;
904 MYDB_BEGIN_ALLOW_THREADS
;
906 err
= myenv
->db_env
->txn_begin(myenv
->db_env
, parent
, &(self
->txn
), flags
);
908 err
= txn_begin(myenv
->db_env
, parent
, &(self
->txn
), flags
);
910 MYDB_END_ALLOW_THREADS
;
911 if (makeDBError(err
)) {
912 Py_DECREF(self
->env
);
921 DBTxn_dealloc(DBTxnObject
* self
)
923 if (self
->in_weakreflist
!= NULL
) {
924 PyObject_ClearWeakRefs((PyObject
*) self
);
928 /* it hasn't been finalized, abort it! */
929 MYDB_BEGIN_ALLOW_THREADS
;
931 self
->txn
->abort(self
->txn
);
933 txn_abort(self
->txn
);
935 MYDB_END_ALLOW_THREADS
;
936 PyErr_Warn(PyExc_RuntimeWarning
,
937 "DBTxn aborted in destructor. No prior commit() or abort().");
940 Py_DECREF(self
->env
);
946 newDBLockObject(DBEnvObject
* myenv
, u_int32_t locker
, DBT
* obj
,
947 db_lockmode_t lock_mode
, int flags
)
950 DBLockObject
* self
= PyObject_New(DBLockObject
, &DBLock_Type
);
953 self
->in_weakreflist
= NULL
;
955 MYDB_BEGIN_ALLOW_THREADS
;
957 err
= myenv
->db_env
->lock_get(myenv
->db_env
, locker
, flags
, obj
, lock_mode
,
960 err
= lock_get(myenv
->db_env
, locker
, flags
, obj
, lock_mode
, &self
->lock
);
962 MYDB_END_ALLOW_THREADS
;
963 if (makeDBError(err
)) {
973 DBLock_dealloc(DBLockObject
* self
)
975 if (self
->in_weakreflist
!= NULL
) {
976 PyObject_ClearWeakRefs((PyObject
*) self
);
978 /* TODO: is this lock held? should we release it? */
985 static DBSequenceObject
*
986 newDBSequenceObject(DBObject
* mydb
, int flags
)
989 DBSequenceObject
* self
= PyObject_New(DBSequenceObject
, &DBSequence_Type
);
994 self
->in_weakreflist
= NULL
;
997 MYDB_BEGIN_ALLOW_THREADS
;
998 err
= db_sequence_create(&self
->sequence
, self
->mydb
->db
, flags
);
999 MYDB_END_ALLOW_THREADS
;
1000 if (makeDBError(err
)) {
1001 Py_DECREF(self
->mydb
);
1011 DBSequence_dealloc(DBSequenceObject
* self
)
1013 if (self
->in_weakreflist
!= NULL
) {
1014 PyObject_ClearWeakRefs((PyObject
*) self
);
1017 Py_DECREF(self
->mydb
);
1022 /* --------------------------------------------------------------------- */
1026 DB_append(DBObject
* self
, PyObject
* args
)
1028 PyObject
* txnobj
= NULL
;
1034 if (!PyArg_UnpackTuple(args
, "append", 1, 2, &dataobj
, &txnobj
))
1037 CHECK_DB_NOT_CLOSED(self
);
1039 /* make a dummy key out of a recno */
1043 key
.size
= sizeof(recno
);
1044 key
.ulen
= key
.size
;
1045 key
.flags
= DB_DBT_USERMEM
;
1047 if (!make_dbt(dataobj
, &data
)) return NULL
;
1048 if (!checkTxnObj(txnobj
, &txn
)) return NULL
;
1050 if (-1 == _DB_put(self
, txn
, &key
, &data
, DB_APPEND
))
1053 return PyInt_FromLong(recno
);
1060 _db_associateCallback(DB
* db
, const DBT
* priKey
, const DBT
* priData
,
1063 int retval
= DB_DONOTINDEX
;
1064 DBObject
* secondaryDB
= (DBObject
*)db
->app_private
;
1065 PyObject
* callback
= secondaryDB
->associateCallback
;
1066 int type
= secondaryDB
->primaryDBType
;
1068 PyObject
* result
= NULL
;
1071 if (callback
!= NULL
) {
1072 MYDB_BEGIN_BLOCK_THREADS
;
1074 if (type
== DB_RECNO
|| type
== DB_QUEUE
)
1075 args
= Py_BuildValue("(ls#)", *((db_recno_t
*)priKey
->data
),
1076 priData
->data
, priData
->size
);
1078 args
= Py_BuildValue("(s#s#)", priKey
->data
, priKey
->size
,
1079 priData
->data
, priData
->size
);
1081 result
= PyEval_CallObject(callback
, args
);
1083 if (args
== NULL
|| result
== NULL
) {
1086 else if (result
== Py_None
) {
1087 retval
= DB_DONOTINDEX
;
1089 else if (PyInt_Check(result
)) {
1090 retval
= PyInt_AsLong(result
);
1092 else if (PyString_Check(result
)) {
1097 PyString_AsStringAndSize(result
, &data
, &size
);
1098 secKey
->flags
= DB_DBT_APPMALLOC
; /* DB will free */
1099 secKey
->data
= malloc(size
); /* TODO, check this */
1101 memcpy(secKey
->data
, data
, size
);
1102 secKey
->size
= size
;
1106 PyErr_SetString(PyExc_MemoryError
,
1107 "malloc failed in _db_associateCallback");
1114 "DB associate callback should return DB_DONOTINDEX or string.");
1121 MYDB_END_BLOCK_THREADS
;
1128 DB_associate(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1131 DBObject
* secondaryDB
;
1134 PyObject
*txnobj
= NULL
;
1136 static char* kwnames
[] = {"secondaryDB", "callback", "flags", "txn",
1139 static char* kwnames
[] = {"secondaryDB", "callback", "flags", NULL
};
1143 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|iO:associate", kwnames
,
1144 &secondaryDB
, &callback
, &flags
,
1147 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|i:associate", kwnames
,
1148 &secondaryDB
, &callback
, &flags
)) {
1154 if (!checkTxnObj(txnobj
, &txn
)) return NULL
;
1157 CHECK_DB_NOT_CLOSED(self
);
1158 if (!DBObject_Check(secondaryDB
)) {
1159 makeTypeError("DB", (PyObject
*)secondaryDB
);
1162 CHECK_DB_NOT_CLOSED(secondaryDB
);
1163 if (callback
== Py_None
) {
1166 else if (!PyCallable_Check(callback
)) {
1167 makeTypeError("Callable", callback
);
1171 /* Save a reference to the callback in the secondary DB. */
1172 Py_XDECREF(secondaryDB
->associateCallback
);
1173 Py_XINCREF(callback
);
1174 secondaryDB
->associateCallback
= callback
;
1175 secondaryDB
->primaryDBType
= _DB_get_type(self
);
1177 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1178 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1179 * The global interepreter lock is not initialized until the first
1180 * thread is created using thread.start_new_thread() or fork() is
1181 * called. that would cause the ALLOW_THREADS here to segfault due
1182 * to a null pointer reference if no threads or child processes
1183 * have been created. This works around that and is a no-op if
1184 * threads have already been initialized.
1185 * (see pybsddb-users mailing list post on 2002-08-07)
1188 PyEval_InitThreads();
1190 MYDB_BEGIN_ALLOW_THREADS
;
1192 err
= self
->db
->associate(self
->db
,
1195 _db_associateCallback
,
1198 err
= self
->db
->associate(self
->db
,
1200 _db_associateCallback
,
1203 MYDB_END_ALLOW_THREADS
;
1206 Py_XDECREF(secondaryDB
->associateCallback
);
1207 secondaryDB
->associateCallback
= NULL
;
1208 secondaryDB
->primaryDBType
= 0;
1220 DB_close(DBObject
* self
, PyObject
* args
)
1223 if (!PyArg_ParseTuple(args
,"|i:close", &flags
))
1225 if (self
->db
!= NULL
) {
1227 CHECK_ENV_NOT_CLOSED(self
->myenvobj
);
1228 err
= self
->db
->close(self
->db
, flags
);
1237 _DB_consume(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
, int consume_flag
)
1239 int err
, flags
=0, type
;
1240 PyObject
* txnobj
= NULL
;
1241 PyObject
* retval
= NULL
;
1244 static char* kwnames
[] = { "txn", "flags", NULL
};
1246 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:consume", kwnames
,
1250 CHECK_DB_NOT_CLOSED(self
);
1251 type
= _DB_get_type(self
);
1254 if (type
!= DB_QUEUE
) {
1255 PyErr_SetString(PyExc_TypeError
,
1256 "Consume methods only allowed for Queue DB's");
1259 if (!checkTxnObj(txnobj
, &txn
))
1264 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1265 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1266 data
.flags
= DB_DBT_MALLOC
;
1267 key
.flags
= DB_DBT_MALLOC
;
1270 MYDB_BEGIN_ALLOW_THREADS
;
1271 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
|consume_flag
);
1272 MYDB_END_ALLOW_THREADS
;
1274 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1275 && self
->moduleFlags
.getReturnsNone
) {
1281 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
, data
.data
,
1292 DB_consume(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
, int consume_flag
)
1294 return _DB_consume(self
, args
, kwargs
, DB_CONSUME
);
1298 DB_consume_wait(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
,
1301 return _DB_consume(self
, args
, kwargs
, DB_CONSUME_WAIT
);
1306 DB_cursor(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1310 PyObject
* txnobj
= NULL
;
1312 static char* kwnames
[] = { "txn", "flags", NULL
};
1314 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:cursor", kwnames
,
1317 CHECK_DB_NOT_CLOSED(self
);
1318 if (!checkTxnObj(txnobj
, &txn
))
1321 MYDB_BEGIN_ALLOW_THREADS
;
1322 err
= self
->db
->cursor(self
->db
, txn
, &dbc
, flags
);
1323 MYDB_END_ALLOW_THREADS
;
1325 return (PyObject
*) newDBCursorObject(dbc
, self
);
1330 DB_delete(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1332 PyObject
* txnobj
= NULL
;
1337 static char* kwnames
[] = { "key", "txn", "flags", NULL
};
1339 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oi:delete", kwnames
,
1340 &keyobj
, &txnobj
, &flags
))
1342 CHECK_DB_NOT_CLOSED(self
);
1343 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
1345 if (!checkTxnObj(txnobj
, &txn
)) {
1350 if (-1 == _DB_delete(self
, txn
, &key
, 0)) {
1361 DB_fd(DBObject
* self
, PyObject
* args
)
1365 if (!PyArg_ParseTuple(args
,":fd"))
1367 CHECK_DB_NOT_CLOSED(self
);
1369 MYDB_BEGIN_ALLOW_THREADS
;
1370 err
= self
->db
->fd(self
->db
, &the_fd
);
1371 MYDB_END_ALLOW_THREADS
;
1373 return PyInt_FromLong(the_fd
);
1378 DB_get(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1381 PyObject
* txnobj
= NULL
;
1383 PyObject
* dfltobj
= NULL
;
1384 PyObject
* retval
= NULL
;
1389 static char* kwnames
[] = {"key", "default", "txn", "flags", "dlen",
1392 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|OOiii:get", kwnames
,
1393 &keyobj
, &dfltobj
, &txnobj
, &flags
, &dlen
,
1397 CHECK_DB_NOT_CLOSED(self
);
1398 if (!make_key_dbt(self
, keyobj
, &key
, &flags
))
1400 if (!checkTxnObj(txnobj
, &txn
)) {
1406 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1407 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1408 data
.flags
= DB_DBT_MALLOC
;
1410 if (!add_partial_dbt(&data
, dlen
, doff
)) {
1415 MYDB_BEGIN_ALLOW_THREADS
;
1416 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
);
1417 MYDB_END_ALLOW_THREADS
;
1419 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) && (dfltobj
!= NULL
)) {
1424 else if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1425 && self
->moduleFlags
.getReturnsNone
) {
1431 if (flags
& DB_SET_RECNO
) /* return both key and data */
1432 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
, data
.data
,
1434 else /* return just the data */
1435 retval
= PyString_FromStringAndSize((char*)data
.data
, data
.size
);
1446 DB_pget(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1449 PyObject
* txnobj
= NULL
;
1451 PyObject
* dfltobj
= NULL
;
1452 PyObject
* retval
= NULL
;
1455 DBT key
, pkey
, data
;
1457 static char* kwnames
[] = {"key", "default", "txn", "flags", "dlen",
1460 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|OOiii:pget", kwnames
,
1461 &keyobj
, &dfltobj
, &txnobj
, &flags
, &dlen
,
1465 CHECK_DB_NOT_CLOSED(self
);
1466 if (!make_key_dbt(self
, keyobj
, &key
, &flags
))
1468 if (!checkTxnObj(txnobj
, &txn
)) {
1474 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1475 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1476 data
.flags
= DB_DBT_MALLOC
;
1478 if (!add_partial_dbt(&data
, dlen
, doff
)) {
1484 pkey
.flags
= DB_DBT_MALLOC
;
1486 MYDB_BEGIN_ALLOW_THREADS
;
1487 err
= self
->db
->pget(self
->db
, txn
, &key
, &pkey
, &data
, flags
);
1488 MYDB_END_ALLOW_THREADS
;
1490 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) && (dfltobj
!= NULL
)) {
1495 else if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1496 && self
->moduleFlags
.getReturnsNone
) {
1504 dataObj
= PyString_FromStringAndSize(data
.data
, data
.size
);
1506 if (self
->primaryDBType
== DB_RECNO
||
1507 self
->primaryDBType
== DB_QUEUE
)
1508 pkeyObj
= PyInt_FromLong(*(int *)pkey
.data
);
1510 pkeyObj
= PyString_FromStringAndSize(pkey
.data
, pkey
.size
);
1512 if (flags
& DB_SET_RECNO
) /* return key , pkey and data */
1515 int type
= _DB_get_type(self
);
1516 if (type
== DB_RECNO
|| type
== DB_QUEUE
)
1517 keyObj
= PyInt_FromLong(*(int *)key
.data
);
1519 keyObj
= PyString_FromStringAndSize(key
.data
, key
.size
);
1520 #if (PY_VERSION_HEX >= 0x02040000)
1521 retval
= PyTuple_Pack(3, keyObj
, pkeyObj
, dataObj
);
1523 retval
= Py_BuildValue("OOO", keyObj
, pkeyObj
, dataObj
);
1527 else /* return just the pkey and data */
1529 #if (PY_VERSION_HEX >= 0x02040000)
1530 retval
= PyTuple_Pack(2, pkeyObj
, dataObj
);
1532 retval
= Py_BuildValue("OO", pkeyObj
, dataObj
);
1548 /* Return size of entry */
1550 DB_get_size(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1553 PyObject
* txnobj
= NULL
;
1555 PyObject
* retval
= NULL
;
1558 static char* kwnames
[] = { "key", "txn", NULL
};
1560 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|O:get_size", kwnames
,
1563 CHECK_DB_NOT_CLOSED(self
);
1564 if (!make_key_dbt(self
, keyobj
, &key
, &flags
))
1566 if (!checkTxnObj(txnobj
, &txn
)) {
1572 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1573 thus getting the record size. */
1574 data
.flags
= DB_DBT_USERMEM
;
1576 MYDB_BEGIN_ALLOW_THREADS
;
1577 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
);
1578 MYDB_END_ALLOW_THREADS
;
1579 if (err
== DB_BUFFER_SMALL
) {
1580 retval
= PyInt_FromLong((long)data
.size
);
1592 DB_get_both(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1595 PyObject
* txnobj
= NULL
;
1598 PyObject
* retval
= NULL
;
1602 static char* kwnames
[] = { "key", "data", "txn", "flags", NULL
};
1605 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|Oi:get_both", kwnames
,
1606 &keyobj
, &dataobj
, &txnobj
, &flags
))
1609 CHECK_DB_NOT_CLOSED(self
);
1610 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
1612 if ( !make_dbt(dataobj
, &data
) ||
1613 !checkTxnObj(txnobj
, &txn
) )
1619 flags
|= DB_GET_BOTH
;
1620 orig_data
= data
.data
;
1622 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1623 /* Tell BerkeleyDB to malloc the return value (thread safe) */
1624 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1625 data
.flags
= DB_DBT_MALLOC
;
1628 MYDB_BEGIN_ALLOW_THREADS
;
1629 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
);
1630 MYDB_END_ALLOW_THREADS
;
1632 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1633 && self
->moduleFlags
.getReturnsNone
) {
1639 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1640 retval
= PyString_FromStringAndSize((char*)data
.data
, data
.size
);
1642 /* Even though the flags require DB_DBT_MALLOC, data is not always
1643 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1644 if (data
.data
!= orig_data
)
1655 DB_get_byteswapped(DBObject
* self
, PyObject
* args
)
1662 if (!PyArg_ParseTuple(args
,":get_byteswapped"))
1664 CHECK_DB_NOT_CLOSED(self
);
1667 MYDB_BEGIN_ALLOW_THREADS
;
1668 err
= self
->db
->get_byteswapped(self
->db
, &retval
);
1669 MYDB_END_ALLOW_THREADS
;
1672 MYDB_BEGIN_ALLOW_THREADS
;
1673 retval
= self
->db
->get_byteswapped(self
->db
);
1674 MYDB_END_ALLOW_THREADS
;
1676 return PyInt_FromLong(retval
);
1681 DB_get_type(DBObject
* self
, PyObject
* args
)
1685 if (!PyArg_ParseTuple(args
,":get_type"))
1687 CHECK_DB_NOT_CLOSED(self
);
1689 type
= _DB_get_type(self
);
1692 return PyInt_FromLong(type
);
1697 DB_join(DBObject
* self
, PyObject
* args
)
1701 PyObject
* cursorsObj
;
1705 if (!PyArg_ParseTuple(args
,"O|i:join", &cursorsObj
, &flags
))
1708 CHECK_DB_NOT_CLOSED(self
);
1710 if (!PySequence_Check(cursorsObj
)) {
1711 PyErr_SetString(PyExc_TypeError
,
1712 "Sequence of DBCursor objects expected");
1716 length
= PyObject_Length(cursorsObj
);
1717 cursors
= malloc((length
+1) * sizeof(DBC
*));
1723 cursors
[length
] = NULL
;
1724 for (x
=0; x
<length
; x
++) {
1725 PyObject
* item
= PySequence_GetItem(cursorsObj
, x
);
1730 if (!DBCursorObject_Check(item
)) {
1731 PyErr_SetString(PyExc_TypeError
,
1732 "Sequence of DBCursor objects expected");
1736 cursors
[x
] = ((DBCursorObject
*)item
)->dbc
;
1740 MYDB_BEGIN_ALLOW_THREADS
;
1741 err
= self
->db
->join(self
->db
, cursors
, &dbc
, flags
);
1742 MYDB_END_ALLOW_THREADS
;
1746 /* FIXME: this is a buggy interface. The returned cursor
1747 contains internal references to the passed in cursors
1748 but does not hold python references to them or prevent
1749 them from being closed prematurely. This can cause
1750 python to crash when things are done in the wrong order. */
1751 return (PyObject
*) newDBCursorObject(dbc
, self
);
1756 DB_key_range(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1759 PyObject
* txnobj
= NULL
;
1764 static char* kwnames
[] = { "key", "txn", "flags", NULL
};
1766 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oi:key_range", kwnames
,
1767 &keyobj
, &txnobj
, &flags
))
1769 CHECK_DB_NOT_CLOSED(self
);
1770 if (!make_dbt(keyobj
, &key
))
1771 /* BTree only, don't need to allow for an int key */
1773 if (!checkTxnObj(txnobj
, &txn
))
1776 MYDB_BEGIN_ALLOW_THREADS
;
1777 err
= self
->db
->key_range(self
->db
, txn
, &key
, &range
, flags
);
1778 MYDB_END_ALLOW_THREADS
;
1781 return Py_BuildValue("ddd", range
.less
, range
.equal
, range
.greater
);
1786 DB_open(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1788 int err
, type
= DB_UNKNOWN
, flags
=0, mode
=0660;
1789 char* filename
= NULL
;
1790 char* dbname
= NULL
;
1792 PyObject
*txnobj
= NULL
;
1795 static char* kwnames
[] = {
1796 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL
};
1797 /* without dbname */
1798 static char* kwnames_basic
[] = {
1799 "filename", "dbtype", "flags", "mode", "txn", NULL
};
1802 static char* kwnames
[] = {
1803 "filename", "dbname", "dbtype", "flags", "mode", NULL
};
1804 /* without dbname */
1805 static char* kwnames_basic
[] = {
1806 "filename", "dbtype", "flags", "mode", NULL
};
1810 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "z|ziiiO:open", kwnames
,
1811 &filename
, &dbname
, &type
, &flags
, &mode
,
1814 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "z|ziii:open", kwnames
,
1815 &filename
, &dbname
, &type
, &flags
,
1820 type
= DB_UNKNOWN
; flags
= 0; mode
= 0660;
1821 filename
= NULL
; dbname
= NULL
;
1823 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,"z|iiiO:open",
1825 &filename
, &type
, &flags
, &mode
,
1829 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,"z|iii:open",
1831 &filename
, &type
, &flags
, &mode
))
1837 if (!checkTxnObj(txnobj
, &txn
)) return NULL
;
1840 if (NULL
== self
->db
) {
1841 PyObject
*t
= Py_BuildValue("(is)", 0,
1842 "Cannot call open() twice for DB object");
1843 PyErr_SetObject(DBError
, t
);
1848 MYDB_BEGIN_ALLOW_THREADS
;
1850 err
= self
->db
->open(self
->db
, txn
, filename
, dbname
, type
, flags
, mode
);
1852 err
= self
->db
->open(self
->db
, filename
, dbname
, type
, flags
, mode
);
1854 MYDB_END_ALLOW_THREADS
;
1855 if (makeDBError(err
)) {
1856 self
->db
->close(self
->db
, 0);
1862 self
->db
->get_flags(self
->db
, &self
->setflags
);
1865 self
->flags
= flags
;
1871 DB_put(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1874 PyObject
* txnobj
= NULL
;
1877 PyObject
* keyobj
, *dataobj
, *retval
;
1880 static char* kwnames
[] = { "key", "data", "txn", "flags", "dlen",
1883 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|Oiii:put", kwnames
,
1884 &keyobj
, &dataobj
, &txnobj
, &flags
, &dlen
, &doff
))
1887 CHECK_DB_NOT_CLOSED(self
);
1888 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
1890 if ( !make_dbt(dataobj
, &data
) ||
1891 !add_partial_dbt(&data
, dlen
, doff
) ||
1892 !checkTxnObj(txnobj
, &txn
) )
1898 if (-1 == _DB_put(self
, txn
, &key
, &data
, flags
)) {
1903 if (flags
& DB_APPEND
)
1904 retval
= PyInt_FromLong(*((db_recno_t
*)key
.data
));
1916 DB_remove(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1919 char* database
= NULL
;
1921 static char* kwnames
[] = { "filename", "dbname", "flags", NULL
};
1923 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zi:remove", kwnames
,
1924 &filename
, &database
, &flags
))
1926 CHECK_DB_NOT_CLOSED(self
);
1928 err
= self
->db
->remove(self
->db
, filename
, database
, flags
);
1937 DB_rename(DBObject
* self
, PyObject
* args
)
1944 if (!PyArg_ParseTuple(args
, "sss|i:rename", &filename
, &database
, &newname
,
1947 CHECK_DB_NOT_CLOSED(self
);
1949 MYDB_BEGIN_ALLOW_THREADS
;
1950 err
= self
->db
->rename(self
->db
, filename
, database
, newname
, flags
);
1951 MYDB_END_ALLOW_THREADS
;
1958 DB_set_bt_minkey(DBObject
* self
, PyObject
* args
)
1962 if (!PyArg_ParseTuple(args
,"i:set_bt_minkey", &minkey
))
1964 CHECK_DB_NOT_CLOSED(self
);
1966 MYDB_BEGIN_ALLOW_THREADS
;
1967 err
= self
->db
->set_bt_minkey(self
->db
, minkey
);
1968 MYDB_END_ALLOW_THREADS
;
1975 _default_cmp(const DBT
*leftKey
,
1976 const DBT
*rightKey
)
1979 int lsize
= leftKey
->size
, rsize
= rightKey
->size
;
1981 res
= memcmp(leftKey
->data
, rightKey
->data
,
1982 lsize
< rsize
? lsize
: rsize
);
1985 if (lsize
< rsize
) {
1988 else if (lsize
> rsize
) {
1996 _db_compareCallback(DB
* db
,
1998 const DBT
*rightKey
)
2002 PyObject
*result
= NULL
;
2003 DBObject
*self
= (DBObject
*)db
->app_private
;
2005 if (self
== NULL
|| self
->btCompareCallback
== NULL
) {
2006 MYDB_BEGIN_BLOCK_THREADS
;
2007 PyErr_SetString(PyExc_TypeError
,
2009 ? "DB_bt_compare db is NULL."
2010 : "DB_bt_compare callback is NULL."));
2011 /* we're in a callback within the DB code, we can't raise */
2013 res
= _default_cmp(leftKey
, rightKey
);
2014 MYDB_END_BLOCK_THREADS
;
2016 MYDB_BEGIN_BLOCK_THREADS
;
2018 args
= Py_BuildValue("s#s#", leftKey
->data
, leftKey
->size
,
2019 rightKey
->data
, rightKey
->size
);
2021 /* XXX(twouters) I highly doubt this INCREF is correct */
2023 result
= PyEval_CallObject(self
->btCompareCallback
, args
);
2025 if (args
== NULL
|| result
== NULL
) {
2026 /* we're in a callback within the DB code, we can't raise */
2028 res
= _default_cmp(leftKey
, rightKey
);
2029 } else if (PyInt_Check(result
)) {
2030 res
= PyInt_AsLong(result
);
2032 PyErr_SetString(PyExc_TypeError
,
2033 "DB_bt_compare callback MUST return an int.");
2034 /* we're in a callback within the DB code, we can't raise */
2036 res
= _default_cmp(leftKey
, rightKey
);
2042 MYDB_END_BLOCK_THREADS
;
2048 DB_set_bt_compare(DBObject
* self
, PyObject
* args
)
2051 PyObject
*comparator
;
2052 PyObject
*tuple
, *result
;
2054 if (!PyArg_ParseTuple(args
, "O:set_bt_compare", &comparator
))
2057 CHECK_DB_NOT_CLOSED(self
);
2059 if (!PyCallable_Check(comparator
)) {
2060 makeTypeError("Callable", comparator
);
2065 * Perform a test call of the comparator function with two empty
2066 * string objects here. verify that it returns an int (0).
2069 tuple
= Py_BuildValue("(ss)", "", "");
2070 result
= PyEval_CallObject(comparator
, tuple
);
2074 if (!PyInt_Check(result
)) {
2075 PyErr_SetString(PyExc_TypeError
,
2076 "callback MUST return an int");
2078 } else if (PyInt_AsLong(result
) != 0) {
2079 PyErr_SetString(PyExc_TypeError
,
2080 "callback failed to return 0 on two empty strings");
2085 /* We don't accept multiple set_bt_compare operations, in order to
2086 * simplify the code. This would have no real use, as one cannot
2087 * change the function once the db is opened anyway */
2088 if (self
->btCompareCallback
!= NULL
) {
2089 PyErr_SetString(PyExc_RuntimeError
, "set_bt_compare() cannot be called more than once");
2093 Py_INCREF(comparator
);
2094 self
->btCompareCallback
= comparator
;
2096 /* This is to workaround a problem with un-initialized threads (see
2097 comment in DB_associate) */
2099 PyEval_InitThreads();
2102 err
= self
->db
->set_bt_compare(self
->db
, _db_compareCallback
);
2105 /* restore the old state in case of error */
2106 Py_DECREF(comparator
);
2107 self
->btCompareCallback
= NULL
;
2113 #endif /* DBVER >= 33 */
2117 DB_set_cachesize(DBObject
* self
, PyObject
* args
)
2120 int gbytes
= 0, bytes
= 0, ncache
= 0;
2122 if (!PyArg_ParseTuple(args
,"ii|i:set_cachesize",
2123 &gbytes
,&bytes
,&ncache
))
2125 CHECK_DB_NOT_CLOSED(self
);
2127 MYDB_BEGIN_ALLOW_THREADS
;
2128 err
= self
->db
->set_cachesize(self
->db
, gbytes
, bytes
, ncache
);
2129 MYDB_END_ALLOW_THREADS
;
2136 DB_set_flags(DBObject
* self
, PyObject
* args
)
2140 if (!PyArg_ParseTuple(args
,"i:set_flags", &flags
))
2142 CHECK_DB_NOT_CLOSED(self
);
2144 MYDB_BEGIN_ALLOW_THREADS
;
2145 err
= self
->db
->set_flags(self
->db
, flags
);
2146 MYDB_END_ALLOW_THREADS
;
2149 self
->setflags
|= flags
;
2155 DB_set_h_ffactor(DBObject
* self
, PyObject
* args
)
2159 if (!PyArg_ParseTuple(args
,"i:set_h_ffactor", &ffactor
))
2161 CHECK_DB_NOT_CLOSED(self
);
2163 MYDB_BEGIN_ALLOW_THREADS
;
2164 err
= self
->db
->set_h_ffactor(self
->db
, ffactor
);
2165 MYDB_END_ALLOW_THREADS
;
2172 DB_set_h_nelem(DBObject
* self
, PyObject
* args
)
2176 if (!PyArg_ParseTuple(args
,"i:set_h_nelem", &nelem
))
2178 CHECK_DB_NOT_CLOSED(self
);
2180 MYDB_BEGIN_ALLOW_THREADS
;
2181 err
= self
->db
->set_h_nelem(self
->db
, nelem
);
2182 MYDB_END_ALLOW_THREADS
;
2189 DB_set_lorder(DBObject
* self
, PyObject
* args
)
2193 if (!PyArg_ParseTuple(args
,"i:set_lorder", &lorder
))
2195 CHECK_DB_NOT_CLOSED(self
);
2197 MYDB_BEGIN_ALLOW_THREADS
;
2198 err
= self
->db
->set_lorder(self
->db
, lorder
);
2199 MYDB_END_ALLOW_THREADS
;
2206 DB_set_pagesize(DBObject
* self
, PyObject
* args
)
2210 if (!PyArg_ParseTuple(args
,"i:set_pagesize", &pagesize
))
2212 CHECK_DB_NOT_CLOSED(self
);
2214 MYDB_BEGIN_ALLOW_THREADS
;
2215 err
= self
->db
->set_pagesize(self
->db
, pagesize
);
2216 MYDB_END_ALLOW_THREADS
;
2223 DB_set_re_delim(DBObject
* self
, PyObject
* args
)
2228 if (!PyArg_ParseTuple(args
,"b:set_re_delim", &delim
)) {
2230 if (!PyArg_ParseTuple(args
,"c:set_re_delim", &delim
))
2234 CHECK_DB_NOT_CLOSED(self
);
2236 MYDB_BEGIN_ALLOW_THREADS
;
2237 err
= self
->db
->set_re_delim(self
->db
, delim
);
2238 MYDB_END_ALLOW_THREADS
;
2244 DB_set_re_len(DBObject
* self
, PyObject
* args
)
2248 if (!PyArg_ParseTuple(args
,"i:set_re_len", &len
))
2250 CHECK_DB_NOT_CLOSED(self
);
2252 MYDB_BEGIN_ALLOW_THREADS
;
2253 err
= self
->db
->set_re_len(self
->db
, len
);
2254 MYDB_END_ALLOW_THREADS
;
2261 DB_set_re_pad(DBObject
* self
, PyObject
* args
)
2266 if (!PyArg_ParseTuple(args
,"b:set_re_pad", &pad
)) {
2268 if (!PyArg_ParseTuple(args
,"c:set_re_pad", &pad
))
2271 CHECK_DB_NOT_CLOSED(self
);
2273 MYDB_BEGIN_ALLOW_THREADS
;
2274 err
= self
->db
->set_re_pad(self
->db
, pad
);
2275 MYDB_END_ALLOW_THREADS
;
2282 DB_set_re_source(DBObject
* self
, PyObject
* args
)
2287 if (!PyArg_ParseTuple(args
,"s:set_re_source", &re_source
))
2289 CHECK_DB_NOT_CLOSED(self
);
2291 MYDB_BEGIN_ALLOW_THREADS
;
2292 err
= self
->db
->set_re_source(self
->db
, re_source
);
2293 MYDB_END_ALLOW_THREADS
;
2300 DB_set_q_extentsize(DBObject
* self
, PyObject
* args
)
2305 if (!PyArg_ParseTuple(args
,"i:set_q_extentsize", &extentsize
))
2307 CHECK_DB_NOT_CLOSED(self
);
2309 MYDB_BEGIN_ALLOW_THREADS
;
2310 err
= self
->db
->set_q_extentsize(self
->db
, extentsize
);
2311 MYDB_END_ALLOW_THREADS
;
2317 DB_stat(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2319 int err
, flags
= 0, type
;
2323 PyObject
* txnobj
= NULL
;
2325 static char* kwnames
[] = { "flags", "txn", NULL
};
2327 static char* kwnames
[] = { "flags", NULL
};
2331 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|iO:stat", kwnames
,
2334 if (!checkTxnObj(txnobj
, &txn
))
2337 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:stat", kwnames
, &flags
))
2340 CHECK_DB_NOT_CLOSED(self
);
2342 MYDB_BEGIN_ALLOW_THREADS
;
2344 err
= self
->db
->stat(self
->db
, txn
, &sp
, flags
);
2346 err
= self
->db
->stat(self
->db
, &sp
, flags
);
2348 err
= self
->db
->stat(self
->db
, &sp
, NULL
, flags
);
2350 MYDB_END_ALLOW_THREADS
;
2355 /* Turn the stat structure into a dictionary */
2356 type
= _DB_get_type(self
);
2357 if ((type
== -1) || ((d
= PyDict_New()) == NULL
)) {
2362 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2363 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2364 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2368 MAKE_HASH_ENTRY(magic
);
2369 MAKE_HASH_ENTRY(version
);
2370 MAKE_HASH_ENTRY(nkeys
);
2371 MAKE_HASH_ENTRY(ndata
);
2372 MAKE_HASH_ENTRY(pagesize
);
2374 MAKE_HASH_ENTRY(nelem
);
2376 MAKE_HASH_ENTRY(ffactor
);
2377 MAKE_HASH_ENTRY(buckets
);
2378 MAKE_HASH_ENTRY(free
);
2379 MAKE_HASH_ENTRY(bfree
);
2380 MAKE_HASH_ENTRY(bigpages
);
2381 MAKE_HASH_ENTRY(big_bfree
);
2382 MAKE_HASH_ENTRY(overflows
);
2383 MAKE_HASH_ENTRY(ovfl_free
);
2384 MAKE_HASH_ENTRY(dup
);
2385 MAKE_HASH_ENTRY(dup_free
);
2390 MAKE_BT_ENTRY(magic
);
2391 MAKE_BT_ENTRY(version
);
2392 MAKE_BT_ENTRY(nkeys
);
2393 MAKE_BT_ENTRY(ndata
);
2394 MAKE_BT_ENTRY(pagesize
);
2395 MAKE_BT_ENTRY(minkey
);
2396 MAKE_BT_ENTRY(re_len
);
2397 MAKE_BT_ENTRY(re_pad
);
2398 MAKE_BT_ENTRY(levels
);
2399 MAKE_BT_ENTRY(int_pg
);
2400 MAKE_BT_ENTRY(leaf_pg
);
2401 MAKE_BT_ENTRY(dup_pg
);
2402 MAKE_BT_ENTRY(over_pg
);
2403 MAKE_BT_ENTRY(free
);
2404 MAKE_BT_ENTRY(int_pgfree
);
2405 MAKE_BT_ENTRY(leaf_pgfree
);
2406 MAKE_BT_ENTRY(dup_pgfree
);
2407 MAKE_BT_ENTRY(over_pgfree
);
2411 MAKE_QUEUE_ENTRY(magic
);
2412 MAKE_QUEUE_ENTRY(version
);
2413 MAKE_QUEUE_ENTRY(nkeys
);
2414 MAKE_QUEUE_ENTRY(ndata
);
2415 MAKE_QUEUE_ENTRY(pagesize
);
2416 MAKE_QUEUE_ENTRY(pages
);
2417 MAKE_QUEUE_ENTRY(re_len
);
2418 MAKE_QUEUE_ENTRY(re_pad
);
2419 MAKE_QUEUE_ENTRY(pgfree
);
2421 MAKE_QUEUE_ENTRY(start
);
2423 MAKE_QUEUE_ENTRY(first_recno
);
2424 MAKE_QUEUE_ENTRY(cur_recno
);
2428 PyErr_SetString(PyExc_TypeError
, "Unknown DB type, unable to stat");
2433 #undef MAKE_HASH_ENTRY
2434 #undef MAKE_BT_ENTRY
2435 #undef MAKE_QUEUE_ENTRY
2442 DB_sync(DBObject
* self
, PyObject
* args
)
2447 if (!PyArg_ParseTuple(args
,"|i:sync", &flags
))
2449 CHECK_DB_NOT_CLOSED(self
);
2451 MYDB_BEGIN_ALLOW_THREADS
;
2452 err
= self
->db
->sync(self
->db
, flags
);
2453 MYDB_END_ALLOW_THREADS
;
2461 DB_truncate(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2465 PyObject
* txnobj
= NULL
;
2467 static char* kwnames
[] = { "txn", "flags", NULL
};
2469 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:cursor", kwnames
,
2472 CHECK_DB_NOT_CLOSED(self
);
2473 if (!checkTxnObj(txnobj
, &txn
))
2476 MYDB_BEGIN_ALLOW_THREADS
;
2477 err
= self
->db
->truncate(self
->db
, txn
, &count
, flags
);
2478 MYDB_END_ALLOW_THREADS
;
2480 return PyInt_FromLong(count
);
2486 DB_upgrade(DBObject
* self
, PyObject
* args
)
2491 if (!PyArg_ParseTuple(args
,"s|i:upgrade", &filename
, &flags
))
2493 CHECK_DB_NOT_CLOSED(self
);
2495 MYDB_BEGIN_ALLOW_THREADS
;
2496 err
= self
->db
->upgrade(self
->db
, filename
, flags
);
2497 MYDB_END_ALLOW_THREADS
;
2504 DB_verify(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2509 char* outFileName
=NULL
;
2511 static char* kwnames
[] = { "filename", "dbname", "outfile", "flags",
2514 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zzi:verify", kwnames
,
2515 &fileName
, &dbName
, &outFileName
, &flags
))
2518 CHECK_DB_NOT_CLOSED(self
);
2520 outFile
= fopen(outFileName
, "w");
2521 /* XXX(nnorwitz): it should probably be an exception if outFile
2524 MYDB_BEGIN_ALLOW_THREADS
;
2525 err
= self
->db
->verify(self
->db
, fileName
, dbName
, outFile
, flags
);
2526 MYDB_END_ALLOW_THREADS
;
2530 /* DB.verify acts as a DB handle destructor (like close); this was
2531 * documented in BerkeleyDB 4.2 but had the undocumented effect
2532 * of not being safe in prior versions while still requiring an explicit
2533 * DB.close call afterwards. Lets call close for the user to emulate
2534 * the safe 4.2 behaviour. */
2536 self
->db
->close(self
->db
, 0);
2546 DB_set_get_returns_none(DBObject
* self
, PyObject
* args
)
2551 if (!PyArg_ParseTuple(args
,"i:set_get_returns_none", &flags
))
2553 CHECK_DB_NOT_CLOSED(self
);
2555 if (self
->moduleFlags
.getReturnsNone
)
2557 if (self
->moduleFlags
.cursorSetReturnsNone
)
2559 self
->moduleFlags
.getReturnsNone
= (flags
>= 1);
2560 self
->moduleFlags
.cursorSetReturnsNone
= (flags
>= 2);
2561 return PyInt_FromLong(oldValue
);
2566 DB_set_encrypt(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2570 char *passwd
= NULL
;
2571 static char* kwnames
[] = { "passwd", "flags", NULL
};
2573 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|i:set_encrypt", kwnames
,
2578 MYDB_BEGIN_ALLOW_THREADS
;
2579 err
= self
->db
->set_encrypt(self
->db
, passwd
, flags
);
2580 MYDB_END_ALLOW_THREADS
;
2585 #endif /* DBVER >= 41 */
2588 /*-------------------------------------------------------------- */
2589 /* Mapping and Dictionary-like access routines */
2591 Py_ssize_t
DB_length(PyObject
* _self
)
2594 Py_ssize_t size
= 0;
2597 DBObject
* self
= (DBObject
*)_self
;
2599 if (self
->db
== NULL
) {
2600 PyObject
*t
= Py_BuildValue("(is)", 0, "DB object has been closed");
2601 PyErr_SetObject(DBError
, t
);
2606 if (self
->haveStat
) { /* Has the stat function been called recently? If
2607 so, we can use the cached value. */
2608 flags
= DB_FAST_STAT
;
2611 MYDB_BEGIN_ALLOW_THREADS
;
2612 redo_stat_for_length
:
2614 err
= self
->db
->stat(self
->db
, /*txnid*/ NULL
, &sp
, flags
);
2616 err
= self
->db
->stat(self
->db
, &sp
, flags
);
2618 err
= self
->db
->stat(self
->db
, &sp
, NULL
, flags
);
2621 /* All the stat structures have matching fields upto the ndata field,
2622 so we can use any of them for the type cast */
2623 size
= ((DB_BTREE_STAT
*)sp
)->bt_ndata
;
2625 /* A size of 0 could mean that BerkeleyDB no longer had the stat values cached.
2626 * redo a full stat to make sure.
2627 * Fixes SF python bug 1493322, pybsddb bug 1184012
2629 if (size
== 0 && (flags
& DB_FAST_STAT
)) {
2633 goto redo_stat_for_length
;
2636 MYDB_END_ALLOW_THREADS
;
2648 PyObject
* DB_subscript(DBObject
* self
, PyObject
* keyobj
)
2655 CHECK_DB_NOT_CLOSED(self
);
2656 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
2660 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
2661 /* Tell BerkeleyDB to malloc the return value (thread safe) */
2662 data
.flags
= DB_DBT_MALLOC
;
2664 MYDB_BEGIN_ALLOW_THREADS
;
2665 err
= self
->db
->get(self
->db
, NULL
, &key
, &data
, 0);
2666 MYDB_END_ALLOW_THREADS
;
2667 if (err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) {
2668 PyErr_SetObject(PyExc_KeyError
, keyobj
);
2671 else if (makeDBError(err
)) {
2675 retval
= PyString_FromStringAndSize((char*)data
.data
, data
.size
);
2685 DB_ass_sub(DBObject
* self
, PyObject
* keyobj
, PyObject
* dataobj
)
2691 if (self
->db
== NULL
) {
2692 PyObject
*t
= Py_BuildValue("(is)", 0, "DB object has been closed");
2693 PyErr_SetObject(DBError
, t
);
2698 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
2701 if (dataobj
!= NULL
) {
2702 if (!make_dbt(dataobj
, &data
))
2705 if (self
->setflags
& (DB_DUP
|DB_DUPSORT
))
2706 /* dictionaries shouldn't have duplicate keys */
2707 flags
= DB_NOOVERWRITE
;
2708 retval
= _DB_put(self
, NULL
, &key
, &data
, flags
);
2710 if ((retval
== -1) && (self
->setflags
& (DB_DUP
|DB_DUPSORT
))) {
2711 /* try deleting any old record that matches and then PUT it
2713 _DB_delete(self
, NULL
, &key
, 0);
2715 retval
= _DB_put(self
, NULL
, &key
, &data
, flags
);
2720 /* dataobj == NULL, so delete the key */
2721 retval
= _DB_delete(self
, NULL
, &key
, 0);
2729 DB_has_key(DBObject
* self
, PyObject
* args
)
2734 PyObject
* txnobj
= NULL
;
2737 if (!PyArg_ParseTuple(args
,"O|O:has_key", &keyobj
, &txnobj
))
2739 CHECK_DB_NOT_CLOSED(self
);
2740 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
2742 if (!checkTxnObj(txnobj
, &txn
)) {
2747 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
2748 it has a record but can't allocate a buffer for the data. This saves
2749 having to deal with data we won't be using.
2752 data
.flags
= DB_DBT_USERMEM
;
2754 MYDB_BEGIN_ALLOW_THREADS
;
2755 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, 0);
2756 MYDB_END_ALLOW_THREADS
;
2759 if (err
== DB_BUFFER_SMALL
|| err
== 0) {
2760 return PyInt_FromLong(1);
2761 } else if (err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) {
2762 return PyInt_FromLong(0);
2770 #define _KEYS_LIST 1
2771 #define _VALUES_LIST 2
2772 #define _ITEMS_LIST 3
2775 _DB_make_list(DBObject
* self
, DB_TXN
* txn
, int type
)
2782 PyObject
* item
= NULL
;
2784 CHECK_DB_NOT_CLOSED(self
);
2788 dbtype
= _DB_get_type(self
);
2792 list
= PyList_New(0);
2797 MYDB_BEGIN_ALLOW_THREADS
;
2798 err
= self
->db
->cursor(self
->db
, txn
, &cursor
, 0);
2799 MYDB_END_ALLOW_THREADS
;
2800 if (makeDBError(err
)) {
2805 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
2806 key
.flags
= DB_DBT_REALLOC
;
2807 data
.flags
= DB_DBT_REALLOC
;
2810 while (1) { /* use the cursor to traverse the DB, collecting items */
2811 MYDB_BEGIN_ALLOW_THREADS
;
2812 err
= cursor
->c_get(cursor
, &key
, &data
, DB_NEXT
);
2813 MYDB_END_ALLOW_THREADS
;
2816 /* for any error, break out of the loop */
2826 item
= PyString_FromStringAndSize((char*)key
.data
, key
.size
);
2830 item
= PyInt_FromLong(*((db_recno_t
*)key
.data
));
2836 item
= PyString_FromStringAndSize((char*)data
.data
, data
.size
);
2844 item
= Py_BuildValue("s#s#", key
.data
, key
.size
, data
.data
,
2849 item
= Py_BuildValue("is#", *((db_recno_t
*)key
.data
),
2850 data
.data
, data
.size
);
2855 PyErr_Format(PyExc_ValueError
, "Unknown key type 0x%x", type
);
2864 PyList_Append(list
, item
);
2868 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
2869 if (err
!= DB_NOTFOUND
&& err
!= DB_KEYEMPTY
&& makeDBError(err
)) {
2877 MYDB_BEGIN_ALLOW_THREADS
;
2878 cursor
->c_close(cursor
);
2879 MYDB_END_ALLOW_THREADS
;
2885 DB_keys(DBObject
* self
, PyObject
* args
)
2887 PyObject
* txnobj
= NULL
;
2890 if (!PyArg_UnpackTuple(args
, "keys", 0, 1, &txnobj
))
2892 if (!checkTxnObj(txnobj
, &txn
))
2894 return _DB_make_list(self
, txn
, _KEYS_LIST
);
2899 DB_items(DBObject
* self
, PyObject
* args
)
2901 PyObject
* txnobj
= NULL
;
2904 if (!PyArg_UnpackTuple(args
, "items", 0, 1, &txnobj
))
2906 if (!checkTxnObj(txnobj
, &txn
))
2908 return _DB_make_list(self
, txn
, _ITEMS_LIST
);
2913 DB_values(DBObject
* self
, PyObject
* args
)
2915 PyObject
* txnobj
= NULL
;
2918 if (!PyArg_UnpackTuple(args
, "values", 0, 1, &txnobj
))
2920 if (!checkTxnObj(txnobj
, &txn
))
2922 return _DB_make_list(self
, txn
, _VALUES_LIST
);
2925 /* --------------------------------------------------------------------- */
2926 /* DBCursor methods */
2930 DBC_close(DBCursorObject
* self
, PyObject
* args
)
2934 if (!PyArg_ParseTuple(args
, ":close"))
2937 if (self
->dbc
!= NULL
) {
2938 MYDB_BEGIN_ALLOW_THREADS
;
2939 err
= self
->dbc
->c_close(self
->dbc
);
2941 MYDB_END_ALLOW_THREADS
;
2949 DBC_count(DBCursorObject
* self
, PyObject
* args
)
2955 if (!PyArg_ParseTuple(args
, "|i:count", &flags
))
2958 CHECK_CURSOR_NOT_CLOSED(self
);
2960 MYDB_BEGIN_ALLOW_THREADS
;
2961 err
= self
->dbc
->c_count(self
->dbc
, &count
, flags
);
2962 MYDB_END_ALLOW_THREADS
;
2965 return PyInt_FromLong(count
);
2970 DBC_current(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
2972 return _DBCursor_get(self
,DB_CURRENT
,args
,kwargs
,"|iii:current");
2977 DBC_delete(DBCursorObject
* self
, PyObject
* args
)
2981 if (!PyArg_ParseTuple(args
, "|i:delete", &flags
))
2984 CHECK_CURSOR_NOT_CLOSED(self
);
2986 MYDB_BEGIN_ALLOW_THREADS
;
2987 err
= self
->dbc
->c_del(self
->dbc
, flags
);
2988 MYDB_END_ALLOW_THREADS
;
2991 self
->mydb
->haveStat
= 0;
2997 DBC_dup(DBCursorObject
* self
, PyObject
* args
)
3002 if (!PyArg_ParseTuple(args
, "|i:dup", &flags
))
3005 CHECK_CURSOR_NOT_CLOSED(self
);
3007 MYDB_BEGIN_ALLOW_THREADS
;
3008 err
= self
->dbc
->c_dup(self
->dbc
, &dbc
, flags
);
3009 MYDB_END_ALLOW_THREADS
;
3012 return (PyObject
*) newDBCursorObject(dbc
, self
->mydb
);
3016 DBC_first(DBCursorObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3018 return _DBCursor_get(self
,DB_FIRST
,args
,kwargs
,"|iii:first");
3023 DBC_get(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3026 PyObject
* keyobj
= NULL
;
3027 PyObject
* dataobj
= NULL
;
3028 PyObject
* retval
= NULL
;
3032 static char* kwnames
[] = { "key","data", "flags", "dlen", "doff",
3037 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|ii:get", &kwnames
[2],
3038 &flags
, &dlen
, &doff
))
3041 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "Oi|ii:get",
3043 &keyobj
, &flags
, &dlen
, &doff
))
3046 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OOi|ii:get",
3047 kwnames
, &keyobj
, &dataobj
,
3048 &flags
, &dlen
, &doff
))
3055 CHECK_CURSOR_NOT_CLOSED(self
);
3057 if (keyobj
&& !make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3059 if ( (dataobj
&& !make_dbt(dataobj
, &data
)) ||
3060 (!add_partial_dbt(&data
, dlen
, doff
)) )
3066 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3067 data
.flags
= DB_DBT_MALLOC
;
3068 if (!(key
.flags
& DB_DBT_REALLOC
)) {
3069 key
.flags
|= DB_DBT_MALLOC
;
3073 MYDB_BEGIN_ALLOW_THREADS
;
3074 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
);
3075 MYDB_END_ALLOW_THREADS
;
3077 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3078 && self
->mydb
->moduleFlags
.getReturnsNone
) {
3082 else if (makeDBError(err
)) {
3086 switch (_DB_get_type(self
->mydb
)) {
3093 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
,
3094 data
.data
, data
.size
);
3098 retval
= Py_BuildValue("is#", *((db_recno_t
*)key
.data
),
3099 data
.data
, data
.size
);
3110 DBC_pget(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3113 PyObject
* keyobj
= NULL
;
3114 PyObject
* dataobj
= NULL
;
3115 PyObject
* retval
= NULL
;
3118 DBT key
, pkey
, data
;
3119 static char* kwnames_keyOnly
[] = { "key", "flags", "dlen", "doff", NULL
};
3120 static char* kwnames
[] = { "key", "data", "flags", "dlen", "doff", NULL
};
3124 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|ii:pget", &kwnames
[2],
3125 &flags
, &dlen
, &doff
))
3128 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "Oi|ii:pget",
3130 &keyobj
, &flags
, &dlen
, &doff
))
3133 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OOi|ii:pget",
3134 kwnames
, &keyobj
, &dataobj
,
3135 &flags
, &dlen
, &doff
))
3142 CHECK_CURSOR_NOT_CLOSED(self
);
3144 if (keyobj
&& !make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3146 if ( (dataobj
&& !make_dbt(dataobj
, &data
)) ||
3147 (!add_partial_dbt(&data
, dlen
, doff
)) ) {
3152 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3153 data
.flags
= DB_DBT_MALLOC
;
3154 if (!(key
.flags
& DB_DBT_REALLOC
)) {
3155 key
.flags
|= DB_DBT_MALLOC
;
3160 pkey
.flags
= DB_DBT_MALLOC
;
3162 MYDB_BEGIN_ALLOW_THREADS
;
3163 err
= self
->dbc
->c_pget(self
->dbc
, &key
, &pkey
, &data
, flags
);
3164 MYDB_END_ALLOW_THREADS
;
3166 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3167 && self
->mydb
->moduleFlags
.getReturnsNone
) {
3171 else if (makeDBError(err
)) {
3177 dataObj
= PyString_FromStringAndSize(data
.data
, data
.size
);
3179 if (self
->mydb
->primaryDBType
== DB_RECNO
||
3180 self
->mydb
->primaryDBType
== DB_QUEUE
)
3181 pkeyObj
= PyInt_FromLong(*(int *)pkey
.data
);
3183 pkeyObj
= PyString_FromStringAndSize(pkey
.data
, pkey
.size
);
3185 if (key
.data
&& key
.size
) /* return key, pkey and data */
3188 int type
= _DB_get_type(self
->mydb
);
3189 if (type
== DB_RECNO
|| type
== DB_QUEUE
)
3190 keyObj
= PyInt_FromLong(*(int *)key
.data
);
3192 keyObj
= PyString_FromStringAndSize(key
.data
, key
.size
);
3193 #if (PY_VERSION_HEX >= 0x02040000)
3194 retval
= PyTuple_Pack(3, keyObj
, pkeyObj
, dataObj
);
3196 retval
= Py_BuildValue("OOO", keyObj
, pkeyObj
, dataObj
);
3201 else /* return just the pkey and data */
3203 #if (PY_VERSION_HEX >= 0x02040000)
3204 retval
= PyTuple_Pack(2, pkeyObj
, dataObj
);
3206 retval
= Py_BuildValue("OO", pkeyObj
, dataObj
);
3214 /* the only time REALLOC should be set is if we used an integer
3215 * key that make_key_dbt malloc'd for us. always free these. */
3216 if (key
.flags
& DB_DBT_REALLOC
) {
3225 DBC_get_recno(DBCursorObject
* self
, PyObject
* args
)
3232 if (!PyArg_ParseTuple(args
, ":get_recno"))
3235 CHECK_CURSOR_NOT_CLOSED(self
);
3239 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3240 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3241 data
.flags
= DB_DBT_MALLOC
;
3242 key
.flags
= DB_DBT_MALLOC
;
3245 MYDB_BEGIN_ALLOW_THREADS
;
3246 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, DB_GET_RECNO
);
3247 MYDB_END_ALLOW_THREADS
;
3250 recno
= *((db_recno_t
*)data
.data
);
3253 return PyInt_FromLong(recno
);
3258 DBC_last(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3260 return _DBCursor_get(self
,DB_LAST
,args
,kwargs
,"|iii:last");
3265 DBC_next(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3267 return _DBCursor_get(self
,DB_NEXT
,args
,kwargs
,"|iii:next");
3272 DBC_prev(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3274 return _DBCursor_get(self
,DB_PREV
,args
,kwargs
,"|iii:prev");
3279 DBC_put(DBCursorObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3282 PyObject
* keyobj
, *dataobj
;
3284 static char* kwnames
[] = { "key", "data", "flags", "dlen", "doff",
3289 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|iii:put", kwnames
,
3290 &keyobj
, &dataobj
, &flags
, &dlen
, &doff
))
3293 CHECK_CURSOR_NOT_CLOSED(self
);
3295 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3297 if (!make_dbt(dataobj
, &data
) ||
3298 !add_partial_dbt(&data
, dlen
, doff
) )
3304 MYDB_BEGIN_ALLOW_THREADS
;
3305 err
= self
->dbc
->c_put(self
->dbc
, &key
, &data
, flags
);
3306 MYDB_END_ALLOW_THREADS
;
3309 self
->mydb
->haveStat
= 0;
3315 DBC_set(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3319 PyObject
* retval
, *keyobj
;
3320 static char* kwnames
[] = { "key", "flags", "dlen", "doff", NULL
};
3324 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|iii:set", kwnames
,
3325 &keyobj
, &flags
, &dlen
, &doff
))
3328 CHECK_CURSOR_NOT_CLOSED(self
);
3330 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3334 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3335 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3336 data
.flags
= DB_DBT_MALLOC
;
3338 if (!add_partial_dbt(&data
, dlen
, doff
)) {
3343 MYDB_BEGIN_ALLOW_THREADS
;
3344 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
|DB_SET
);
3345 MYDB_END_ALLOW_THREADS
;
3346 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3347 && self
->mydb
->moduleFlags
.cursorSetReturnsNone
) {
3351 else if (makeDBError(err
)) {
3355 switch (_DB_get_type(self
->mydb
)) {
3362 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
,
3363 data
.data
, data
.size
);
3367 retval
= Py_BuildValue("is#", *((db_recno_t
*)key
.data
),
3368 data
.data
, data
.size
);
3374 /* the only time REALLOC should be set is if we used an integer
3375 * key that make_key_dbt malloc'd for us. always free these. */
3376 if (key
.flags
& DB_DBT_REALLOC
) {
3385 DBC_set_range(DBCursorObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3389 PyObject
* retval
, *keyobj
;
3390 static char* kwnames
[] = { "key", "flags", "dlen", "doff", NULL
};
3394 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|iii:set_range", kwnames
,
3395 &keyobj
, &flags
, &dlen
, &doff
))
3398 CHECK_CURSOR_NOT_CLOSED(self
);
3400 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3404 if (!add_partial_dbt(&data
, dlen
, doff
)) {
3408 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3409 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3410 data
.flags
|= DB_DBT_MALLOC
;
3411 /* only BTREE databases will return anything in the key */
3412 if (!(key
.flags
& DB_DBT_REALLOC
) && _DB_get_type(self
->mydb
) == DB_BTREE
) {
3413 key
.flags
|= DB_DBT_MALLOC
;
3416 MYDB_BEGIN_ALLOW_THREADS
;
3417 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
|DB_SET_RANGE
);
3418 MYDB_END_ALLOW_THREADS
;
3419 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3420 && self
->mydb
->moduleFlags
.cursorSetReturnsNone
) {
3424 else if (makeDBError(err
)) {
3428 switch (_DB_get_type(self
->mydb
)) {
3435 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
,
3436 data
.data
, data
.size
);
3440 retval
= Py_BuildValue("is#", *((db_recno_t
*)key
.data
),
3441 data
.data
, data
.size
);
3447 /* the only time REALLOC should be set is if we used an integer
3448 * key that make_key_dbt malloc'd for us. always free these. */
3449 if (key
.flags
& DB_DBT_REALLOC
) {
3457 _DBC_get_set_both(DBCursorObject
* self
, PyObject
* keyobj
, PyObject
* dataobj
,
3458 int flags
, unsigned int returnsNone
)
3464 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3465 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3467 if (!make_dbt(dataobj
, &data
)) {
3472 MYDB_BEGIN_ALLOW_THREADS
;
3473 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
|DB_GET_BOTH
);
3474 MYDB_END_ALLOW_THREADS
;
3475 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) && returnsNone
) {
3479 else if (makeDBError(err
)) {
3483 switch (_DB_get_type(self
->mydb
)) {
3490 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
,
3491 data
.data
, data
.size
);
3495 retval
= Py_BuildValue("is#", *((db_recno_t
*)key
.data
),
3496 data
.data
, data
.size
);
3506 DBC_get_both(DBCursorObject
* self
, PyObject
* args
)
3509 PyObject
*keyobj
, *dataobj
;
3511 if (!PyArg_ParseTuple(args
, "OO|i:get_both", &keyobj
, &dataobj
, &flags
))
3514 /* if the cursor is closed, self->mydb may be invalid */
3515 CHECK_CURSOR_NOT_CLOSED(self
);
3517 return _DBC_get_set_both(self
, keyobj
, dataobj
, flags
,
3518 self
->mydb
->moduleFlags
.getReturnsNone
);
3521 /* Return size of entry */
3523 DBC_get_current_size(DBCursorObject
* self
, PyObject
* args
)
3525 int err
, flags
=DB_CURRENT
;
3526 PyObject
* retval
= NULL
;
3529 if (!PyArg_ParseTuple(args
, ":get_current_size"))
3531 CHECK_CURSOR_NOT_CLOSED(self
);
3535 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3536 getting the record size. */
3537 data
.flags
= DB_DBT_USERMEM
;
3539 MYDB_BEGIN_ALLOW_THREADS
;
3540 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
);
3541 MYDB_END_ALLOW_THREADS
;
3542 if (err
== DB_BUFFER_SMALL
|| !err
) {
3543 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3544 retval
= PyInt_FromLong((long)data
.size
);
3555 DBC_set_both(DBCursorObject
* self
, PyObject
* args
)
3558 PyObject
*keyobj
, *dataobj
;
3560 if (!PyArg_ParseTuple(args
, "OO|i:set_both", &keyobj
, &dataobj
, &flags
))
3563 /* if the cursor is closed, self->mydb may be invalid */
3564 CHECK_CURSOR_NOT_CLOSED(self
);
3566 return _DBC_get_set_both(self
, keyobj
, dataobj
, flags
,
3567 self
->mydb
->moduleFlags
.cursorSetReturnsNone
);
3572 DBC_set_recno(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3574 int err
, irecno
, flags
=0;
3580 static char* kwnames
[] = { "recno","flags", "dlen", "doff", NULL
};
3582 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|iii:set_recno", kwnames
,
3583 &irecno
, &flags
, &dlen
, &doff
))
3586 CHECK_CURSOR_NOT_CLOSED(self
);
3589 recno
= (db_recno_t
) irecno
;
3590 /* use allocated space so DB will be able to realloc room for the real
3592 key
.data
= malloc(sizeof(db_recno_t
));
3593 if (key
.data
== NULL
) {
3594 PyErr_SetString(PyExc_MemoryError
, "Key memory allocation failed");
3597 key
.size
= sizeof(db_recno_t
);
3598 key
.ulen
= key
.size
;
3599 memcpy(key
.data
, &recno
, sizeof(db_recno_t
));
3600 key
.flags
= DB_DBT_REALLOC
;
3603 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3604 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3605 data
.flags
= DB_DBT_MALLOC
;
3607 if (!add_partial_dbt(&data
, dlen
, doff
)) {
3612 MYDB_BEGIN_ALLOW_THREADS
;
3613 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
|DB_SET_RECNO
);
3614 MYDB_END_ALLOW_THREADS
;
3615 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3616 && self
->mydb
->moduleFlags
.cursorSetReturnsNone
) {
3620 else if (makeDBError(err
)) {
3623 else { /* Can only be used for BTrees, so no need to return int key */
3624 retval
= Py_BuildValue("s#s#", key
.data
, key
.size
,
3625 data
.data
, data
.size
);
3635 DBC_consume(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3637 return _DBCursor_get(self
,DB_CONSUME
,args
,kwargs
,"|iii:consume");
3642 DBC_next_dup(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3644 return _DBCursor_get(self
,DB_NEXT_DUP
,args
,kwargs
,"|iii:next_dup");
3649 DBC_next_nodup(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3651 return _DBCursor_get(self
,DB_NEXT_NODUP
,args
,kwargs
,"|iii:next_nodup");
3656 DBC_prev_nodup(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3658 return _DBCursor_get(self
,DB_PREV_NODUP
,args
,kwargs
,"|iii:prev_nodup");
3663 DBC_join_item(DBCursorObject
* self
, PyObject
* args
)
3669 if (!PyArg_ParseTuple(args
, "|i:join_item", &flags
))
3672 CHECK_CURSOR_NOT_CLOSED(self
);
3676 if (CHECK_DBFLAG(self
->mydb
, DB_THREAD
)) {
3677 /* Tell BerkeleyDB to malloc the return value (thread safe) */
3678 key
.flags
= DB_DBT_MALLOC
;
3681 MYDB_BEGIN_ALLOW_THREADS
;
3682 err
= self
->dbc
->c_get(self
->dbc
, &key
, &data
, flags
| DB_JOIN_ITEM
);
3683 MYDB_END_ALLOW_THREADS
;
3684 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3685 && self
->mydb
->moduleFlags
.getReturnsNone
) {
3689 else if (makeDBError(err
)) {
3693 retval
= Py_BuildValue("s#", key
.data
, key
.size
);
3702 /* --------------------------------------------------------------------- */
3707 DBEnv_close(DBEnvObject
* self
, PyObject
* args
)
3711 if (!PyArg_ParseTuple(args
, "|i:close", &flags
))
3713 if (!self
->closed
) { /* Don't close more than once */
3714 MYDB_BEGIN_ALLOW_THREADS
;
3715 err
= self
->db_env
->close(self
->db_env
, flags
);
3716 MYDB_END_ALLOW_THREADS
;
3717 /* after calling DBEnv->close, regardless of error, this DBEnv
3718 * may not be accessed again (BerkeleyDB docs). */
3720 self
->db_env
= NULL
;
3728 DBEnv_open(DBEnvObject
* self
, PyObject
* args
)
3730 int err
, flags
=0, mode
=0660;
3733 if (!PyArg_ParseTuple(args
, "z|ii:open", &db_home
, &flags
, &mode
))
3736 CHECK_ENV_NOT_CLOSED(self
);
3738 MYDB_BEGIN_ALLOW_THREADS
;
3739 err
= self
->db_env
->open(self
->db_env
, db_home
, flags
, mode
);
3740 MYDB_END_ALLOW_THREADS
;
3743 self
->flags
= flags
;
3749 DBEnv_remove(DBEnvObject
* self
, PyObject
* args
)
3754 if (!PyArg_ParseTuple(args
, "s|i:remove", &db_home
, &flags
))
3756 CHECK_ENV_NOT_CLOSED(self
);
3757 MYDB_BEGIN_ALLOW_THREADS
;
3758 err
= self
->db_env
->remove(self
->db_env
, db_home
, flags
);
3759 MYDB_END_ALLOW_THREADS
;
3766 DBEnv_dbremove(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3771 char *database
= NULL
;
3772 PyObject
*txnobj
= NULL
;
3774 static char* kwnames
[] = { "file", "database", "txn", "flags",
3777 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zOi:dbremove", kwnames
,
3778 &file
, &database
, &txnobj
, &flags
)) {
3781 if (!checkTxnObj(txnobj
, &txn
)) {
3784 CHECK_ENV_NOT_CLOSED(self
);
3785 MYDB_BEGIN_ALLOW_THREADS
;
3786 err
= self
->db_env
->dbremove(self
->db_env
, txn
, file
, database
, flags
);
3787 MYDB_END_ALLOW_THREADS
;
3793 DBEnv_dbrename(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3798 char *database
= NULL
;
3799 char *newname
= NULL
;
3800 PyObject
*txnobj
= NULL
;
3802 static char* kwnames
[] = { "file", "database", "newname", "txn",
3805 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "szs|Oi:dbrename", kwnames
,
3806 &file
, &database
, &newname
, &txnobj
, &flags
)) {
3809 if (!checkTxnObj(txnobj
, &txn
)) {
3812 CHECK_ENV_NOT_CLOSED(self
);
3813 MYDB_BEGIN_ALLOW_THREADS
;
3814 err
= self
->db_env
->dbrename(self
->db_env
, txn
, file
, database
, newname
,
3816 MYDB_END_ALLOW_THREADS
;
3822 DBEnv_set_encrypt(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3826 char *passwd
= NULL
;
3827 static char* kwnames
[] = { "passwd", "flags", NULL
};
3829 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|i:set_encrypt", kwnames
,
3834 MYDB_BEGIN_ALLOW_THREADS
;
3835 err
= self
->db_env
->set_encrypt(self
->db_env
, passwd
, flags
);
3836 MYDB_END_ALLOW_THREADS
;
3841 #endif /* DBVER >= 41 */
3845 DBEnv_set_timeout(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3849 u_int32_t timeout
= 0;
3850 static char* kwnames
[] = { "timeout", "flags", NULL
};
3852 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "ii:set_timeout", kwnames
,
3853 &timeout
, &flags
)) {
3857 MYDB_BEGIN_ALLOW_THREADS
;
3858 err
= self
->db_env
->set_timeout(self
->db_env
, (db_timeout_t
)timeout
, flags
);
3859 MYDB_END_ALLOW_THREADS
;
3864 #endif /* DBVER >= 40 */
3867 DBEnv_set_shm_key(DBEnvObject
* self
, PyObject
* args
)
3872 if (!PyArg_ParseTuple(args
, "l:set_shm_key", &shm_key
))
3874 CHECK_ENV_NOT_CLOSED(self
);
3876 err
= self
->db_env
->set_shm_key(self
->db_env
, shm_key
);
3882 DBEnv_set_cachesize(DBEnvObject
* self
, PyObject
* args
)
3884 int err
, gbytes
=0, bytes
=0, ncache
=0;
3886 if (!PyArg_ParseTuple(args
, "ii|i:set_cachesize",
3887 &gbytes
, &bytes
, &ncache
))
3889 CHECK_ENV_NOT_CLOSED(self
);
3891 MYDB_BEGIN_ALLOW_THREADS
;
3892 err
= self
->db_env
->set_cachesize(self
->db_env
, gbytes
, bytes
, ncache
);
3893 MYDB_END_ALLOW_THREADS
;
3900 DBEnv_set_flags(DBEnvObject
* self
, PyObject
* args
)
3902 int err
, flags
=0, onoff
=0;
3904 if (!PyArg_ParseTuple(args
, "ii:set_flags",
3907 CHECK_ENV_NOT_CLOSED(self
);
3909 MYDB_BEGIN_ALLOW_THREADS
;
3910 err
= self
->db_env
->set_flags(self
->db_env
, flags
, onoff
);
3911 MYDB_END_ALLOW_THREADS
;
3918 DBEnv_set_data_dir(DBEnvObject
* self
, PyObject
* args
)
3923 if (!PyArg_ParseTuple(args
, "s:set_data_dir", &dir
))
3925 CHECK_ENV_NOT_CLOSED(self
);
3927 MYDB_BEGIN_ALLOW_THREADS
;
3928 err
= self
->db_env
->set_data_dir(self
->db_env
, dir
);
3929 MYDB_END_ALLOW_THREADS
;
3936 DBEnv_set_lg_bsize(DBEnvObject
* self
, PyObject
* args
)
3940 if (!PyArg_ParseTuple(args
, "i:set_lg_bsize", &lg_bsize
))
3942 CHECK_ENV_NOT_CLOSED(self
);
3944 MYDB_BEGIN_ALLOW_THREADS
;
3945 err
= self
->db_env
->set_lg_bsize(self
->db_env
, lg_bsize
);
3946 MYDB_END_ALLOW_THREADS
;
3953 DBEnv_set_lg_dir(DBEnvObject
* self
, PyObject
* args
)
3958 if (!PyArg_ParseTuple(args
, "s:set_lg_dir", &dir
))
3960 CHECK_ENV_NOT_CLOSED(self
);
3962 MYDB_BEGIN_ALLOW_THREADS
;
3963 err
= self
->db_env
->set_lg_dir(self
->db_env
, dir
);
3964 MYDB_END_ALLOW_THREADS
;
3970 DBEnv_set_lg_max(DBEnvObject
* self
, PyObject
* args
)
3974 if (!PyArg_ParseTuple(args
, "i:set_lg_max", &lg_max
))
3976 CHECK_ENV_NOT_CLOSED(self
);
3978 MYDB_BEGIN_ALLOW_THREADS
;
3979 err
= self
->db_env
->set_lg_max(self
->db_env
, lg_max
);
3980 MYDB_END_ALLOW_THREADS
;
3988 DBEnv_set_lg_regionmax(DBEnvObject
* self
, PyObject
* args
)
3992 if (!PyArg_ParseTuple(args
, "i:set_lg_regionmax", &lg_max
))
3994 CHECK_ENV_NOT_CLOSED(self
);
3996 MYDB_BEGIN_ALLOW_THREADS
;
3997 err
= self
->db_env
->set_lg_regionmax(self
->db_env
, lg_max
);
3998 MYDB_END_ALLOW_THREADS
;
4006 DBEnv_set_lk_detect(DBEnvObject
* self
, PyObject
* args
)
4010 if (!PyArg_ParseTuple(args
, "i:set_lk_detect", &lk_detect
))
4012 CHECK_ENV_NOT_CLOSED(self
);
4014 MYDB_BEGIN_ALLOW_THREADS
;
4015 err
= self
->db_env
->set_lk_detect(self
->db_env
, lk_detect
);
4016 MYDB_END_ALLOW_THREADS
;
4024 DBEnv_set_lk_max(DBEnvObject
* self
, PyObject
* args
)
4028 if (!PyArg_ParseTuple(args
, "i:set_lk_max", &max
))
4030 CHECK_ENV_NOT_CLOSED(self
);
4032 MYDB_BEGIN_ALLOW_THREADS
;
4033 err
= self
->db_env
->set_lk_max(self
->db_env
, max
);
4034 MYDB_END_ALLOW_THREADS
;
4043 DBEnv_set_lk_max_locks(DBEnvObject
* self
, PyObject
* args
)
4047 if (!PyArg_ParseTuple(args
, "i:set_lk_max_locks", &max
))
4049 CHECK_ENV_NOT_CLOSED(self
);
4051 MYDB_BEGIN_ALLOW_THREADS
;
4052 err
= self
->db_env
->set_lk_max_locks(self
->db_env
, max
);
4053 MYDB_END_ALLOW_THREADS
;
4060 DBEnv_set_lk_max_lockers(DBEnvObject
* self
, PyObject
* args
)
4064 if (!PyArg_ParseTuple(args
, "i:set_lk_max_lockers", &max
))
4066 CHECK_ENV_NOT_CLOSED(self
);
4068 MYDB_BEGIN_ALLOW_THREADS
;
4069 err
= self
->db_env
->set_lk_max_lockers(self
->db_env
, max
);
4070 MYDB_END_ALLOW_THREADS
;
4077 DBEnv_set_lk_max_objects(DBEnvObject
* self
, PyObject
* args
)
4081 if (!PyArg_ParseTuple(args
, "i:set_lk_max_objects", &max
))
4083 CHECK_ENV_NOT_CLOSED(self
);
4085 MYDB_BEGIN_ALLOW_THREADS
;
4086 err
= self
->db_env
->set_lk_max_objects(self
->db_env
, max
);
4087 MYDB_END_ALLOW_THREADS
;
4094 DBEnv_set_mp_mmapsize(DBEnvObject
* self
, PyObject
* args
)
4096 int err
, mp_mmapsize
;
4098 if (!PyArg_ParseTuple(args
, "i:set_mp_mmapsize", &mp_mmapsize
))
4100 CHECK_ENV_NOT_CLOSED(self
);
4102 MYDB_BEGIN_ALLOW_THREADS
;
4103 err
= self
->db_env
->set_mp_mmapsize(self
->db_env
, mp_mmapsize
);
4104 MYDB_END_ALLOW_THREADS
;
4111 DBEnv_set_tmp_dir(DBEnvObject
* self
, PyObject
* args
)
4116 if (!PyArg_ParseTuple(args
, "s:set_tmp_dir", &dir
))
4118 CHECK_ENV_NOT_CLOSED(self
);
4120 MYDB_BEGIN_ALLOW_THREADS
;
4121 err
= self
->db_env
->set_tmp_dir(self
->db_env
, dir
);
4122 MYDB_END_ALLOW_THREADS
;
4129 DBEnv_txn_begin(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4132 PyObject
* txnobj
= NULL
;
4134 static char* kwnames
[] = { "parent", "flags", NULL
};
4136 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:txn_begin", kwnames
,
4140 if (!checkTxnObj(txnobj
, &txn
))
4142 CHECK_ENV_NOT_CLOSED(self
);
4144 return (PyObject
*)newDBTxnObject(self
, txn
, flags
);
4149 DBEnv_txn_checkpoint(DBEnvObject
* self
, PyObject
* args
)
4151 int err
, kbyte
=0, min
=0, flags
=0;
4153 if (!PyArg_ParseTuple(args
, "|iii:txn_checkpoint", &kbyte
, &min
, &flags
))
4155 CHECK_ENV_NOT_CLOSED(self
);
4157 MYDB_BEGIN_ALLOW_THREADS
;
4159 err
= self
->db_env
->txn_checkpoint(self
->db_env
, kbyte
, min
, flags
);
4161 err
= txn_checkpoint(self
->db_env
, kbyte
, min
, flags
);
4163 MYDB_END_ALLOW_THREADS
;
4170 DBEnv_set_tx_max(DBEnvObject
* self
, PyObject
* args
)
4174 if (!PyArg_ParseTuple(args
, "i:set_tx_max", &max
))
4176 CHECK_ENV_NOT_CLOSED(self
);
4178 err
= self
->db_env
->set_tx_max(self
->db_env
, max
);
4185 DBEnv_set_tx_timestamp(DBEnvObject
* self
, PyObject
* args
)
4191 if (!PyArg_ParseTuple(args
, "l:set_tx_timestamp", &stamp
))
4193 CHECK_ENV_NOT_CLOSED(self
);
4194 timestamp
= (time_t)stamp
;
4195 err
= self
->db_env
->set_tx_timestamp(self
->db_env
, ×tamp
);
4202 DBEnv_lock_detect(DBEnvObject
* self
, PyObject
* args
)
4204 int err
, atype
, flags
=0;
4207 if (!PyArg_ParseTuple(args
, "i|i:lock_detect", &atype
, &flags
))
4209 CHECK_ENV_NOT_CLOSED(self
);
4211 MYDB_BEGIN_ALLOW_THREADS
;
4213 err
= self
->db_env
->lock_detect(self
->db_env
, flags
, atype
, &aborted
);
4215 err
= lock_detect(self
->db_env
, flags
, atype
, &aborted
);
4217 MYDB_END_ALLOW_THREADS
;
4219 return PyInt_FromLong(aborted
);
4224 DBEnv_lock_get(DBEnvObject
* self
, PyObject
* args
)
4227 int locker
, lock_mode
;
4231 if (!PyArg_ParseTuple(args
, "iOi|i:lock_get", &locker
, &objobj
, &lock_mode
, &flags
))
4235 if (!make_dbt(objobj
, &obj
))
4238 return (PyObject
*)newDBLockObject(self
, locker
, &obj
, lock_mode
, flags
);
4243 DBEnv_lock_id(DBEnvObject
* self
, PyObject
* args
)
4248 if (!PyArg_ParseTuple(args
, ":lock_id"))
4251 CHECK_ENV_NOT_CLOSED(self
);
4252 MYDB_BEGIN_ALLOW_THREADS
;
4254 err
= self
->db_env
->lock_id(self
->db_env
, &theID
);
4256 err
= lock_id(self
->db_env
, &theID
);
4258 MYDB_END_ALLOW_THREADS
;
4261 return PyInt_FromLong((long)theID
);
4266 DBEnv_lock_id_free(DBEnvObject
* self
, PyObject
* args
)
4271 if (!PyArg_ParseTuple(args
, "I:lock_id_free", &theID
))
4274 CHECK_ENV_NOT_CLOSED(self
);
4275 MYDB_BEGIN_ALLOW_THREADS
;
4276 err
= self
->db_env
->lock_id_free(self
->db_env
, theID
);
4277 MYDB_END_ALLOW_THREADS
;
4284 DBEnv_lock_put(DBEnvObject
* self
, PyObject
* args
)
4287 DBLockObject
* dblockobj
;
4289 if (!PyArg_ParseTuple(args
, "O!:lock_put", &DBLock_Type
, &dblockobj
))
4292 CHECK_ENV_NOT_CLOSED(self
);
4293 MYDB_BEGIN_ALLOW_THREADS
;
4295 err
= self
->db_env
->lock_put(self
->db_env
, &dblockobj
->lock
);
4297 err
= lock_put(self
->db_env
, &dblockobj
->lock
);
4299 MYDB_END_ALLOW_THREADS
;
4306 DBEnv_lsn_reset(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4310 u_int32_t flags
= 0;
4311 static char* kwnames
[] = { "file", "flags", NULL
};
4313 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "z|i:lsn_reset", kwnames
,
4316 CHECK_ENV_NOT_CLOSED(self
);
4318 MYDB_BEGIN_ALLOW_THREADS
;
4319 err
= self
->db_env
->lsn_reset(self
->db_env
, file
, flags
);
4320 MYDB_END_ALLOW_THREADS
;
4324 #endif /* DBVER >= 4.4 */
4328 DBEnv_log_stat(DBEnvObject
* self
, PyObject
* args
)
4331 DB_LOG_STAT
* statp
= NULL
;
4333 u_int32_t flags
= 0;
4335 if (!PyArg_ParseTuple(args
, "|i:log_stat", &flags
))
4337 CHECK_ENV_NOT_CLOSED(self
);
4339 MYDB_BEGIN_ALLOW_THREADS
;
4340 err
= self
->db_env
->log_stat(self
->db_env
, &statp
, flags
);
4341 MYDB_END_ALLOW_THREADS
;
4344 /* Turn the stat structure into a dictionary */
4352 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4355 MAKE_ENTRY(version
);
4357 MAKE_ENTRY(lg_bsize
);
4359 MAKE_ENTRY(lg_size
);
4365 MAKE_ENTRY(w_mbytes
);
4366 MAKE_ENTRY(w_bytes
);
4367 MAKE_ENTRY(wc_mbytes
);
4368 MAKE_ENTRY(wc_bytes
);
4370 MAKE_ENTRY(wcount_fill
);
4375 MAKE_ENTRY(cur_file
);
4376 MAKE_ENTRY(cur_offset
);
4377 MAKE_ENTRY(disk_file
);
4378 MAKE_ENTRY(disk_offset
);
4379 MAKE_ENTRY(maxcommitperflush
);
4380 MAKE_ENTRY(mincommitperflush
);
4381 MAKE_ENTRY(regsize
);
4382 MAKE_ENTRY(region_wait
);
4383 MAKE_ENTRY(region_nowait
);
4388 } /* DBEnv_log_stat */
4389 #endif /* DBVER >= 4.0 for log_stat method */
4393 DBEnv_lock_stat(DBEnvObject
* self
, PyObject
* args
)
4398 u_int32_t flags
= 0;
4400 if (!PyArg_ParseTuple(args
, "|i:lock_stat", &flags
))
4402 CHECK_ENV_NOT_CLOSED(self
);
4404 MYDB_BEGIN_ALLOW_THREADS
;
4406 err
= self
->db_env
->lock_stat(self
->db_env
, &sp
, flags
);
4409 err
= lock_stat(self
->db_env
, &sp
);
4411 err
= lock_stat(self
->db_env
, &sp
, NULL
);
4414 MYDB_END_ALLOW_THREADS
;
4417 /* Turn the stat structure into a dictionary */
4424 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4430 MAKE_ENTRY(maxlocks
);
4431 MAKE_ENTRY(maxlockers
);
4432 MAKE_ENTRY(maxobjects
);
4434 MAKE_ENTRY(maxnlocks
);
4435 MAKE_ENTRY(nlockers
);
4436 MAKE_ENTRY(maxnlockers
);
4437 MAKE_ENTRY(nobjects
);
4438 MAKE_ENTRY(maxnobjects
);
4439 MAKE_ENTRY(nrequests
);
4440 MAKE_ENTRY(nreleases
);
4442 MAKE_ENTRY(nnowaits
); /* these were renamed in 4.4 */
4443 MAKE_ENTRY(nconflicts
);
4445 MAKE_ENTRY(lock_nowait
);
4446 MAKE_ENTRY(lock_wait
);
4448 MAKE_ENTRY(ndeadlocks
);
4449 MAKE_ENTRY(regsize
);
4450 MAKE_ENTRY(region_wait
);
4451 MAKE_ENTRY(region_nowait
);
4460 DBEnv_log_archive(DBEnvObject
* self
, PyObject
* args
)
4464 char **log_list
= NULL
;
4466 PyObject
* item
= NULL
;
4468 if (!PyArg_ParseTuple(args
, "|i:log_archive", &flags
))
4471 CHECK_ENV_NOT_CLOSED(self
);
4472 MYDB_BEGIN_ALLOW_THREADS
;
4474 err
= self
->db_env
->log_archive(self
->db_env
, &log_list
, flags
);
4476 err
= log_archive(self
->db_env
, &log_list
, flags
);
4478 err
= log_archive(self
->db_env
, &log_list
, flags
, NULL
);
4480 MYDB_END_ALLOW_THREADS
;
4483 list
= PyList_New(0);
4491 char **log_list_start
;
4492 for (log_list_start
= log_list
; *log_list
!= NULL
; ++log_list
) {
4493 item
= PyString_FromString (*log_list
);
4499 PyList_Append(list
, item
);
4502 free(log_list_start
);
4509 DBEnv_txn_stat(DBEnvObject
* self
, PyObject
* args
)
4516 if (!PyArg_ParseTuple(args
, "|i:txn_stat", &flags
))
4518 CHECK_ENV_NOT_CLOSED(self
);
4520 MYDB_BEGIN_ALLOW_THREADS
;
4522 err
= self
->db_env
->txn_stat(self
->db_env
, &sp
, flags
);
4524 err
= txn_stat(self
->db_env
, &sp
);
4526 err
= txn_stat(self
->db_env
, &sp
, NULL
);
4528 MYDB_END_ALLOW_THREADS
;
4531 /* Turn the stat structure into a dictionary */
4538 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4539 #define MAKE_TIME_T_ENTRY(name)_addTimeTToDict(d, #name, sp->st_##name)
4541 MAKE_TIME_T_ENTRY(time_ckp
);
4542 MAKE_ENTRY(last_txnid
);
4543 MAKE_ENTRY(maxtxns
);
4544 MAKE_ENTRY(nactive
);
4545 MAKE_ENTRY(maxnactive
);
4546 MAKE_ENTRY(nbegins
);
4547 MAKE_ENTRY(naborts
);
4548 MAKE_ENTRY(ncommits
);
4549 MAKE_ENTRY(regsize
);
4550 MAKE_ENTRY(region_wait
);
4551 MAKE_ENTRY(region_nowait
);
4554 #undef MAKE_TIME_T_ENTRY
4561 DBEnv_set_get_returns_none(DBEnvObject
* self
, PyObject
* args
)
4566 if (!PyArg_ParseTuple(args
,"i:set_get_returns_none", &flags
))
4568 CHECK_ENV_NOT_CLOSED(self
);
4570 if (self
->moduleFlags
.getReturnsNone
)
4572 if (self
->moduleFlags
.cursorSetReturnsNone
)
4574 self
->moduleFlags
.getReturnsNone
= (flags
>= 1);
4575 self
->moduleFlags
.cursorSetReturnsNone
= (flags
>= 2);
4576 return PyInt_FromLong(oldValue
);
4580 /* --------------------------------------------------------------------- */
4585 DBTxn_commit(DBTxnObject
* self
, PyObject
* args
)
4590 if (!PyArg_ParseTuple(args
, "|i:commit", &flags
))
4594 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
4595 "after txn_commit or txn_abort");
4596 PyErr_SetObject(DBError
, t
);
4601 self
->txn
= NULL
; /* this DB_TXN is no longer valid after this call */
4602 MYDB_BEGIN_ALLOW_THREADS
;
4604 err
= txn
->commit(txn
, flags
);
4606 err
= txn_commit(txn
, flags
);
4608 MYDB_END_ALLOW_THREADS
;
4614 DBTxn_prepare(DBTxnObject
* self
, PyObject
* args
)
4621 if (!PyArg_ParseTuple(args
, "s#:prepare", &gid
, &gid_size
))
4624 if (gid_size
!= DB_XIDDATASIZE
) {
4625 PyErr_SetString(PyExc_TypeError
,
4626 "gid must be DB_XIDDATASIZE bytes long");
4631 PyObject
*t
= Py_BuildValue("(is)", 0,"DBTxn must not be used "
4632 "after txn_commit or txn_abort");
4633 PyErr_SetObject(DBError
, t
);
4637 MYDB_BEGIN_ALLOW_THREADS
;
4639 err
= self
->txn
->prepare(self
->txn
, (u_int8_t
*)gid
);
4641 err
= txn_prepare(self
->txn
, (u_int8_t
*)gid
);
4643 MYDB_END_ALLOW_THREADS
;
4649 if (!PyArg_ParseTuple(args
, ":prepare"))
4653 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
4654 "after txn_commit or txn_abort");
4655 PyErr_SetObject(DBError
, t
);
4659 MYDB_BEGIN_ALLOW_THREADS
;
4660 err
= txn_prepare(self
->txn
);
4661 MYDB_END_ALLOW_THREADS
;
4669 DBTxn_abort(DBTxnObject
* self
, PyObject
* args
)
4674 if (!PyArg_ParseTuple(args
, ":abort"))
4678 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
4679 "after txn_commit or txn_abort");
4680 PyErr_SetObject(DBError
, t
);
4685 self
->txn
= NULL
; /* this DB_TXN is no longer valid after this call */
4686 MYDB_BEGIN_ALLOW_THREADS
;
4688 err
= txn
->abort(txn
);
4690 err
= txn_abort(txn
);
4692 MYDB_END_ALLOW_THREADS
;
4699 DBTxn_id(DBTxnObject
* self
, PyObject
* args
)
4703 if (!PyArg_ParseTuple(args
, ":id"))
4707 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
4708 "after txn_commit or txn_abort");
4709 PyErr_SetObject(DBError
, t
);
4713 MYDB_BEGIN_ALLOW_THREADS
;
4715 id
= self
->txn
->id(self
->txn
);
4717 id
= txn_id(self
->txn
);
4719 MYDB_END_ALLOW_THREADS
;
4720 return PyInt_FromLong(id
);
4724 /* --------------------------------------------------------------------- */
4725 /* DBSequence methods */
4729 DBSequence_close(DBSequenceObject
* self
, PyObject
* args
)
4732 if (!PyArg_ParseTuple(args
,"|i:close", &flags
))
4734 CHECK_SEQUENCE_NOT_CLOSED(self
)
4736 MYDB_BEGIN_ALLOW_THREADS
4737 err
= self
->sequence
->close(self
->sequence
, flags
);
4738 self
->sequence
= NULL
;
4739 MYDB_END_ALLOW_THREADS
4747 DBSequence_get(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4752 PyObject
*txnobj
= NULL
;
4754 static char* kwnames
[] = {"delta", "txn", "flags", NULL
};
4755 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|iOi:get", kwnames
, &delta
, &txnobj
, &flags
))
4757 CHECK_SEQUENCE_NOT_CLOSED(self
)
4759 if (!checkTxnObj(txnobj
, &txn
))
4762 MYDB_BEGIN_ALLOW_THREADS
4763 err
= self
->sequence
->get(self
->sequence
, txn
, delta
, &value
, flags
);
4764 MYDB_END_ALLOW_THREADS
4767 return PyLong_FromLongLong(value
);
4772 DBSequence_get_dbp(DBSequenceObject
* self
, PyObject
* args
)
4774 if (!PyArg_ParseTuple(args
,":get_dbp"))
4776 CHECK_SEQUENCE_NOT_CLOSED(self
)
4777 Py_INCREF(self
->mydb
);
4778 return (PyObject
* )self
->mydb
;
4782 DBSequence_get_key(DBSequenceObject
* self
, PyObject
* args
)
4786 PyObject
*retval
= NULL
;
4787 key
.flags
= DB_DBT_MALLOC
;
4788 CHECK_SEQUENCE_NOT_CLOSED(self
)
4789 MYDB_BEGIN_ALLOW_THREADS
4790 err
= self
->sequence
->get_key(self
->sequence
, &key
);
4791 MYDB_END_ALLOW_THREADS
4794 retval
= PyString_FromStringAndSize(key
.data
, key
.size
);
4803 DBSequence_init_value(DBSequenceObject
* self
, PyObject
* args
)
4807 if (!PyArg_ParseTuple(args
,"L:init_value", &value
))
4809 CHECK_SEQUENCE_NOT_CLOSED(self
)
4811 MYDB_BEGIN_ALLOW_THREADS
4812 err
= self
->sequence
->initial_value(self
->sequence
, value
);
4813 MYDB_END_ALLOW_THREADS
4821 DBSequence_open(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4825 PyObject
*txnobj
= NULL
;
4829 static char* kwnames
[] = {"key", "txn", "flags", NULL
};
4830 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oi:open", kwnames
, &keyobj
, &txnobj
, &flags
))
4833 if (!checkTxnObj(txnobj
, &txn
))
4836 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
4839 MYDB_BEGIN_ALLOW_THREADS
4840 err
= self
->sequence
->open(self
->sequence
, txn
, &key
, flags
);
4841 MYDB_END_ALLOW_THREADS
4850 DBSequence_remove(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4853 PyObject
*txnobj
= NULL
;
4856 static char* kwnames
[] = {"txn", "flags", NULL
};
4857 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:remove", kwnames
, &txnobj
, &flags
))
4860 if (!checkTxnObj(txnobj
, &txn
))
4863 CHECK_SEQUENCE_NOT_CLOSED(self
)
4865 MYDB_BEGIN_ALLOW_THREADS
4866 err
= self
->sequence
->remove(self
->sequence
, txn
, flags
);
4867 MYDB_END_ALLOW_THREADS
4874 DBSequence_set_cachesize(DBSequenceObject
* self
, PyObject
* args
)
4877 if (!PyArg_ParseTuple(args
,"i:set_cachesize", &size
))
4879 CHECK_SEQUENCE_NOT_CLOSED(self
)
4881 MYDB_BEGIN_ALLOW_THREADS
4882 err
= self
->sequence
->set_cachesize(self
->sequence
, size
);
4883 MYDB_END_ALLOW_THREADS
4890 DBSequence_get_cachesize(DBSequenceObject
* self
, PyObject
* args
)
4893 if (!PyArg_ParseTuple(args
,":get_cachesize"))
4895 CHECK_SEQUENCE_NOT_CLOSED(self
)
4897 MYDB_BEGIN_ALLOW_THREADS
4898 err
= self
->sequence
->get_cachesize(self
->sequence
, &size
);
4899 MYDB_END_ALLOW_THREADS
4902 return PyInt_FromLong(size
);
4906 DBSequence_set_flags(DBSequenceObject
* self
, PyObject
* args
)
4909 if (!PyArg_ParseTuple(args
,"i:set_flags", &flags
))
4911 CHECK_SEQUENCE_NOT_CLOSED(self
)
4913 MYDB_BEGIN_ALLOW_THREADS
4914 err
= self
->sequence
->set_flags(self
->sequence
, flags
);
4915 MYDB_END_ALLOW_THREADS
4923 DBSequence_get_flags(DBSequenceObject
* self
, PyObject
* args
)
4927 if (!PyArg_ParseTuple(args
,":get_flags"))
4929 CHECK_SEQUENCE_NOT_CLOSED(self
)
4931 MYDB_BEGIN_ALLOW_THREADS
4932 err
= self
->sequence
->get_flags(self
->sequence
, &flags
);
4933 MYDB_END_ALLOW_THREADS
4936 return PyInt_FromLong((int)flags
);
4940 DBSequence_set_range(DBSequenceObject
* self
, PyObject
* args
)
4944 if (!PyArg_ParseTuple(args
,"(LL):set_range", &min
, &max
))
4946 CHECK_SEQUENCE_NOT_CLOSED(self
)
4948 MYDB_BEGIN_ALLOW_THREADS
4949 err
= self
->sequence
->set_range(self
->sequence
, min
, max
);
4950 MYDB_END_ALLOW_THREADS
4957 DBSequence_get_range(DBSequenceObject
* self
, PyObject
* args
)
4961 if (!PyArg_ParseTuple(args
,":get_range"))
4963 CHECK_SEQUENCE_NOT_CLOSED(self
)
4965 MYDB_BEGIN_ALLOW_THREADS
4966 err
= self
->sequence
->get_range(self
->sequence
, &min
, &max
);
4967 MYDB_END_ALLOW_THREADS
4970 return Py_BuildValue("(LL)", min
, max
);
4974 DBSequence_stat(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4977 DB_SEQUENCE_STAT
* sp
= NULL
;
4978 PyObject
* dict_stat
;
4979 static char* kwnames
[] = {"flags", NULL
};
4980 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:stat", kwnames
, &flags
))
4982 CHECK_SEQUENCE_NOT_CLOSED(self
);
4984 MYDB_BEGIN_ALLOW_THREADS
;
4985 err
= self
->sequence
->stat(self
->sequence
, &sp
, flags
);
4986 MYDB_END_ALLOW_THREADS
;
4989 if ((dict_stat
= PyDict_New()) == NULL
) {
4995 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
4996 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
4998 MAKE_INT_ENTRY(wait
);
4999 MAKE_INT_ENTRY(nowait
);
5000 MAKE_LONG_LONG_ENTRY(current
);
5001 MAKE_LONG_LONG_ENTRY(value
);
5002 MAKE_LONG_LONG_ENTRY(last_value
);
5003 MAKE_LONG_LONG_ENTRY(min
);
5004 MAKE_LONG_LONG_ENTRY(max
);
5005 MAKE_INT_ENTRY(cache_size
);
5006 MAKE_INT_ENTRY(flags
);
5008 #undef MAKE_INT_ENTRY
5009 #undef MAKE_LONG_LONG_ENTRY
5017 /* --------------------------------------------------------------------- */
5018 /* Method definition tables and type objects */
5020 static PyMethodDef DB_methods
[] = {
5021 {"append", (PyCFunction
)DB_append
, METH_VARARGS
},
5023 {"associate", (PyCFunction
)DB_associate
, METH_VARARGS
|METH_KEYWORDS
},
5025 {"close", (PyCFunction
)DB_close
, METH_VARARGS
},
5026 {"consume", (PyCFunction
)DB_consume
, METH_VARARGS
|METH_KEYWORDS
},
5027 {"consume_wait", (PyCFunction
)DB_consume_wait
, METH_VARARGS
|METH_KEYWORDS
},
5028 {"cursor", (PyCFunction
)DB_cursor
, METH_VARARGS
|METH_KEYWORDS
},
5029 {"delete", (PyCFunction
)DB_delete
, METH_VARARGS
|METH_KEYWORDS
},
5030 {"fd", (PyCFunction
)DB_fd
, METH_VARARGS
},
5031 {"get", (PyCFunction
)DB_get
, METH_VARARGS
|METH_KEYWORDS
},
5033 {"pget", (PyCFunction
)DB_pget
, METH_VARARGS
|METH_KEYWORDS
},
5035 {"get_both", (PyCFunction
)DB_get_both
, METH_VARARGS
|METH_KEYWORDS
},
5036 {"get_byteswapped", (PyCFunction
)DB_get_byteswapped
,METH_VARARGS
},
5037 {"get_size", (PyCFunction
)DB_get_size
, METH_VARARGS
|METH_KEYWORDS
},
5038 {"get_type", (PyCFunction
)DB_get_type
, METH_VARARGS
},
5039 {"join", (PyCFunction
)DB_join
, METH_VARARGS
},
5040 {"key_range", (PyCFunction
)DB_key_range
, METH_VARARGS
|METH_KEYWORDS
},
5041 {"has_key", (PyCFunction
)DB_has_key
, METH_VARARGS
},
5042 {"items", (PyCFunction
)DB_items
, METH_VARARGS
},
5043 {"keys", (PyCFunction
)DB_keys
, METH_VARARGS
},
5044 {"open", (PyCFunction
)DB_open
, METH_VARARGS
|METH_KEYWORDS
},
5045 {"put", (PyCFunction
)DB_put
, METH_VARARGS
|METH_KEYWORDS
},
5046 {"remove", (PyCFunction
)DB_remove
, METH_VARARGS
|METH_KEYWORDS
},
5047 {"rename", (PyCFunction
)DB_rename
, METH_VARARGS
},
5048 {"set_bt_minkey", (PyCFunction
)DB_set_bt_minkey
, METH_VARARGS
},
5050 {"set_bt_compare", (PyCFunction
)DB_set_bt_compare
, METH_VARARGS
},
5052 {"set_cachesize", (PyCFunction
)DB_set_cachesize
, METH_VARARGS
},
5054 {"set_encrypt", (PyCFunction
)DB_set_encrypt
, METH_VARARGS
|METH_KEYWORDS
},
5056 {"set_flags", (PyCFunction
)DB_set_flags
, METH_VARARGS
},
5057 {"set_h_ffactor", (PyCFunction
)DB_set_h_ffactor
, METH_VARARGS
},
5058 {"set_h_nelem", (PyCFunction
)DB_set_h_nelem
, METH_VARARGS
},
5059 {"set_lorder", (PyCFunction
)DB_set_lorder
, METH_VARARGS
},
5060 {"set_pagesize", (PyCFunction
)DB_set_pagesize
, METH_VARARGS
},
5061 {"set_re_delim", (PyCFunction
)DB_set_re_delim
, METH_VARARGS
},
5062 {"set_re_len", (PyCFunction
)DB_set_re_len
, METH_VARARGS
},
5063 {"set_re_pad", (PyCFunction
)DB_set_re_pad
, METH_VARARGS
},
5064 {"set_re_source", (PyCFunction
)DB_set_re_source
, METH_VARARGS
},
5065 {"set_q_extentsize",(PyCFunction
)DB_set_q_extentsize
,METH_VARARGS
},
5066 {"stat", (PyCFunction
)DB_stat
, METH_VARARGS
|METH_KEYWORDS
},
5067 {"sync", (PyCFunction
)DB_sync
, METH_VARARGS
},
5069 {"truncate", (PyCFunction
)DB_truncate
, METH_VARARGS
|METH_KEYWORDS
},
5071 {"type", (PyCFunction
)DB_get_type
, METH_VARARGS
},
5072 {"upgrade", (PyCFunction
)DB_upgrade
, METH_VARARGS
},
5073 {"values", (PyCFunction
)DB_values
, METH_VARARGS
},
5074 {"verify", (PyCFunction
)DB_verify
, METH_VARARGS
|METH_KEYWORDS
},
5075 {"set_get_returns_none",(PyCFunction
)DB_set_get_returns_none
, METH_VARARGS
},
5076 {NULL
, NULL
} /* sentinel */
5080 static PyMappingMethods DB_mapping
= {
5081 DB_length
, /*mp_length*/
5082 (binaryfunc
)DB_subscript
, /*mp_subscript*/
5083 (objobjargproc
)DB_ass_sub
, /*mp_ass_subscript*/
5087 static PyMethodDef DBCursor_methods
[] = {
5088 {"close", (PyCFunction
)DBC_close
, METH_VARARGS
},
5089 {"count", (PyCFunction
)DBC_count
, METH_VARARGS
},
5090 {"current", (PyCFunction
)DBC_current
, METH_VARARGS
|METH_KEYWORDS
},
5091 {"delete", (PyCFunction
)DBC_delete
, METH_VARARGS
},
5092 {"dup", (PyCFunction
)DBC_dup
, METH_VARARGS
},
5093 {"first", (PyCFunction
)DBC_first
, METH_VARARGS
|METH_KEYWORDS
},
5094 {"get", (PyCFunction
)DBC_get
, METH_VARARGS
|METH_KEYWORDS
},
5096 {"pget", (PyCFunction
)DBC_pget
, METH_VARARGS
|METH_KEYWORDS
},
5098 {"get_recno", (PyCFunction
)DBC_get_recno
, METH_VARARGS
},
5099 {"last", (PyCFunction
)DBC_last
, METH_VARARGS
|METH_KEYWORDS
},
5100 {"next", (PyCFunction
)DBC_next
, METH_VARARGS
|METH_KEYWORDS
},
5101 {"prev", (PyCFunction
)DBC_prev
, METH_VARARGS
|METH_KEYWORDS
},
5102 {"put", (PyCFunction
)DBC_put
, METH_VARARGS
|METH_KEYWORDS
},
5103 {"set", (PyCFunction
)DBC_set
, METH_VARARGS
|METH_KEYWORDS
},
5104 {"set_range", (PyCFunction
)DBC_set_range
, METH_VARARGS
|METH_KEYWORDS
},
5105 {"get_both", (PyCFunction
)DBC_get_both
, METH_VARARGS
},
5106 {"get_current_size",(PyCFunction
)DBC_get_current_size
, METH_VARARGS
},
5107 {"set_both", (PyCFunction
)DBC_set_both
, METH_VARARGS
},
5108 {"set_recno", (PyCFunction
)DBC_set_recno
, METH_VARARGS
|METH_KEYWORDS
},
5109 {"consume", (PyCFunction
)DBC_consume
, METH_VARARGS
|METH_KEYWORDS
},
5110 {"next_dup", (PyCFunction
)DBC_next_dup
, METH_VARARGS
|METH_KEYWORDS
},
5111 {"next_nodup", (PyCFunction
)DBC_next_nodup
, METH_VARARGS
|METH_KEYWORDS
},
5112 {"prev_nodup", (PyCFunction
)DBC_prev_nodup
, METH_VARARGS
|METH_KEYWORDS
},
5113 {"join_item", (PyCFunction
)DBC_join_item
, METH_VARARGS
},
5114 {NULL
, NULL
} /* sentinel */
5118 static PyMethodDef DBEnv_methods
[] = {
5119 {"close", (PyCFunction
)DBEnv_close
, METH_VARARGS
},
5120 {"open", (PyCFunction
)DBEnv_open
, METH_VARARGS
},
5121 {"remove", (PyCFunction
)DBEnv_remove
, METH_VARARGS
},
5123 {"dbremove", (PyCFunction
)DBEnv_dbremove
, METH_VARARGS
|METH_KEYWORDS
},
5124 {"dbrename", (PyCFunction
)DBEnv_dbrename
, METH_VARARGS
|METH_KEYWORDS
},
5125 {"set_encrypt", (PyCFunction
)DBEnv_set_encrypt
, METH_VARARGS
|METH_KEYWORDS
},
5128 {"set_timeout", (PyCFunction
)DBEnv_set_timeout
, METH_VARARGS
|METH_KEYWORDS
},
5130 {"set_shm_key", (PyCFunction
)DBEnv_set_shm_key
, METH_VARARGS
},
5131 {"set_cachesize", (PyCFunction
)DBEnv_set_cachesize
, METH_VARARGS
},
5132 {"set_data_dir", (PyCFunction
)DBEnv_set_data_dir
, METH_VARARGS
},
5133 {"set_flags", (PyCFunction
)DBEnv_set_flags
, METH_VARARGS
},
5134 {"set_lg_bsize", (PyCFunction
)DBEnv_set_lg_bsize
, METH_VARARGS
},
5135 {"set_lg_dir", (PyCFunction
)DBEnv_set_lg_dir
, METH_VARARGS
},
5136 {"set_lg_max", (PyCFunction
)DBEnv_set_lg_max
, METH_VARARGS
},
5138 {"set_lg_regionmax",(PyCFunction
)DBEnv_set_lg_regionmax
, METH_VARARGS
},
5140 {"set_lk_detect", (PyCFunction
)DBEnv_set_lk_detect
, METH_VARARGS
},
5142 {"set_lk_max", (PyCFunction
)DBEnv_set_lk_max
, METH_VARARGS
},
5144 {"set_lk_max_locks", (PyCFunction
)DBEnv_set_lk_max_locks
, METH_VARARGS
},
5145 {"set_lk_max_lockers", (PyCFunction
)DBEnv_set_lk_max_lockers
, METH_VARARGS
},
5146 {"set_lk_max_objects", (PyCFunction
)DBEnv_set_lk_max_objects
, METH_VARARGS
},
5147 {"set_mp_mmapsize", (PyCFunction
)DBEnv_set_mp_mmapsize
, METH_VARARGS
},
5148 {"set_tmp_dir", (PyCFunction
)DBEnv_set_tmp_dir
, METH_VARARGS
},
5149 {"txn_begin", (PyCFunction
)DBEnv_txn_begin
, METH_VARARGS
|METH_KEYWORDS
},
5150 {"txn_checkpoint", (PyCFunction
)DBEnv_txn_checkpoint
, METH_VARARGS
},
5151 {"txn_stat", (PyCFunction
)DBEnv_txn_stat
, METH_VARARGS
},
5152 {"set_tx_max", (PyCFunction
)DBEnv_set_tx_max
, METH_VARARGS
},
5153 {"set_tx_timestamp", (PyCFunction
)DBEnv_set_tx_timestamp
, METH_VARARGS
},
5154 {"lock_detect", (PyCFunction
)DBEnv_lock_detect
, METH_VARARGS
},
5155 {"lock_get", (PyCFunction
)DBEnv_lock_get
, METH_VARARGS
},
5156 {"lock_id", (PyCFunction
)DBEnv_lock_id
, METH_VARARGS
},
5158 {"lock_id_free", (PyCFunction
)DBEnv_lock_id_free
, METH_VARARGS
},
5160 {"lock_put", (PyCFunction
)DBEnv_lock_put
, METH_VARARGS
},
5161 {"lock_stat", (PyCFunction
)DBEnv_lock_stat
, METH_VARARGS
},
5162 {"log_archive", (PyCFunction
)DBEnv_log_archive
, METH_VARARGS
},
5164 {"log_stat", (PyCFunction
)DBEnv_log_stat
, METH_VARARGS
},
5167 {"lsn_reset", (PyCFunction
)DBEnv_lsn_reset
, METH_VARARGS
|METH_KEYWORDS
},
5169 {"set_get_returns_none",(PyCFunction
)DBEnv_set_get_returns_none
, METH_VARARGS
},
5170 {NULL
, NULL
} /* sentinel */
5174 static PyMethodDef DBTxn_methods
[] = {
5175 {"commit", (PyCFunction
)DBTxn_commit
, METH_VARARGS
},
5176 {"prepare", (PyCFunction
)DBTxn_prepare
, METH_VARARGS
},
5177 {"abort", (PyCFunction
)DBTxn_abort
, METH_VARARGS
},
5178 {"id", (PyCFunction
)DBTxn_id
, METH_VARARGS
},
5179 {NULL
, NULL
} /* sentinel */
5184 static PyMethodDef DBSequence_methods
[] = {
5185 {"close", (PyCFunction
)DBSequence_close
, METH_VARARGS
},
5186 {"get", (PyCFunction
)DBSequence_get
, METH_VARARGS
|METH_KEYWORDS
},
5187 {"get_dbp", (PyCFunction
)DBSequence_get_dbp
, METH_VARARGS
},
5188 {"get_key", (PyCFunction
)DBSequence_get_key
, METH_VARARGS
},
5189 {"init_value", (PyCFunction
)DBSequence_init_value
, METH_VARARGS
},
5190 {"open", (PyCFunction
)DBSequence_open
, METH_VARARGS
|METH_KEYWORDS
},
5191 {"remove", (PyCFunction
)DBSequence_remove
, METH_VARARGS
|METH_KEYWORDS
},
5192 {"set_cachesize", (PyCFunction
)DBSequence_set_cachesize
, METH_VARARGS
},
5193 {"get_cachesize", (PyCFunction
)DBSequence_get_cachesize
, METH_VARARGS
},
5194 {"set_flags", (PyCFunction
)DBSequence_set_flags
, METH_VARARGS
},
5195 {"get_flags", (PyCFunction
)DBSequence_get_flags
, METH_VARARGS
},
5196 {"set_range", (PyCFunction
)DBSequence_set_range
, METH_VARARGS
},
5197 {"get_range", (PyCFunction
)DBSequence_get_range
, METH_VARARGS
},
5198 {"stat", (PyCFunction
)DBSequence_stat
, METH_VARARGS
|METH_KEYWORDS
},
5199 {NULL
, NULL
} /* sentinel */
5205 DB_getattr(DBObject
* self
, char *name
)
5207 return Py_FindMethod(DB_methods
, (PyObject
* )self
, name
);
5212 DBEnv_getattr(DBEnvObject
* self
, char *name
)
5214 if (!strcmp(name
, "db_home")) {
5215 CHECK_ENV_NOT_CLOSED(self
);
5216 if (self
->db_env
->db_home
== NULL
) {
5219 return PyString_FromString(self
->db_env
->db_home
);
5222 return Py_FindMethod(DBEnv_methods
, (PyObject
* )self
, name
);
5227 DBCursor_getattr(DBCursorObject
* self
, char *name
)
5229 return Py_FindMethod(DBCursor_methods
, (PyObject
* )self
, name
);
5233 DBTxn_getattr(DBTxnObject
* self
, char *name
)
5235 return Py_FindMethod(DBTxn_methods
, (PyObject
* )self
, name
);
5239 DBLock_getattr(DBLockObject
* self
, char *name
)
5246 DBSequence_getattr(DBSequenceObject
* self
, char *name
)
5248 return Py_FindMethod(DBSequence_methods
, (PyObject
* )self
, name
);
5252 statichere PyTypeObject DB_Type
= {
5253 PyObject_HEAD_INIT(NULL
)
5256 sizeof(DBObject
), /*tp_basicsize*/
5259 (destructor
)DB_dealloc
, /*tp_dealloc*/
5261 (getattrfunc
)DB_getattr
, /*tp_getattr*/
5266 0, /*tp_as_sequence*/
5267 &DB_mapping
,/*tp_as_mapping*/
5271 0, /* tp_getattro */
5272 0, /* tp_setattro */
5273 0, /* tp_as_buffer */
5274 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
5276 0, /* tp_traverse */
5278 0, /* tp_richcompare */
5279 offsetof(DBObject
, in_weakreflist
), /* tp_weaklistoffset */
5283 statichere PyTypeObject DBCursor_Type
= {
5284 PyObject_HEAD_INIT(NULL
)
5286 "DBCursor", /*tp_name*/
5287 sizeof(DBCursorObject
), /*tp_basicsize*/
5290 (destructor
)DBCursor_dealloc
,/*tp_dealloc*/
5292 (getattrfunc
)DBCursor_getattr
, /*tp_getattr*/
5297 0, /*tp_as_sequence*/
5298 0, /*tp_as_mapping*/
5302 0, /* tp_getattro */
5303 0, /* tp_setattro */
5304 0, /* tp_as_buffer */
5305 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
5307 0, /* tp_traverse */
5309 0, /* tp_richcompare */
5310 offsetof(DBCursorObject
, in_weakreflist
), /* tp_weaklistoffset */
5314 statichere PyTypeObject DBEnv_Type
= {
5315 PyObject_HEAD_INIT(NULL
)
5317 "DBEnv", /*tp_name*/
5318 sizeof(DBEnvObject
), /*tp_basicsize*/
5321 (destructor
)DBEnv_dealloc
, /*tp_dealloc*/
5323 (getattrfunc
)DBEnv_getattr
, /*tp_getattr*/
5328 0, /*tp_as_sequence*/
5329 0, /*tp_as_mapping*/
5333 0, /* tp_getattro */
5334 0, /* tp_setattro */
5335 0, /* tp_as_buffer */
5336 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
5338 0, /* tp_traverse */
5340 0, /* tp_richcompare */
5341 offsetof(DBEnvObject
, in_weakreflist
), /* tp_weaklistoffset */
5344 statichere PyTypeObject DBTxn_Type
= {
5345 PyObject_HEAD_INIT(NULL
)
5347 "DBTxn", /*tp_name*/
5348 sizeof(DBTxnObject
), /*tp_basicsize*/
5351 (destructor
)DBTxn_dealloc
, /*tp_dealloc*/
5353 (getattrfunc
)DBTxn_getattr
, /*tp_getattr*/
5358 0, /*tp_as_sequence*/
5359 0, /*tp_as_mapping*/
5363 0, /* tp_getattro */
5364 0, /* tp_setattro */
5365 0, /* tp_as_buffer */
5366 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
5368 0, /* tp_traverse */
5370 0, /* tp_richcompare */
5371 offsetof(DBTxnObject
, in_weakreflist
), /* tp_weaklistoffset */
5375 statichere PyTypeObject DBLock_Type
= {
5376 PyObject_HEAD_INIT(NULL
)
5378 "DBLock", /*tp_name*/
5379 sizeof(DBLockObject
), /*tp_basicsize*/
5382 (destructor
)DBLock_dealloc
, /*tp_dealloc*/
5384 (getattrfunc
)DBLock_getattr
, /*tp_getattr*/
5389 0, /*tp_as_sequence*/
5390 0, /*tp_as_mapping*/
5394 0, /* tp_getattro */
5395 0, /* tp_setattro */
5396 0, /* tp_as_buffer */
5397 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
5399 0, /* tp_traverse */
5401 0, /* tp_richcompare */
5402 offsetof(DBLockObject
, in_weakreflist
), /* tp_weaklistoffset */
5406 statichere PyTypeObject DBSequence_Type
= {
5407 PyObject_HEAD_INIT(NULL
)
5409 "DBSequence", /*tp_name*/
5410 sizeof(DBSequenceObject
), /*tp_basicsize*/
5413 (destructor
)DBSequence_dealloc
, /*tp_dealloc*/
5415 (getattrfunc
)DBSequence_getattr
,/*tp_getattr*/
5420 0, /*tp_as_sequence*/
5421 0, /*tp_as_mapping*/
5425 0, /* tp_getattro */
5426 0, /* tp_setattro */
5427 0, /* tp_as_buffer */
5428 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
5430 0, /* tp_traverse */
5432 0, /* tp_richcompare */
5433 offsetof(DBSequenceObject
, in_weakreflist
), /* tp_weaklistoffset */
5437 /* --------------------------------------------------------------------- */
5438 /* Module-level functions */
5441 DB_construct(PyObject
* self
, PyObject
* args
, PyObject
* kwargs
)
5443 PyObject
* dbenvobj
= NULL
;
5445 static char* kwnames
[] = { "dbEnv", "flags", NULL
};
5447 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:DB", kwnames
,
5450 if (dbenvobj
== Py_None
)
5452 else if (dbenvobj
&& !DBEnvObject_Check(dbenvobj
)) {
5453 makeTypeError("DBEnv", dbenvobj
);
5457 return (PyObject
* )newDBObject((DBEnvObject
*)dbenvobj
, flags
);
5462 DBEnv_construct(PyObject
* self
, PyObject
* args
)
5465 if (!PyArg_ParseTuple(args
, "|i:DbEnv", &flags
)) return NULL
;
5466 return (PyObject
* )newDBEnvObject(flags
);
5471 DBSequence_construct(PyObject
* self
, PyObject
* args
, PyObject
* kwargs
)
5475 static char* kwnames
[] = { "db", "flags", NULL
};
5477 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|i:DBSequence", kwnames
, &dbobj
, &flags
))
5479 if (!DBObject_Check(dbobj
)) {
5480 makeTypeError("DB", dbobj
);
5483 return (PyObject
* )newDBSequenceObject((DBObject
*)dbobj
, flags
);
5487 static char bsddb_version_doc
[] =
5488 "Returns a tuple of major, minor, and patch release numbers of the\n\
5489 underlying DB library.";
5492 bsddb_version(PyObject
* self
, PyObject
* args
)
5494 int major
, minor
, patch
;
5496 if (!PyArg_ParseTuple(args
, ":version"))
5498 db_version(&major
, &minor
, &patch
);
5499 return Py_BuildValue("(iii)", major
, minor
, patch
);
5503 /* List of functions defined in the module */
5505 static PyMethodDef bsddb_methods
[] = {
5506 {"DB", (PyCFunction
)DB_construct
, METH_VARARGS
| METH_KEYWORDS
},
5507 {"DBEnv", (PyCFunction
)DBEnv_construct
, METH_VARARGS
},
5509 {"DBSequence", (PyCFunction
)DBSequence_construct
, METH_VARARGS
| METH_KEYWORDS
},
5511 {"version", (PyCFunction
)bsddb_version
, METH_VARARGS
, bsddb_version_doc
},
5512 {NULL
, NULL
} /* sentinel */
5516 static BSDDB_api bsddb_api
;
5519 /* --------------------------------------------------------------------- */
5520 /* Module initialization */
5523 /* Convenience routine to export an integer value.
5524 * Errors are silently ignored, for better or for worse...
5526 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
5528 #define MODULE_NAME_MAX_LEN 11
5529 static char _bsddbModuleName
[MODULE_NAME_MAX_LEN
+1] = "_bsddb";
5531 DL_EXPORT(void) init_bsddb(void)
5535 PyObject
* pybsddb_version_s
= PyString_FromString( PY_BSDDB_VERSION
);
5536 PyObject
* db_version_s
= PyString_FromString( DB_VERSION_STRING
);
5537 PyObject
* cvsid_s
= PyString_FromString( rcs_id
);
5540 /* Initialize the type of the new type objects here; doing it here
5541 is required for portability to Windows without requiring C++. */
5542 Py_TYPE(&DB_Type
) = &PyType_Type
;
5543 Py_TYPE(&DBCursor_Type
) = &PyType_Type
;
5544 Py_TYPE(&DBEnv_Type
) = &PyType_Type
;
5545 Py_TYPE(&DBTxn_Type
) = &PyType_Type
;
5546 Py_TYPE(&DBLock_Type
) = &PyType_Type
;
5548 Py_TYPE(&DBSequence_Type
) = &PyType_Type
;
5552 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
5553 /* Save the current interpreter, so callbacks can do the right thing. */
5554 _db_interpreterState
= PyThreadState_GET()->interp
;
5557 /* Create the module and add the functions */
5558 m
= Py_InitModule(_bsddbModuleName
, bsddb_methods
);
5562 /* Add some symbolic constants to the module */
5563 d
= PyModule_GetDict(m
);
5564 PyDict_SetItemString(d
, "__version__", pybsddb_version_s
);
5565 PyDict_SetItemString(d
, "cvsid", cvsid_s
);
5566 PyDict_SetItemString(d
, "DB_VERSION_STRING", db_version_s
);
5567 Py_DECREF(pybsddb_version_s
);
5568 pybsddb_version_s
= NULL
;
5571 Py_DECREF(db_version_s
);
5572 db_version_s
= NULL
;
5574 ADD_INT(d
, DB_VERSION_MAJOR
);
5575 ADD_INT(d
, DB_VERSION_MINOR
);
5576 ADD_INT(d
, DB_VERSION_PATCH
);
5578 ADD_INT(d
, DB_MAX_PAGES
);
5579 ADD_INT(d
, DB_MAX_RECORDS
);
5582 ADD_INT(d
, DB_RPCCLIENT
);
5584 ADD_INT(d
, DB_CLIENT
);
5585 /* allow apps to be written using DB_RPCCLIENT on older BerkeleyDB */
5586 _addIntToDict(d
, "DB_RPCCLIENT", DB_CLIENT
);
5588 ADD_INT(d
, DB_XA_CREATE
);
5590 ADD_INT(d
, DB_CREATE
);
5591 ADD_INT(d
, DB_NOMMAP
);
5592 ADD_INT(d
, DB_THREAD
);
5594 ADD_INT(d
, DB_FORCE
);
5595 ADD_INT(d
, DB_INIT_CDB
);
5596 ADD_INT(d
, DB_INIT_LOCK
);
5597 ADD_INT(d
, DB_INIT_LOG
);
5598 ADD_INT(d
, DB_INIT_MPOOL
);
5599 ADD_INT(d
, DB_INIT_TXN
);
5600 ADD_INT(d
, DB_JOINENV
);
5602 ADD_INT(d
, DB_RECOVER
);
5603 ADD_INT(d
, DB_RECOVER_FATAL
);
5604 ADD_INT(d
, DB_TXN_NOSYNC
);
5605 ADD_INT(d
, DB_USE_ENVIRON
);
5606 ADD_INT(d
, DB_USE_ENVIRON_ROOT
);
5608 ADD_INT(d
, DB_LOCKDOWN
);
5609 ADD_INT(d
, DB_PRIVATE
);
5610 ADD_INT(d
, DB_SYSTEM_MEM
);
5612 ADD_INT(d
, DB_TXN_SYNC
);
5613 ADD_INT(d
, DB_TXN_NOWAIT
);
5615 ADD_INT(d
, DB_EXCL
);
5616 ADD_INT(d
, DB_FCNTL_LOCKING
);
5617 ADD_INT(d
, DB_ODDFILESIZE
);
5618 ADD_INT(d
, DB_RDWRMASTER
);
5619 ADD_INT(d
, DB_RDONLY
);
5620 ADD_INT(d
, DB_TRUNCATE
);
5621 ADD_INT(d
, DB_EXTENT
);
5622 ADD_INT(d
, DB_CDB_ALLDB
);
5623 ADD_INT(d
, DB_VERIFY
);
5624 ADD_INT(d
, DB_UPGRADE
);
5626 ADD_INT(d
, DB_AGGRESSIVE
);
5627 ADD_INT(d
, DB_NOORDERCHK
);
5628 ADD_INT(d
, DB_ORDERCHKONLY
);
5629 ADD_INT(d
, DB_PR_PAGE
);
5631 ADD_INT(d
, DB_VRFY_FLAGMASK
);
5632 ADD_INT(d
, DB_PR_HEADERS
);
5634 ADD_INT(d
, DB_PR_RECOVERYTEST
);
5635 ADD_INT(d
, DB_SALVAGE
);
5637 ADD_INT(d
, DB_LOCK_NORUN
);
5638 ADD_INT(d
, DB_LOCK_DEFAULT
);
5639 ADD_INT(d
, DB_LOCK_OLDEST
);
5640 ADD_INT(d
, DB_LOCK_RANDOM
);
5641 ADD_INT(d
, DB_LOCK_YOUNGEST
);
5643 ADD_INT(d
, DB_LOCK_MAXLOCKS
);
5644 ADD_INT(d
, DB_LOCK_MINLOCKS
);
5645 ADD_INT(d
, DB_LOCK_MINWRITE
);
5650 /* docs say to use zero instead */
5651 _addIntToDict(d
, "DB_LOCK_CONFLICT", 0);
5653 ADD_INT(d
, DB_LOCK_CONFLICT
);
5656 ADD_INT(d
, DB_LOCK_DUMP
);
5657 ADD_INT(d
, DB_LOCK_GET
);
5658 ADD_INT(d
, DB_LOCK_INHERIT
);
5659 ADD_INT(d
, DB_LOCK_PUT
);
5660 ADD_INT(d
, DB_LOCK_PUT_ALL
);
5661 ADD_INT(d
, DB_LOCK_PUT_OBJ
);
5663 ADD_INT(d
, DB_LOCK_NG
);
5664 ADD_INT(d
, DB_LOCK_READ
);
5665 ADD_INT(d
, DB_LOCK_WRITE
);
5666 ADD_INT(d
, DB_LOCK_NOWAIT
);
5667 ADD_INT(d
, DB_LOCK_WAIT
);
5668 ADD_INT(d
, DB_LOCK_IWRITE
);
5669 ADD_INT(d
, DB_LOCK_IREAD
);
5670 ADD_INT(d
, DB_LOCK_IWR
);
5673 ADD_INT(d
, DB_LOCK_DIRTY
);
5675 ADD_INT(d
, DB_LOCK_READ_UNCOMMITTED
); /* renamed in 4.4 */
5677 ADD_INT(d
, DB_LOCK_WWRITE
);
5680 ADD_INT(d
, DB_LOCK_RECORD
);
5681 ADD_INT(d
, DB_LOCK_UPGRADE
);
5682 ADD_INT(d
, DB_LOCK_SWITCH
);
5684 ADD_INT(d
, DB_LOCK_UPGRADE_WRITE
);
5687 ADD_INT(d
, DB_LOCK_NOWAIT
);
5688 ADD_INT(d
, DB_LOCK_RECORD
);
5689 ADD_INT(d
, DB_LOCK_UPGRADE
);
5692 ADD_INT(d
, DB_LSTAT_ABORTED
);
5694 ADD_INT(d
, DB_LSTAT_ERR
);
5696 ADD_INT(d
, DB_LSTAT_FREE
);
5697 ADD_INT(d
, DB_LSTAT_HELD
);
5699 ADD_INT(d
, DB_LSTAT_NOGRANT
);
5701 ADD_INT(d
, DB_LSTAT_PENDING
);
5702 ADD_INT(d
, DB_LSTAT_WAITING
);
5705 ADD_INT(d
, DB_ARCH_ABS
);
5706 ADD_INT(d
, DB_ARCH_DATA
);
5707 ADD_INT(d
, DB_ARCH_LOG
);
5709 ADD_INT(d
, DB_ARCH_REMOVE
);
5712 ADD_INT(d
, DB_BTREE
);
5713 ADD_INT(d
, DB_HASH
);
5714 ADD_INT(d
, DB_RECNO
);
5715 ADD_INT(d
, DB_QUEUE
);
5716 ADD_INT(d
, DB_UNKNOWN
);
5719 ADD_INT(d
, DB_DUPSORT
);
5720 ADD_INT(d
, DB_RECNUM
);
5721 ADD_INT(d
, DB_RENUMBER
);
5722 ADD_INT(d
, DB_REVSPLITOFF
);
5723 ADD_INT(d
, DB_SNAPSHOT
);
5725 ADD_INT(d
, DB_JOIN_NOSORT
);
5727 ADD_INT(d
, DB_AFTER
);
5728 ADD_INT(d
, DB_APPEND
);
5729 ADD_INT(d
, DB_BEFORE
);
5731 ADD_INT(d
, DB_CACHED_COUNTS
);
5734 _addIntToDict(d
, "DB_CHECKPOINT", 0);
5736 ADD_INT(d
, DB_CHECKPOINT
);
5737 ADD_INT(d
, DB_CURLSN
);
5739 #if ((DBVER >= 33) && (DBVER <= 41))
5740 ADD_INT(d
, DB_COMMIT
);
5742 ADD_INT(d
, DB_CONSUME
);
5743 ADD_INT(d
, DB_CONSUME_WAIT
);
5744 ADD_INT(d
, DB_CURRENT
);
5746 ADD_INT(d
, DB_FAST_STAT
);
5748 ADD_INT(d
, DB_FIRST
);
5749 ADD_INT(d
, DB_FLUSH
);
5750 ADD_INT(d
, DB_GET_BOTH
);
5751 ADD_INT(d
, DB_GET_RECNO
);
5752 ADD_INT(d
, DB_JOIN_ITEM
);
5753 ADD_INT(d
, DB_KEYFIRST
);
5754 ADD_INT(d
, DB_KEYLAST
);
5755 ADD_INT(d
, DB_LAST
);
5756 ADD_INT(d
, DB_NEXT
);
5757 ADD_INT(d
, DB_NEXT_DUP
);
5758 ADD_INT(d
, DB_NEXT_NODUP
);
5759 ADD_INT(d
, DB_NODUPDATA
);
5760 ADD_INT(d
, DB_NOOVERWRITE
);
5761 ADD_INT(d
, DB_NOSYNC
);
5762 ADD_INT(d
, DB_POSITION
);
5763 ADD_INT(d
, DB_PREV
);
5764 ADD_INT(d
, DB_PREV_NODUP
);
5766 ADD_INT(d
, DB_RECORDCOUNT
);
5769 ADD_INT(d
, DB_SET_RANGE
);
5770 ADD_INT(d
, DB_SET_RECNO
);
5771 ADD_INT(d
, DB_WRITECURSOR
);
5773 ADD_INT(d
, DB_OPFLAGS_MASK
);
5776 ADD_INT(d
, DB_DIRTY_READ
);
5777 ADD_INT(d
, DB_MULTIPLE
);
5778 ADD_INT(d
, DB_MULTIPLE_KEY
);
5782 ADD_INT(d
, DB_READ_UNCOMMITTED
); /* replaces DB_DIRTY_READ in 4.4 */
5783 ADD_INT(d
, DB_READ_COMMITTED
);
5787 ADD_INT(d
, DB_DONOTINDEX
);
5791 _addIntToDict(d
, "DB_INCOMPLETE", 0);
5793 ADD_INT(d
, DB_INCOMPLETE
);
5795 ADD_INT(d
, DB_KEYEMPTY
);
5796 ADD_INT(d
, DB_KEYEXIST
);
5797 ADD_INT(d
, DB_LOCK_DEADLOCK
);
5798 ADD_INT(d
, DB_LOCK_NOTGRANTED
);
5799 ADD_INT(d
, DB_NOSERVER
);
5800 ADD_INT(d
, DB_NOSERVER_HOME
);
5801 ADD_INT(d
, DB_NOSERVER_ID
);
5802 ADD_INT(d
, DB_NOTFOUND
);
5803 ADD_INT(d
, DB_OLD_VERSION
);
5804 ADD_INT(d
, DB_RUNRECOVERY
);
5805 ADD_INT(d
, DB_VERIFY_BAD
);
5807 ADD_INT(d
, DB_PAGE_NOTFOUND
);
5808 ADD_INT(d
, DB_SECONDARY_BAD
);
5811 ADD_INT(d
, DB_STAT_CLEAR
);
5812 ADD_INT(d
, DB_REGION_INIT
);
5813 ADD_INT(d
, DB_NOLOCKING
);
5814 ADD_INT(d
, DB_YIELDCPU
);
5815 ADD_INT(d
, DB_PANIC_ENVIRONMENT
);
5816 ADD_INT(d
, DB_NOPANIC
);
5820 ADD_INT(d
, DB_REGISTER
);
5824 ADD_INT(d
, DB_TIME_NOTGRANTED
);
5825 ADD_INT(d
, DB_TXN_NOT_DURABLE
);
5826 ADD_INT(d
, DB_TXN_WRITE_NOSYNC
);
5827 ADD_INT(d
, DB_LOG_AUTOREMOVE
);
5828 ADD_INT(d
, DB_DIRECT_LOG
);
5829 ADD_INT(d
, DB_DIRECT_DB
);
5830 ADD_INT(d
, DB_INIT_REP
);
5831 ADD_INT(d
, DB_ENCRYPT
);
5832 ADD_INT(d
, DB_CHKSUM
);
5836 ADD_INT(d
, DB_LOG_INMEMORY
);
5837 ADD_INT(d
, DB_BUFFER_SMALL
);
5838 ADD_INT(d
, DB_SEQ_DEC
);
5839 ADD_INT(d
, DB_SEQ_INC
);
5840 ADD_INT(d
, DB_SEQ_WRAP
);
5844 ADD_INT(d
, DB_ENCRYPT_AES
);
5845 ADD_INT(d
, DB_AUTO_COMMIT
);
5847 /* allow berkeleydb 4.1 aware apps to run on older versions */
5848 _addIntToDict(d
, "DB_AUTO_COMMIT", 0);
5862 ADD_INT(d
, DB_SET_LOCK_TIMEOUT
);
5863 ADD_INT(d
, DB_SET_TXN_TIMEOUT
);
5866 /* The exception name must be correct for pickled exception *
5867 * objects to unpickle properly. */
5868 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
5869 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
5871 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
5874 /* All the rest of the exceptions derive only from DBError */
5875 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
5876 PyDict_SetItemString(d, #name, name)
5878 /* The base exception class is DBError */
5879 DBError
= NULL
; /* used in MAKE_EX so that it derives from nothing */
5882 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
5883 * from both DBError and KeyError, since the API only supports
5884 * using one base class. */
5885 PyDict_SetItemString(d
, "KeyError", PyExc_KeyError
);
5886 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
5887 "class DBKeyEmptyError(DBError, KeyError): pass",
5888 Py_file_input
, d
, d
);
5889 DBNotFoundError
= PyDict_GetItemString(d
, "DBNotFoundError");
5890 DBKeyEmptyError
= PyDict_GetItemString(d
, "DBKeyEmptyError");
5891 PyDict_DelItemString(d
, "KeyError");
5894 #if !INCOMPLETE_IS_WARNING
5895 MAKE_EX(DBIncompleteError
);
5897 MAKE_EX(DBCursorClosedError
);
5898 MAKE_EX(DBKeyEmptyError
);
5899 MAKE_EX(DBKeyExistError
);
5900 MAKE_EX(DBLockDeadlockError
);
5901 MAKE_EX(DBLockNotGrantedError
);
5902 MAKE_EX(DBOldVersionError
);
5903 MAKE_EX(DBRunRecoveryError
);
5904 MAKE_EX(DBVerifyBadError
);
5905 MAKE_EX(DBNoServerError
);
5906 MAKE_EX(DBNoServerHomeError
);
5907 MAKE_EX(DBNoServerIDError
);
5909 MAKE_EX(DBPageNotFoundError
);
5910 MAKE_EX(DBSecondaryBadError
);
5913 MAKE_EX(DBInvalidArgError
);
5914 MAKE_EX(DBAccessError
);
5915 MAKE_EX(DBNoSpaceError
);
5916 MAKE_EX(DBNoMemoryError
);
5917 MAKE_EX(DBAgainError
);
5918 MAKE_EX(DBBusyError
);
5919 MAKE_EX(DBFileExistsError
);
5920 MAKE_EX(DBNoSuchFileError
);
5921 MAKE_EX(DBPermissionsError
);
5925 /* Initiliase the C API structure and add it to the module */
5926 bsddb_api
.db_type
= &DB_Type
;
5927 bsddb_api
.dbcursor_type
= &DBCursor_Type
;
5928 bsddb_api
.dbenv_type
= &DBEnv_Type
;
5929 bsddb_api
.dbtxn_type
= &DBTxn_Type
;
5930 bsddb_api
.dblock_type
= &DBLock_Type
;
5932 bsddb_api
.dbsequence_type
= &DBSequence_Type
;
5934 bsddb_api
.makeDBError
= makeDBError
;
5936 py_api
= PyCObject_FromVoidPtr((void*)&bsddb_api
, NULL
);
5937 PyDict_SetItemString(d
, "api", py_api
);
5940 /* Check for errors */
5941 if (PyErr_Occurred()) {
5943 Py_FatalError("can't initialize module _bsddb");
5947 /* allow this module to be named _pybsddb so that it can be installed
5948 * and imported on top of python >= 2.3 that includes its own older
5949 * copy of the library named _bsddb without importing the old version. */
5950 DL_EXPORT(void) init_pybsddb(void)
5952 strncpy(_bsddbModuleName
, "_pybsddb", MODULE_NAME_MAX_LEN
);