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 Berkeley DB 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> was once again the maintainer.
53 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
54 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
57 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
60 * http://pybsddb.sf.net
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
65 * http://www.python.org/peps/pep-0291.html
67 * This module contains 6 types:
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
74 * DBSequence (Sequence)
78 /* --------------------------------------------------------------------- */
81 * Portions of this module, associated unit tests and build scripts are the
82 * result of a contract with The Written Word (http://thewrittenword.com/)
83 * Many thanks go out to them for causing me to raise the bar on quality and
84 * functionality, resulting in a better bsddb3 package for all of us to use.
89 /* --------------------------------------------------------------------- */
91 #include <stddef.h> /* for offsetof() */
94 #define COMPILING_BSDDB_C
96 #undef COMPILING_BSDDB_C
98 static char *rcs_id
= "$Id$";
100 /* --------------------------------------------------------------------- */
101 /* Various macro definitions */
103 #if (PY_VERSION_HEX < 0x02050000)
104 typedef int Py_ssize_t
;
107 #if (PY_VERSION_HEX < 0x02060000) /* really: before python trunk r63675 */
108 /* This code now uses PyBytes* API function names instead of PyString*.
109 * These #defines map to their equivalent on earlier python versions. */
110 #define PyBytes_FromStringAndSize PyString_FromStringAndSize
111 #define PyBytes_FromString PyString_FromString
112 #define PyBytes_AsStringAndSize PyString_AsStringAndSize
113 #define PyBytes_Check PyString_Check
114 #define PyBytes_GET_SIZE PyString_GET_SIZE
115 #define PyBytes_AS_STRING PyString_AS_STRING
120 /* These are for when calling Python --> C */
121 #define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
122 #define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
124 /* For 2.3, use the PyGILState_ calls */
125 #if (PY_VERSION_HEX >= 0x02030000)
126 #define MYDB_USE_GILSTATE
129 /* and these are for calling C --> Python */
130 #if defined(MYDB_USE_GILSTATE)
131 #define MYDB_BEGIN_BLOCK_THREADS \
132 PyGILState_STATE __savestate = PyGILState_Ensure();
133 #define MYDB_END_BLOCK_THREADS \
134 PyGILState_Release(__savestate);
135 #else /* MYDB_USE_GILSTATE */
136 /* Pre GILState API - do it the long old way */
137 static PyInterpreterState
* _db_interpreterState
= NULL
;
138 #define MYDB_BEGIN_BLOCK_THREADS { \
139 PyThreadState* prevState; \
140 PyThreadState* newState; \
141 PyEval_AcquireLock(); \
142 newState = PyThreadState_New(_db_interpreterState); \
143 prevState = PyThreadState_Swap(newState);
145 #define MYDB_END_BLOCK_THREADS \
146 newState = PyThreadState_Swap(prevState); \
147 PyThreadState_Clear(newState); \
148 PyEval_ReleaseLock(); \
149 PyThreadState_Delete(newState); \
151 #endif /* MYDB_USE_GILSTATE */
154 /* Compiled without threads - avoid all this cruft */
155 #define MYDB_BEGIN_ALLOW_THREADS
156 #define MYDB_END_ALLOW_THREADS
157 #define MYDB_BEGIN_BLOCK_THREADS
158 #define MYDB_END_BLOCK_THREADS
162 /* Should DB_INCOMPLETE be turned into a warning or an exception? */
163 #define INCOMPLETE_IS_WARNING 1
165 /* --------------------------------------------------------------------- */
168 static PyObject
* DBError
; /* Base class, all others derive from this */
169 static PyObject
* DBCursorClosedError
; /* raised when trying to use a closed cursor object */
170 static PyObject
* DBKeyEmptyError
; /* DB_KEYEMPTY: also derives from KeyError */
171 static PyObject
* DBKeyExistError
; /* DB_KEYEXIST */
172 static PyObject
* DBLockDeadlockError
; /* DB_LOCK_DEADLOCK */
173 static PyObject
* DBLockNotGrantedError
; /* DB_LOCK_NOTGRANTED */
174 static PyObject
* DBNotFoundError
; /* DB_NOTFOUND: also derives from KeyError */
175 static PyObject
* DBOldVersionError
; /* DB_OLD_VERSION */
176 static PyObject
* DBRunRecoveryError
; /* DB_RUNRECOVERY */
177 static PyObject
* DBVerifyBadError
; /* DB_VERIFY_BAD */
178 static PyObject
* DBNoServerError
; /* DB_NOSERVER */
179 static PyObject
* DBNoServerHomeError
; /* DB_NOSERVER_HOME */
180 static PyObject
* DBNoServerIDError
; /* DB_NOSERVER_ID */
182 static PyObject
* DBPageNotFoundError
; /* DB_PAGE_NOTFOUND */
183 static PyObject
* DBSecondaryBadError
; /* DB_SECONDARY_BAD */
186 #if !INCOMPLETE_IS_WARNING
187 static PyObject
* DBIncompleteError
; /* DB_INCOMPLETE */
190 static PyObject
* DBInvalidArgError
; /* EINVAL */
191 static PyObject
* DBAccessError
; /* EACCES */
192 static PyObject
* DBNoSpaceError
; /* ENOSPC */
193 static PyObject
* DBNoMemoryError
; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
194 static PyObject
* DBAgainError
; /* EAGAIN */
195 static PyObject
* DBBusyError
; /* EBUSY */
196 static PyObject
* DBFileExistsError
; /* EEXIST */
197 static PyObject
* DBNoSuchFileError
; /* ENOENT */
198 static PyObject
* DBPermissionsError
; /* EPERM */
201 static PyObject
* DBRepHandleDeadError
; /* DB_REP_HANDLE_DEAD */
205 #define DB_BUFFER_SMALL ENOMEM
209 /* --------------------------------------------------------------------- */
210 /* Structure definitions */
212 #if PYTHON_API_VERSION < 1010
213 #error "Python 2.1 or later required"
217 /* Defaults for moduleFlags in DBEnvObject and DBObject. */
218 #define DEFAULT_GET_RETURNS_NONE 1
219 #define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
222 staticforward PyTypeObject DB_Type
, DBCursor_Type
, DBEnv_Type
, DBTxn_Type
, DBLock_Type
;
224 staticforward PyTypeObject DBSequence_Type
;
228 /* for compatibility with Python 2.5 and earlier */
229 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
232 #define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
233 #define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
234 #define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
235 #define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
236 #define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
238 #define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
242 #define _DBC_close(dbc) dbc->c_close(dbc)
243 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
244 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
245 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
246 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
247 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
248 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
250 #define _DBC_close(dbc) dbc->close(dbc)
251 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
252 #define _DBC_del(dbc,a) dbc->del(dbc,a)
253 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
254 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
255 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
256 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
260 /* --------------------------------------------------------------------- */
261 /* Utility macros and functions */
263 #define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
265 object->sibling_next=backlink; \
266 object->sibling_prev_p=&(backlink); \
268 if (object->sibling_next) { \
269 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
273 #define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
275 if (object->sibling_next) { \
276 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
278 *(object->sibling_prev_p)=object->sibling_next; \
281 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
283 if (object->sibling_next) { \
284 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
286 if (object->sibling_prev_p) { \
287 *(object->sibling_prev_p)=object->sibling_next; \
291 #define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
293 object->sibling_next_txn=backlink; \
294 object->sibling_prev_p_txn=&(backlink); \
296 if (object->sibling_next_txn) { \
297 object->sibling_next_txn->sibling_prev_p_txn= \
298 &(object->sibling_next_txn); \
302 #define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
304 if (object->sibling_next_txn) { \
305 object->sibling_next_txn->sibling_prev_p_txn= \
306 object->sibling_prev_p_txn; \
308 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
312 #define RETURN_IF_ERR() \
313 if (makeDBError(err)) { \
317 #define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
319 #define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
320 if ((nonNull) == NULL) { \
321 PyObject *errTuple = NULL; \
322 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
323 PyErr_SetObject((pyErrObj), errTuple); \
324 Py_DECREF(errTuple); \
328 #define CHECK_DB_NOT_CLOSED(dbobj) \
329 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
331 #define CHECK_ENV_NOT_CLOSED(env) \
332 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
334 #define CHECK_CURSOR_NOT_CLOSED(curs) \
335 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
338 #define CHECK_SEQUENCE_NOT_CLOSED(curs) \
339 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
342 #define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
343 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
345 #define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
347 #define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
348 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
351 static int makeDBError(int err
);
354 /* Return the access method type of the DBObject */
355 static int _DB_get_type(DBObject
* self
)
360 err
= self
->db
->get_type(self
->db
, &type
);
361 if (makeDBError(err
)) {
366 return self
->db
->get_type(self
->db
);
371 /* Create a DBT structure (containing key and data values) from Python
372 strings. Returns 1 on success, 0 on an error. */
373 static int make_dbt(PyObject
* obj
, DBT
* dbt
)
376 if (obj
== Py_None
) {
377 /* no need to do anything, the structure has already been zeroed */
379 else if (!PyArg_Parse(obj
, "s#", &dbt
->data
, &dbt
->size
)) {
380 PyErr_SetString(PyExc_TypeError
,
381 "Data values must be of type string or None.");
388 /* Recno and Queue DBs can have integer keys. This function figures out
389 what's been given, verifies that it's allowed, and then makes the DBT.
391 Caller MUST call FREE_DBT(key) when done. */
393 make_key_dbt(DBObject
* self
, PyObject
* keyobj
, DBT
* key
, int* pflags
)
399 if (keyobj
== Py_None
) {
400 type
= _DB_get_type(self
);
403 if (type
== DB_RECNO
|| type
== DB_QUEUE
) {
406 "None keys not allowed for Recno and Queue DB's");
409 /* no need to do anything, the structure has already been zeroed */
412 else if (PyBytes_Check(keyobj
)) {
413 /* verify access method type */
414 type
= _DB_get_type(self
);
417 if (type
== DB_RECNO
|| type
== DB_QUEUE
) {
420 "String keys not allowed for Recno and Queue DB's");
425 * NOTE(gps): I don't like doing a data copy here, it seems
426 * wasteful. But without a clean way to tell FREE_DBT if it
427 * should free key->data or not we have to. Other places in
428 * the code check for DB_THREAD and forceably set DBT_MALLOC
429 * when we otherwise would leave flags 0 to indicate that.
431 key
->data
= malloc(PyBytes_GET_SIZE(keyobj
));
432 if (key
->data
== NULL
) {
433 PyErr_SetString(PyExc_MemoryError
, "Key memory allocation failed");
436 memcpy(key
->data
, PyBytes_AS_STRING(keyobj
),
437 PyBytes_GET_SIZE(keyobj
));
438 key
->flags
= DB_DBT_REALLOC
;
439 key
->size
= PyBytes_GET_SIZE(keyobj
);
442 else if (PyInt_Check(keyobj
)) {
443 /* verify access method type */
444 type
= _DB_get_type(self
);
447 if (type
== DB_BTREE
&& pflags
!= NULL
) {
448 /* if BTREE then an Integer key is allowed with the
449 * DB_SET_RECNO flag */
450 *pflags
|= DB_SET_RECNO
;
452 else if (type
!= DB_RECNO
&& type
!= DB_QUEUE
) {
455 "Integer keys only allowed for Recno and Queue DB's");
459 /* Make a key out of the requested recno, use allocated space so DB
460 * will be able to realloc room for the real key if needed. */
461 recno
= PyInt_AS_LONG(keyobj
);
462 key
->data
= malloc(sizeof(db_recno_t
));
463 if (key
->data
== NULL
) {
464 PyErr_SetString(PyExc_MemoryError
, "Key memory allocation failed");
467 key
->ulen
= key
->size
= sizeof(db_recno_t
);
468 memcpy(key
->data
, &recno
, sizeof(db_recno_t
));
469 key
->flags
= DB_DBT_REALLOC
;
472 PyErr_Format(PyExc_TypeError
,
473 "String or Integer object expected for key, %s found",
474 Py_TYPE(keyobj
)->tp_name
);
482 /* Add partial record access to an existing DBT data struct.
483 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
484 and the data storage/retrieval will be done using dlen and doff. */
485 static int add_partial_dbt(DBT
* d
, int dlen
, int doff
) {
486 /* if neither were set we do nothing (-1 is the default value) */
487 if ((dlen
== -1) && (doff
== -1)) {
491 if ((dlen
< 0) || (doff
< 0)) {
492 PyErr_SetString(PyExc_TypeError
, "dlen and doff must both be >= 0");
496 d
->flags
= d
->flags
| DB_DBT_PARTIAL
;
497 d
->dlen
= (unsigned int) dlen
;
498 d
->doff
= (unsigned int) doff
;
502 /* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
503 /* TODO: make this use the native libc strlcpy() when available (BSD) */
504 unsigned int our_strlcpy(char* dest
, const char* src
, unsigned int n
)
506 unsigned int srclen
, copylen
;
508 srclen
= strlen(src
);
511 copylen
= (srclen
> n
-1) ? n
-1 : srclen
;
512 /* populate dest[0] thru dest[copylen-1] */
513 memcpy(dest
, src
, copylen
);
514 /* guarantee null termination */
520 /* Callback used to save away more information about errors from the DB
522 static char _db_errmsg
[1024];
524 static void _db_errorCallback(const char* prefix
, char* msg
)
526 static void _db_errorCallback(const DB_ENV
*db_env
,
527 const char* prefix
, const char* msg
)
530 our_strlcpy(_db_errmsg
, msg
, sizeof(_db_errmsg
));
535 ** We need these functions because some results
536 ** are undefined if pointer is NULL. Some other
537 ** give None instead of "".
539 ** This functions are static and will be
542 static const char *DummyString
= "This string is a simple placeholder";
543 static PyObject
*Build_PyString(const char *p
,int s
)
549 return PyBytes_FromStringAndSize(p
,s
);
552 static PyObject
*BuildValue_S(const void *p
,int s
)
558 return Py_BuildValue("s#",p
,s
);
561 static PyObject
*BuildValue_SS(const void *p1
,int s1
,const void *p2
,int s2
)
571 return Py_BuildValue("s#s#",p1
,s1
,p2
,s2
);
574 static PyObject
*BuildValue_IS(int i
,const void *p
,int s
)
580 return Py_BuildValue("is#",i
,p
,s
);
583 static PyObject
*BuildValue_LS(long i
,const void *p
,int s
)
589 return Py_BuildValue("ls#",i
,p
,s
);
594 /* make a nice exception object to raise for errors. */
595 static int makeDBError(int err
)
597 char errTxt
[2048]; /* really big, just in case... */
598 PyObject
*errObj
= NULL
;
599 PyObject
*errTuple
= NULL
;
600 int exceptionRaised
= 0;
601 unsigned int bytes_left
;
604 case 0: /* successful, no error */ break;
608 #if INCOMPLETE_IS_WARNING
609 bytes_left
= our_strlcpy(errTxt
, db_strerror(err
), sizeof(errTxt
));
610 /* Ensure that bytes_left never goes negative */
611 if (_db_errmsg
[0] && bytes_left
< (sizeof(errTxt
) - 4)) {
612 bytes_left
= sizeof(errTxt
) - bytes_left
- 4 - 1;
613 assert(bytes_left
>= 0);
614 strcat(errTxt
, " -- ");
615 strncat(errTxt
, _db_errmsg
, bytes_left
);
618 exceptionRaised
= PyErr_Warn(PyExc_RuntimeWarning
, errTxt
);
620 #else /* do an exception instead */
621 errObj
= DBIncompleteError
;
624 #endif /* DBVER < 41 */
626 case DB_KEYEMPTY
: errObj
= DBKeyEmptyError
; break;
627 case DB_KEYEXIST
: errObj
= DBKeyExistError
; break;
628 case DB_LOCK_DEADLOCK
: errObj
= DBLockDeadlockError
; break;
629 case DB_LOCK_NOTGRANTED
: errObj
= DBLockNotGrantedError
; break;
630 case DB_NOTFOUND
: errObj
= DBNotFoundError
; break;
631 case DB_OLD_VERSION
: errObj
= DBOldVersionError
; break;
632 case DB_RUNRECOVERY
: errObj
= DBRunRecoveryError
; break;
633 case DB_VERIFY_BAD
: errObj
= DBVerifyBadError
; break;
634 case DB_NOSERVER
: errObj
= DBNoServerError
; break;
635 case DB_NOSERVER_HOME
: errObj
= DBNoServerHomeError
; break;
636 case DB_NOSERVER_ID
: errObj
= DBNoServerIDError
; break;
638 case DB_PAGE_NOTFOUND
: errObj
= DBPageNotFoundError
; break;
639 case DB_SECONDARY_BAD
: errObj
= DBSecondaryBadError
; break;
641 case DB_BUFFER_SMALL
: errObj
= DBNoMemoryError
; break;
644 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
645 case ENOMEM
: errObj
= PyExc_MemoryError
; break;
647 case EINVAL
: errObj
= DBInvalidArgError
; break;
648 case EACCES
: errObj
= DBAccessError
; break;
649 case ENOSPC
: errObj
= DBNoSpaceError
; break;
650 case EAGAIN
: errObj
= DBAgainError
; break;
651 case EBUSY
: errObj
= DBBusyError
; break;
652 case EEXIST
: errObj
= DBFileExistsError
; break;
653 case ENOENT
: errObj
= DBNoSuchFileError
; break;
654 case EPERM
: errObj
= DBPermissionsError
; break;
657 case DB_REP_HANDLE_DEAD
: errObj
= DBRepHandleDeadError
; break;
660 default: errObj
= DBError
; break;
663 if (errObj
!= NULL
) {
664 bytes_left
= our_strlcpy(errTxt
, db_strerror(err
), sizeof(errTxt
));
665 /* Ensure that bytes_left never goes negative */
666 if (_db_errmsg
[0] && bytes_left
< (sizeof(errTxt
) - 4)) {
667 bytes_left
= sizeof(errTxt
) - bytes_left
- 4 - 1;
668 assert(bytes_left
>= 0);
669 strcat(errTxt
, " -- ");
670 strncat(errTxt
, _db_errmsg
, bytes_left
);
674 errTuple
= Py_BuildValue("(is)", err
, errTxt
);
675 PyErr_SetObject(errObj
, errTuple
);
679 return ((errObj
!= NULL
) || exceptionRaised
);
684 /* set a type exception */
685 static void makeTypeError(char* expected
, PyObject
* found
)
687 PyErr_Format(PyExc_TypeError
, "Expected %s argument, %s found.",
688 expected
, Py_TYPE(found
)->tp_name
);
692 /* verify that an obj is either None or a DBTxn, and set the txn pointer */
693 static int checkTxnObj(PyObject
* txnobj
, DB_TXN
** txn
)
695 if (txnobj
== Py_None
|| txnobj
== NULL
) {
699 if (DBTxnObject_Check(txnobj
)) {
700 *txn
= ((DBTxnObject
*)txnobj
)->txn
;
704 makeTypeError("DBTxn", txnobj
);
709 /* Delete a key from a database
710 Returns 0 on success, -1 on an error. */
711 static int _DB_delete(DBObject
* self
, DB_TXN
*txn
, DBT
*key
, int flags
)
715 MYDB_BEGIN_ALLOW_THREADS
;
716 err
= self
->db
->del(self
->db
, txn
, key
, 0);
717 MYDB_END_ALLOW_THREADS
;
718 if (makeDBError(err
)) {
726 /* Store a key into a database
727 Returns 0 on success, -1 on an error. */
728 static int _DB_put(DBObject
* self
, DB_TXN
*txn
, DBT
*key
, DBT
*data
, int flags
)
732 MYDB_BEGIN_ALLOW_THREADS
;
733 err
= self
->db
->put(self
->db
, txn
, key
, data
, flags
);
734 MYDB_END_ALLOW_THREADS
;
735 if (makeDBError(err
)) {
742 /* Get a key/data pair from a cursor */
743 static PyObject
* _DBCursor_get(DBCursorObject
* self
, int extra_flags
,
744 PyObject
*args
, PyObject
*kwargs
, char *format
)
747 PyObject
* retval
= NULL
;
752 static char* kwnames
[] = { "flags", "dlen", "doff", NULL
};
754 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, format
, kwnames
,
755 &flags
, &dlen
, &doff
))
758 CHECK_CURSOR_NOT_CLOSED(self
);
760 flags
|= extra_flags
;
763 if (!add_partial_dbt(&data
, dlen
, doff
))
766 MYDB_BEGIN_ALLOW_THREADS
;
767 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
);
768 MYDB_END_ALLOW_THREADS
;
770 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
771 && self
->mydb
->moduleFlags
.getReturnsNone
) {
775 else if (makeDBError(err
)) {
778 else { /* otherwise, success! */
780 /* if Recno or Queue, return the key as an Int */
781 switch (_DB_get_type(self
->mydb
)) {
788 retval
= BuildValue_IS(*((db_recno_t
*)key
.data
), data
.data
, data
.size
);
793 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
801 /* add an integer to a dictionary using the given name as a key */
802 static void _addIntToDict(PyObject
* dict
, char *name
, int value
)
804 PyObject
* v
= PyInt_FromLong((long) value
);
805 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
811 /* The same, when the value is a time_t */
812 static void _addTimeTToDict(PyObject
* dict
, char *name
, time_t value
)
815 /* if the value fits in regular int, use that. */
817 if (sizeof(time_t) > sizeof(long))
818 v
= PyLong_FromLongLong((PY_LONG_LONG
) value
);
821 v
= PyInt_FromLong((long) value
);
822 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
829 /* add an db_seq_t to a dictionary using the given name as a key */
830 static void _addDb_seq_tToDict(PyObject
* dict
, char *name
, db_seq_t value
)
832 PyObject
* v
= PyLong_FromLongLong(value
);
833 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
841 static void _addDB_lsnToDict(PyObject
* dict
, char *name
, DB_LSN value
)
843 PyObject
*v
= Py_BuildValue("(ll)",value
.file
,value
.offset
);
844 if (!v
|| PyDict_SetItemString(dict
, name
, v
))
851 /* --------------------------------------------------------------------- */
852 /* Allocators and deallocators */
855 newDBObject(DBEnvObject
* arg
, int flags
)
858 DB_ENV
* db_env
= NULL
;
861 self
= PyObject_New(DBObject
, &DB_Type
);
868 self
->myenvobj
= NULL
;
869 self
->children_cursors
= NULL
;
871 self
->children_sequences
= NULL
;
874 self
->associateCallback
= NULL
;
875 self
->btCompareCallback
= NULL
;
876 self
->primaryDBType
= 0;
878 self
->in_weakreflist
= NULL
;
880 /* keep a reference to our python DBEnv object */
883 self
->myenvobj
= arg
;
884 db_env
= arg
->db_env
;
885 INSERT_IN_DOUBLE_LINKED_LIST(self
->myenvobj
->children_dbs
,self
);
887 self
->sibling_prev_p
=NULL
;
888 self
->sibling_next
=NULL
;
891 self
->sibling_prev_p_txn
=NULL
;
892 self
->sibling_next_txn
=NULL
;
895 self
->moduleFlags
= self
->myenvobj
->moduleFlags
;
897 self
->moduleFlags
.getReturnsNone
= DEFAULT_GET_RETURNS_NONE
;
898 self
->moduleFlags
.cursorSetReturnsNone
= DEFAULT_CURSOR_SET_RETURNS_NONE
;
900 MYDB_BEGIN_ALLOW_THREADS
;
901 err
= db_create(&self
->db
, db_env
, flags
);
902 if (self
->db
!= NULL
) {
903 self
->db
->set_errcall(self
->db
, _db_errorCallback
);
905 self
->db
->app_private
= (void*)self
;
908 MYDB_END_ALLOW_THREADS
;
909 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
910 * list so that a DBEnv can refuse to close without aborting any open
911 * DBTxns and closing any open DBs first. */
912 if (makeDBError(err
)) {
913 if (self
->myenvobj
) {
914 Py_DECREF(self
->myenvobj
);
915 self
->myenvobj
= NULL
;
924 /* Forward declaration */
925 static PyObject
*DB_close_internal(DBObject
* self
, int flags
);
928 DB_dealloc(DBObject
* self
)
932 if (self
->db
!= NULL
) {
933 dummy
=DB_close_internal(self
,0);
936 if (self
->in_weakreflist
!= NULL
) {
937 PyObject_ClearWeakRefs((PyObject
*) self
);
939 if (self
->myenvobj
) {
940 Py_DECREF(self
->myenvobj
);
941 self
->myenvobj
= NULL
;
944 if (self
->associateCallback
!= NULL
) {
945 Py_DECREF(self
->associateCallback
);
946 self
->associateCallback
= NULL
;
948 if (self
->btCompareCallback
!= NULL
) {
949 Py_DECREF(self
->btCompareCallback
);
950 self
->btCompareCallback
= NULL
;
956 static DBCursorObject
*
957 newDBCursorObject(DBC
* dbc
, DBTxnObject
*txn
, DBObject
* db
)
959 DBCursorObject
* self
= PyObject_New(DBCursorObject
, &DBCursor_Type
);
966 INSERT_IN_DOUBLE_LINKED_LIST(self
->mydb
->children_cursors
,self
);
967 if (txn
&& ((PyObject
*)txn
!=Py_None
)) {
968 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn
->children_cursors
,self
);
974 self
->in_weakreflist
= NULL
;
975 Py_INCREF(self
->mydb
);
980 /* Forward declaration */
981 static PyObject
*DBC_close_internal(DBCursorObject
* self
);
984 DBCursor_dealloc(DBCursorObject
* self
)
988 if (self
->dbc
!= NULL
) {
989 dummy
=DBC_close_internal(self
);
992 if (self
->in_weakreflist
!= NULL
) {
993 PyObject_ClearWeakRefs((PyObject
*) self
);
995 Py_DECREF(self
->mydb
);
1001 newDBEnvObject(int flags
)
1004 DBEnvObject
* self
= PyObject_New(DBEnvObject
, &DBEnv_Type
);
1009 self
->flags
= flags
;
1010 self
->moduleFlags
.getReturnsNone
= DEFAULT_GET_RETURNS_NONE
;
1011 self
->moduleFlags
.cursorSetReturnsNone
= DEFAULT_CURSOR_SET_RETURNS_NONE
;
1012 self
->children_dbs
= NULL
;
1013 self
->children_txns
= NULL
;
1014 self
->in_weakreflist
= NULL
;
1017 self
->event_notifyCallback
= NULL
;
1020 MYDB_BEGIN_ALLOW_THREADS
;
1021 err
= db_env_create(&self
->db_env
, flags
);
1022 MYDB_END_ALLOW_THREADS
;
1023 if (makeDBError(err
)) {
1028 self
->db_env
->set_errcall(self
->db_env
, _db_errorCallback
);
1029 self
->db_env
->app_private
=self
;
1034 /* Forward declaration */
1035 static PyObject
*DBEnv_close_internal(DBEnvObject
* self
, int flags
);
1038 DBEnv_dealloc(DBEnvObject
* self
)
1042 if (self
->db_env
&& !self
->closed
) {
1043 dummy
=DBEnv_close_internal(self
,0);
1048 Py_XDECREF(self
->event_notifyCallback
);
1049 self
->event_notifyCallback
= NULL
;
1052 if (self
->in_weakreflist
!= NULL
) {
1053 PyObject_ClearWeakRefs((PyObject
*) self
);
1061 newDBTxnObject(DBEnvObject
* myenv
, DBTxnObject
*parent
, DB_TXN
*txn
, int flags
)
1064 DB_TXN
*parent_txn
= NULL
;
1066 DBTxnObject
* self
= PyObject_New(DBTxnObject
, &DBTxn_Type
);
1070 self
->in_weakreflist
= NULL
;
1071 self
->children_txns
= NULL
;
1072 self
->children_dbs
= NULL
;
1073 self
->children_cursors
= NULL
;
1074 self
->children_sequences
= NULL
;
1075 self
->flag_prepare
= 0;
1076 self
->parent_txn
= NULL
;
1079 if (parent
&& ((PyObject
*)parent
!=Py_None
)) {
1080 parent_txn
= parent
->txn
;
1086 MYDB_BEGIN_ALLOW_THREADS
;
1088 err
= myenv
->db_env
->txn_begin(myenv
->db_env
, parent_txn
, &(self
->txn
), flags
);
1090 err
= txn_begin(myenv
->db_env
, parent
->txn
, &(self_txn
), flags
);
1092 MYDB_END_ALLOW_THREADS
;
1094 if (makeDBError(err
)) {
1100 /* Can't use 'parent' because could be 'parent==Py_None' */
1102 self
->parent_txn
= parent
;
1105 INSERT_IN_DOUBLE_LINKED_LIST(parent
->children_txns
, self
);
1107 self
->parent_txn
= NULL
;
1110 INSERT_IN_DOUBLE_LINKED_LIST(myenv
->children_txns
, self
);
1116 /* Forward declaration */
1118 DBTxn_abort_discard_internal(DBTxnObject
* self
, int discard
);
1121 DBTxn_dealloc(DBTxnObject
* self
)
1126 int flag_prepare
= self
->flag_prepare
;
1127 dummy
=DBTxn_abort_discard_internal(self
,0);
1129 if (!flag_prepare
) {
1130 PyErr_Warn(PyExc_RuntimeWarning
,
1131 "DBTxn aborted in destructor. No prior commit() or abort().");
1135 if (self
->in_weakreflist
!= NULL
) {
1136 PyObject_ClearWeakRefs((PyObject
*) self
);
1140 Py_DECREF(self
->env
);
1142 Py_DECREF(self
->parent_txn
);
1148 static DBLockObject
*
1149 newDBLockObject(DBEnvObject
* myenv
, u_int32_t locker
, DBT
* obj
,
1150 db_lockmode_t lock_mode
, int flags
)
1153 DBLockObject
* self
= PyObject_New(DBLockObject
, &DBLock_Type
);
1156 self
->in_weakreflist
= NULL
;
1158 MYDB_BEGIN_ALLOW_THREADS
;
1160 err
= myenv
->db_env
->lock_get(myenv
->db_env
, locker
, flags
, obj
, lock_mode
,
1163 err
= lock_get(myenv
->db_env
, locker
, flags
, obj
, lock_mode
, &self
->lock
);
1165 MYDB_END_ALLOW_THREADS
;
1166 if (makeDBError(err
)) {
1176 DBLock_dealloc(DBLockObject
* self
)
1178 if (self
->in_weakreflist
!= NULL
) {
1179 PyObject_ClearWeakRefs((PyObject
*) self
);
1181 /* TODO: is this lock held? should we release it? */
1188 static DBSequenceObject
*
1189 newDBSequenceObject(DBObject
* mydb
, int flags
)
1192 DBSequenceObject
* self
= PyObject_New(DBSequenceObject
, &DBSequence_Type
);
1198 INSERT_IN_DOUBLE_LINKED_LIST(self
->mydb
->children_sequences
,self
);
1201 self
->in_weakreflist
= NULL
;
1203 MYDB_BEGIN_ALLOW_THREADS
;
1204 err
= db_sequence_create(&self
->sequence
, self
->mydb
->db
, flags
);
1205 MYDB_END_ALLOW_THREADS
;
1206 if (makeDBError(err
)) {
1214 /* Forward declaration */
1216 *DBSequence_close_internal(DBSequenceObject
* self
, int flags
, int do_not_close
);
1219 DBSequence_dealloc(DBSequenceObject
* self
)
1223 if (self
->sequence
!= NULL
) {
1224 dummy
=DBSequence_close_internal(self
,0,0);
1228 if (self
->in_weakreflist
!= NULL
) {
1229 PyObject_ClearWeakRefs((PyObject
*) self
);
1232 Py_DECREF(self
->mydb
);
1237 /* --------------------------------------------------------------------- */
1241 DB_append(DBObject
* self
, PyObject
* args
)
1243 PyObject
* txnobj
= NULL
;
1249 if (!PyArg_UnpackTuple(args
, "append", 1, 2, &dataobj
, &txnobj
))
1252 CHECK_DB_NOT_CLOSED(self
);
1254 /* make a dummy key out of a recno */
1258 key
.size
= sizeof(recno
);
1259 key
.ulen
= key
.size
;
1260 key
.flags
= DB_DBT_USERMEM
;
1262 if (!make_dbt(dataobj
, &data
)) return NULL
;
1263 if (!checkTxnObj(txnobj
, &txn
)) return NULL
;
1265 if (-1 == _DB_put(self
, txn
, &key
, &data
, DB_APPEND
))
1268 return PyInt_FromLong(recno
);
1275 _db_associateCallback(DB
* db
, const DBT
* priKey
, const DBT
* priData
,
1278 int retval
= DB_DONOTINDEX
;
1279 DBObject
* secondaryDB
= (DBObject
*)db
->app_private
;
1280 PyObject
* callback
= secondaryDB
->associateCallback
;
1281 int type
= secondaryDB
->primaryDBType
;
1283 PyObject
* result
= NULL
;
1286 if (callback
!= NULL
) {
1287 MYDB_BEGIN_BLOCK_THREADS
;
1289 if (type
== DB_RECNO
|| type
== DB_QUEUE
)
1290 args
= BuildValue_LS(*((db_recno_t
*)priKey
->data
), priData
->data
, priData
->size
);
1292 args
= BuildValue_SS(priKey
->data
, priKey
->size
, priData
->data
, priData
->size
);
1294 result
= PyEval_CallObject(callback
, args
);
1296 if (args
== NULL
|| result
== NULL
) {
1299 else if (result
== Py_None
) {
1300 retval
= DB_DONOTINDEX
;
1302 else if (PyInt_Check(result
)) {
1303 retval
= PyInt_AsLong(result
);
1305 else if (PyBytes_Check(result
)) {
1310 PyBytes_AsStringAndSize(result
, &data
, &size
);
1311 secKey
->flags
= DB_DBT_APPMALLOC
; /* DB will free */
1312 secKey
->data
= malloc(size
); /* TODO, check this */
1314 memcpy(secKey
->data
, data
, size
);
1315 secKey
->size
= size
;
1319 PyErr_SetString(PyExc_MemoryError
,
1320 "malloc failed in _db_associateCallback");
1327 "DB associate callback should return DB_DONOTINDEX or string.");
1334 MYDB_END_BLOCK_THREADS
;
1341 DB_associate(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1344 DBObject
* secondaryDB
;
1347 PyObject
*txnobj
= NULL
;
1349 static char* kwnames
[] = {"secondaryDB", "callback", "flags", "txn",
1352 static char* kwnames
[] = {"secondaryDB", "callback", "flags", NULL
};
1356 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|iO:associate", kwnames
,
1357 &secondaryDB
, &callback
, &flags
,
1360 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|i:associate", kwnames
,
1361 &secondaryDB
, &callback
, &flags
)) {
1367 if (!checkTxnObj(txnobj
, &txn
)) return NULL
;
1370 CHECK_DB_NOT_CLOSED(self
);
1371 if (!DBObject_Check(secondaryDB
)) {
1372 makeTypeError("DB", (PyObject
*)secondaryDB
);
1375 CHECK_DB_NOT_CLOSED(secondaryDB
);
1376 if (callback
== Py_None
) {
1379 else if (!PyCallable_Check(callback
)) {
1380 makeTypeError("Callable", callback
);
1384 /* Save a reference to the callback in the secondary DB. */
1385 Py_XDECREF(secondaryDB
->associateCallback
);
1386 Py_XINCREF(callback
);
1387 secondaryDB
->associateCallback
= callback
;
1388 secondaryDB
->primaryDBType
= _DB_get_type(self
);
1390 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1391 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1392 * The global interepreter lock is not initialized until the first
1393 * thread is created using thread.start_new_thread() or fork() is
1394 * called. that would cause the ALLOW_THREADS here to segfault due
1395 * to a null pointer reference if no threads or child processes
1396 * have been created. This works around that and is a no-op if
1397 * threads have already been initialized.
1398 * (see pybsddb-users mailing list post on 2002-08-07)
1401 PyEval_InitThreads();
1403 MYDB_BEGIN_ALLOW_THREADS
;
1405 err
= self
->db
->associate(self
->db
,
1408 _db_associateCallback
,
1411 err
= self
->db
->associate(self
->db
,
1413 _db_associateCallback
,
1416 MYDB_END_ALLOW_THREADS
;
1419 Py_XDECREF(secondaryDB
->associateCallback
);
1420 secondaryDB
->associateCallback
= NULL
;
1421 secondaryDB
->primaryDBType
= 0;
1433 DB_close_internal(DBObject
* self
, int flags
)
1438 if (self
->db
!= NULL
) {
1439 /* Can be NULL if db is not in an environment */
1440 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self
);
1442 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self
);
1446 while(self
->children_cursors
) {
1447 dummy
=DBC_close_internal(self
->children_cursors
);
1452 while(self
->children_sequences
) {
1453 dummy
=DBSequence_close_internal(self
->children_sequences
,0,0);
1458 MYDB_BEGIN_ALLOW_THREADS
;
1459 err
= self
->db
->close(self
->db
, flags
);
1460 MYDB_END_ALLOW_THREADS
;
1468 DB_close(DBObject
* self
, PyObject
* args
)
1471 if (!PyArg_ParseTuple(args
,"|i:close", &flags
))
1473 return DB_close_internal(self
,flags
);
1478 _DB_consume(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
, int consume_flag
)
1480 int err
, flags
=0, type
;
1481 PyObject
* txnobj
= NULL
;
1482 PyObject
* retval
= NULL
;
1485 static char* kwnames
[] = { "txn", "flags", NULL
};
1487 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:consume", kwnames
,
1491 CHECK_DB_NOT_CLOSED(self
);
1492 type
= _DB_get_type(self
);
1495 if (type
!= DB_QUEUE
) {
1496 PyErr_SetString(PyExc_TypeError
,
1497 "Consume methods only allowed for Queue DB's");
1500 if (!checkTxnObj(txnobj
, &txn
))
1505 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1506 /* Tell Berkeley DB to malloc the return value (thread safe) */
1507 data
.flags
= DB_DBT_MALLOC
;
1508 key
.flags
= DB_DBT_MALLOC
;
1511 MYDB_BEGIN_ALLOW_THREADS
;
1512 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
|consume_flag
);
1513 MYDB_END_ALLOW_THREADS
;
1515 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1516 && self
->moduleFlags
.getReturnsNone
) {
1522 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
1532 DB_consume(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
, int consume_flag
)
1534 return _DB_consume(self
, args
, kwargs
, DB_CONSUME
);
1538 DB_consume_wait(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
,
1541 return _DB_consume(self
, args
, kwargs
, DB_CONSUME_WAIT
);
1546 DB_cursor(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1550 PyObject
* txnobj
= NULL
;
1552 static char* kwnames
[] = { "txn", "flags", NULL
};
1554 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:cursor", kwnames
,
1557 CHECK_DB_NOT_CLOSED(self
);
1558 if (!checkTxnObj(txnobj
, &txn
))
1561 MYDB_BEGIN_ALLOW_THREADS
;
1562 err
= self
->db
->cursor(self
->db
, txn
, &dbc
, flags
);
1563 MYDB_END_ALLOW_THREADS
;
1565 return (PyObject
*) newDBCursorObject(dbc
, (DBTxnObject
*)txnobj
, self
);
1570 DB_delete(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1572 PyObject
* txnobj
= NULL
;
1577 static char* kwnames
[] = { "key", "txn", "flags", NULL
};
1579 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oi:delete", kwnames
,
1580 &keyobj
, &txnobj
, &flags
))
1582 CHECK_DB_NOT_CLOSED(self
);
1583 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
1585 if (!checkTxnObj(txnobj
, &txn
)) {
1590 if (-1 == _DB_delete(self
, txn
, &key
, 0)) {
1601 DB_fd(DBObject
* self
, PyObject
* args
)
1605 if (!PyArg_ParseTuple(args
,":fd"))
1607 CHECK_DB_NOT_CLOSED(self
);
1609 MYDB_BEGIN_ALLOW_THREADS
;
1610 err
= self
->db
->fd(self
->db
, &the_fd
);
1611 MYDB_END_ALLOW_THREADS
;
1613 return PyInt_FromLong(the_fd
);
1618 DB_get(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1621 PyObject
* txnobj
= NULL
;
1623 PyObject
* dfltobj
= NULL
;
1624 PyObject
* retval
= NULL
;
1629 static char* kwnames
[] = {"key", "default", "txn", "flags", "dlen",
1632 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|OOiii:get", kwnames
,
1633 &keyobj
, &dfltobj
, &txnobj
, &flags
, &dlen
,
1637 CHECK_DB_NOT_CLOSED(self
);
1638 if (!make_key_dbt(self
, keyobj
, &key
, &flags
))
1640 if (!checkTxnObj(txnobj
, &txn
)) {
1646 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1647 /* Tell Berkeley DB to malloc the return value (thread safe) */
1648 data
.flags
= DB_DBT_MALLOC
;
1650 if (!add_partial_dbt(&data
, dlen
, doff
)) {
1655 MYDB_BEGIN_ALLOW_THREADS
;
1656 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
);
1657 MYDB_END_ALLOW_THREADS
;
1659 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) && (dfltobj
!= NULL
)) {
1664 else if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1665 && self
->moduleFlags
.getReturnsNone
) {
1671 if (flags
& DB_SET_RECNO
) /* return both key and data */
1672 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
1673 else /* return just the data */
1674 retval
= Build_PyString(data
.data
, data
.size
);
1685 DB_pget(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1688 PyObject
* txnobj
= NULL
;
1690 PyObject
* dfltobj
= NULL
;
1691 PyObject
* retval
= NULL
;
1694 DBT key
, pkey
, data
;
1696 static char* kwnames
[] = {"key", "default", "txn", "flags", "dlen",
1699 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|OOiii:pget", kwnames
,
1700 &keyobj
, &dfltobj
, &txnobj
, &flags
, &dlen
,
1704 CHECK_DB_NOT_CLOSED(self
);
1705 if (!make_key_dbt(self
, keyobj
, &key
, &flags
))
1707 if (!checkTxnObj(txnobj
, &txn
)) {
1713 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1714 /* Tell Berkeley DB to malloc the return value (thread safe) */
1715 data
.flags
= DB_DBT_MALLOC
;
1717 if (!add_partial_dbt(&data
, dlen
, doff
)) {
1723 pkey
.flags
= DB_DBT_MALLOC
;
1725 MYDB_BEGIN_ALLOW_THREADS
;
1726 err
= self
->db
->pget(self
->db
, txn
, &key
, &pkey
, &data
, flags
);
1727 MYDB_END_ALLOW_THREADS
;
1729 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) && (dfltobj
!= NULL
)) {
1734 else if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1735 && self
->moduleFlags
.getReturnsNone
) {
1743 dataObj
= Build_PyString(data
.data
, data
.size
);
1745 if (self
->primaryDBType
== DB_RECNO
||
1746 self
->primaryDBType
== DB_QUEUE
)
1747 pkeyObj
= PyInt_FromLong(*(int *)pkey
.data
);
1749 pkeyObj
= Build_PyString(pkey
.data
, pkey
.size
);
1751 if (flags
& DB_SET_RECNO
) /* return key , pkey and data */
1754 int type
= _DB_get_type(self
);
1755 if (type
== DB_RECNO
|| type
== DB_QUEUE
)
1756 keyObj
= PyInt_FromLong(*(int *)key
.data
);
1758 keyObj
= Build_PyString(key
.data
, key
.size
);
1759 #if (PY_VERSION_HEX >= 0x02040000)
1760 retval
= PyTuple_Pack(3, keyObj
, pkeyObj
, dataObj
);
1762 retval
= Py_BuildValue("OOO", keyObj
, pkeyObj
, dataObj
);
1766 else /* return just the pkey and data */
1768 #if (PY_VERSION_HEX >= 0x02040000)
1769 retval
= PyTuple_Pack(2, pkeyObj
, dataObj
);
1771 retval
= Py_BuildValue("OO", pkeyObj
, dataObj
);
1787 /* Return size of entry */
1789 DB_get_size(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1792 PyObject
* txnobj
= NULL
;
1794 PyObject
* retval
= NULL
;
1797 static char* kwnames
[] = { "key", "txn", NULL
};
1799 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|O:get_size", kwnames
,
1802 CHECK_DB_NOT_CLOSED(self
);
1803 if (!make_key_dbt(self
, keyobj
, &key
, &flags
))
1805 if (!checkTxnObj(txnobj
, &txn
)) {
1811 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1812 thus getting the record size. */
1813 data
.flags
= DB_DBT_USERMEM
;
1815 MYDB_BEGIN_ALLOW_THREADS
;
1816 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
);
1817 MYDB_END_ALLOW_THREADS
;
1818 if (err
== DB_BUFFER_SMALL
) {
1819 retval
= PyInt_FromLong((long)data
.size
);
1831 DB_get_both(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1834 PyObject
* txnobj
= NULL
;
1837 PyObject
* retval
= NULL
;
1841 static char* kwnames
[] = { "key", "data", "txn", "flags", NULL
};
1844 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|Oi:get_both", kwnames
,
1845 &keyobj
, &dataobj
, &txnobj
, &flags
))
1848 CHECK_DB_NOT_CLOSED(self
);
1849 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
1851 if ( !make_dbt(dataobj
, &data
) ||
1852 !checkTxnObj(txnobj
, &txn
) )
1858 flags
|= DB_GET_BOTH
;
1859 orig_data
= data
.data
;
1861 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
1862 /* Tell Berkeley DB to malloc the return value (thread safe) */
1863 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
1864 data
.flags
= DB_DBT_MALLOC
;
1867 MYDB_BEGIN_ALLOW_THREADS
;
1868 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, flags
);
1869 MYDB_END_ALLOW_THREADS
;
1871 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
1872 && self
->moduleFlags
.getReturnsNone
) {
1878 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
1879 retval
= Build_PyString(data
.data
, data
.size
);
1881 /* Even though the flags require DB_DBT_MALLOC, data is not always
1882 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1883 if (data
.data
!= orig_data
)
1894 DB_get_byteswapped(DBObject
* self
, PyObject
* args
)
1901 if (!PyArg_ParseTuple(args
,":get_byteswapped"))
1903 CHECK_DB_NOT_CLOSED(self
);
1906 MYDB_BEGIN_ALLOW_THREADS
;
1907 err
= self
->db
->get_byteswapped(self
->db
, &retval
);
1908 MYDB_END_ALLOW_THREADS
;
1911 MYDB_BEGIN_ALLOW_THREADS
;
1912 retval
= self
->db
->get_byteswapped(self
->db
);
1913 MYDB_END_ALLOW_THREADS
;
1915 return PyInt_FromLong(retval
);
1920 DB_get_type(DBObject
* self
, PyObject
* args
)
1924 if (!PyArg_ParseTuple(args
,":get_type"))
1926 CHECK_DB_NOT_CLOSED(self
);
1928 type
= _DB_get_type(self
);
1931 return PyInt_FromLong(type
);
1936 DB_join(DBObject
* self
, PyObject
* args
)
1940 PyObject
* cursorsObj
;
1944 if (!PyArg_ParseTuple(args
,"O|i:join", &cursorsObj
, &flags
))
1947 CHECK_DB_NOT_CLOSED(self
);
1949 if (!PySequence_Check(cursorsObj
)) {
1950 PyErr_SetString(PyExc_TypeError
,
1951 "Sequence of DBCursor objects expected");
1955 length
= PyObject_Length(cursorsObj
);
1956 cursors
= malloc((length
+1) * sizeof(DBC
*));
1962 cursors
[length
] = NULL
;
1963 for (x
=0; x
<length
; x
++) {
1964 PyObject
* item
= PySequence_GetItem(cursorsObj
, x
);
1969 if (!DBCursorObject_Check(item
)) {
1970 PyErr_SetString(PyExc_TypeError
,
1971 "Sequence of DBCursor objects expected");
1975 cursors
[x
] = ((DBCursorObject
*)item
)->dbc
;
1979 MYDB_BEGIN_ALLOW_THREADS
;
1980 err
= self
->db
->join(self
->db
, cursors
, &dbc
, flags
);
1981 MYDB_END_ALLOW_THREADS
;
1985 /* FIXME: this is a buggy interface. The returned cursor
1986 contains internal references to the passed in cursors
1987 but does not hold python references to them or prevent
1988 them from being closed prematurely. This can cause
1989 python to crash when things are done in the wrong order. */
1990 return (PyObject
*) newDBCursorObject(dbc
, NULL
, self
);
1995 DB_key_range(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
1998 PyObject
* txnobj
= NULL
;
2003 static char* kwnames
[] = { "key", "txn", "flags", NULL
};
2005 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oi:key_range", kwnames
,
2006 &keyobj
, &txnobj
, &flags
))
2008 CHECK_DB_NOT_CLOSED(self
);
2009 if (!make_dbt(keyobj
, &key
))
2010 /* BTree only, don't need to allow for an int key */
2012 if (!checkTxnObj(txnobj
, &txn
))
2015 MYDB_BEGIN_ALLOW_THREADS
;
2016 err
= self
->db
->key_range(self
->db
, txn
, &key
, &range
, flags
);
2017 MYDB_END_ALLOW_THREADS
;
2020 return Py_BuildValue("ddd", range
.less
, range
.equal
, range
.greater
);
2025 DB_open(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2027 int err
, type
= DB_UNKNOWN
, flags
=0, mode
=0660;
2028 char* filename
= NULL
;
2029 char* dbname
= NULL
;
2031 PyObject
*txnobj
= NULL
;
2034 static char* kwnames
[] = {
2035 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL
};
2036 /* without dbname */
2037 static char* kwnames_basic
[] = {
2038 "filename", "dbtype", "flags", "mode", "txn", NULL
};
2041 static char* kwnames
[] = {
2042 "filename", "dbname", "dbtype", "flags", "mode", NULL
};
2043 /* without dbname */
2044 static char* kwnames_basic
[] = {
2045 "filename", "dbtype", "flags", "mode", NULL
};
2049 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "z|ziiiO:open", kwnames
,
2050 &filename
, &dbname
, &type
, &flags
, &mode
,
2053 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "z|ziii:open", kwnames
,
2054 &filename
, &dbname
, &type
, &flags
,
2059 type
= DB_UNKNOWN
; flags
= 0; mode
= 0660;
2060 filename
= NULL
; dbname
= NULL
;
2062 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,"z|iiiO:open",
2064 &filename
, &type
, &flags
, &mode
,
2068 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,"z|iii:open",
2070 &filename
, &type
, &flags
, &mode
))
2076 if (!checkTxnObj(txnobj
, &txn
)) return NULL
;
2079 if (NULL
== self
->db
) {
2080 PyObject
*t
= Py_BuildValue("(is)", 0,
2081 "Cannot call open() twice for DB object");
2082 PyErr_SetObject(DBError
, t
);
2088 if (txn
) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2089 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject
*)txnobj
)->children_dbs
,self
);
2090 self
->txn
=(DBTxnObject
*)txnobj
;
2098 MYDB_BEGIN_ALLOW_THREADS
;
2100 err
= self
->db
->open(self
->db
, txn
, filename
, dbname
, type
, flags
, mode
);
2102 err
= self
->db
->open(self
->db
, filename
, dbname
, type
, flags
, mode
);
2104 MYDB_END_ALLOW_THREADS
;
2105 if (makeDBError(err
)) {
2108 dummy
=DB_close_internal(self
,0);
2114 self
->db
->get_flags(self
->db
, &self
->setflags
);
2117 self
->flags
= flags
;
2124 DB_put(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2127 PyObject
* txnobj
= NULL
;
2130 PyObject
* keyobj
, *dataobj
, *retval
;
2133 static char* kwnames
[] = { "key", "data", "txn", "flags", "dlen",
2136 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|Oiii:put", kwnames
,
2137 &keyobj
, &dataobj
, &txnobj
, &flags
, &dlen
, &doff
))
2140 CHECK_DB_NOT_CLOSED(self
);
2141 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
2143 if ( !make_dbt(dataobj
, &data
) ||
2144 !add_partial_dbt(&data
, dlen
, doff
) ||
2145 !checkTxnObj(txnobj
, &txn
) )
2151 if (-1 == _DB_put(self
, txn
, &key
, &data
, flags
)) {
2156 if (flags
& DB_APPEND
)
2157 retval
= PyInt_FromLong(*((db_recno_t
*)key
.data
));
2169 DB_remove(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2172 char* database
= NULL
;
2174 static char* kwnames
[] = { "filename", "dbname", "flags", NULL
};
2176 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zi:remove", kwnames
,
2177 &filename
, &database
, &flags
))
2179 CHECK_DB_NOT_CLOSED(self
);
2181 err
= self
->db
->remove(self
->db
, filename
, database
, flags
);
2190 DB_rename(DBObject
* self
, PyObject
* args
)
2197 if (!PyArg_ParseTuple(args
, "sss|i:rename", &filename
, &database
, &newname
,
2200 CHECK_DB_NOT_CLOSED(self
);
2202 MYDB_BEGIN_ALLOW_THREADS
;
2203 err
= self
->db
->rename(self
->db
, filename
, database
, newname
, flags
);
2204 MYDB_END_ALLOW_THREADS
;
2211 DB_set_bt_minkey(DBObject
* self
, PyObject
* args
)
2215 if (!PyArg_ParseTuple(args
,"i:set_bt_minkey", &minkey
))
2217 CHECK_DB_NOT_CLOSED(self
);
2219 MYDB_BEGIN_ALLOW_THREADS
;
2220 err
= self
->db
->set_bt_minkey(self
->db
, minkey
);
2221 MYDB_END_ALLOW_THREADS
;
2228 _default_cmp(const DBT
*leftKey
,
2229 const DBT
*rightKey
)
2232 int lsize
= leftKey
->size
, rsize
= rightKey
->size
;
2234 res
= memcmp(leftKey
->data
, rightKey
->data
,
2235 lsize
< rsize
? lsize
: rsize
);
2238 if (lsize
< rsize
) {
2241 else if (lsize
> rsize
) {
2249 _db_compareCallback(DB
* db
,
2251 const DBT
*rightKey
)
2255 PyObject
*result
= NULL
;
2256 DBObject
*self
= (DBObject
*)db
->app_private
;
2258 if (self
== NULL
|| self
->btCompareCallback
== NULL
) {
2259 MYDB_BEGIN_BLOCK_THREADS
;
2260 PyErr_SetString(PyExc_TypeError
,
2262 ? "DB_bt_compare db is NULL."
2263 : "DB_bt_compare callback is NULL."));
2264 /* we're in a callback within the DB code, we can't raise */
2266 res
= _default_cmp(leftKey
, rightKey
);
2267 MYDB_END_BLOCK_THREADS
;
2269 MYDB_BEGIN_BLOCK_THREADS
;
2271 args
= BuildValue_SS(leftKey
->data
, leftKey
->size
, rightKey
->data
, rightKey
->size
);
2273 /* XXX(twouters) I highly doubt this INCREF is correct */
2275 result
= PyEval_CallObject(self
->btCompareCallback
, args
);
2277 if (args
== NULL
|| result
== NULL
) {
2278 /* we're in a callback within the DB code, we can't raise */
2280 res
= _default_cmp(leftKey
, rightKey
);
2281 } else if (PyInt_Check(result
)) {
2282 res
= PyInt_AsLong(result
);
2284 PyErr_SetString(PyExc_TypeError
,
2285 "DB_bt_compare callback MUST return an int.");
2286 /* we're in a callback within the DB code, we can't raise */
2288 res
= _default_cmp(leftKey
, rightKey
);
2294 MYDB_END_BLOCK_THREADS
;
2300 DB_set_bt_compare(DBObject
* self
, PyObject
* args
)
2303 PyObject
*comparator
;
2304 PyObject
*tuple
, *result
;
2306 if (!PyArg_ParseTuple(args
, "O:set_bt_compare", &comparator
))
2309 CHECK_DB_NOT_CLOSED(self
);
2311 if (!PyCallable_Check(comparator
)) {
2312 makeTypeError("Callable", comparator
);
2317 * Perform a test call of the comparator function with two empty
2318 * string objects here. verify that it returns an int (0).
2321 tuple
= Py_BuildValue("(ss)", "", "");
2322 result
= PyEval_CallObject(comparator
, tuple
);
2326 if (!PyInt_Check(result
)) {
2327 PyErr_SetString(PyExc_TypeError
,
2328 "callback MUST return an int");
2330 } else if (PyInt_AsLong(result
) != 0) {
2331 PyErr_SetString(PyExc_TypeError
,
2332 "callback failed to return 0 on two empty strings");
2337 /* We don't accept multiple set_bt_compare operations, in order to
2338 * simplify the code. This would have no real use, as one cannot
2339 * change the function once the db is opened anyway */
2340 if (self
->btCompareCallback
!= NULL
) {
2341 PyErr_SetString(PyExc_RuntimeError
, "set_bt_compare() cannot be called more than once");
2345 Py_INCREF(comparator
);
2346 self
->btCompareCallback
= comparator
;
2348 /* This is to workaround a problem with un-initialized threads (see
2349 comment in DB_associate) */
2351 PyEval_InitThreads();
2354 err
= self
->db
->set_bt_compare(self
->db
, _db_compareCallback
);
2357 /* restore the old state in case of error */
2358 Py_DECREF(comparator
);
2359 self
->btCompareCallback
= NULL
;
2365 #endif /* DBVER >= 33 */
2369 DB_set_cachesize(DBObject
* self
, PyObject
* args
)
2372 int gbytes
= 0, bytes
= 0, ncache
= 0;
2374 if (!PyArg_ParseTuple(args
,"ii|i:set_cachesize",
2375 &gbytes
,&bytes
,&ncache
))
2377 CHECK_DB_NOT_CLOSED(self
);
2379 MYDB_BEGIN_ALLOW_THREADS
;
2380 err
= self
->db
->set_cachesize(self
->db
, gbytes
, bytes
, ncache
);
2381 MYDB_END_ALLOW_THREADS
;
2388 DB_set_flags(DBObject
* self
, PyObject
* args
)
2392 if (!PyArg_ParseTuple(args
,"i:set_flags", &flags
))
2394 CHECK_DB_NOT_CLOSED(self
);
2396 MYDB_BEGIN_ALLOW_THREADS
;
2397 err
= self
->db
->set_flags(self
->db
, flags
);
2398 MYDB_END_ALLOW_THREADS
;
2401 self
->setflags
|= flags
;
2407 DB_set_h_ffactor(DBObject
* self
, PyObject
* args
)
2411 if (!PyArg_ParseTuple(args
,"i:set_h_ffactor", &ffactor
))
2413 CHECK_DB_NOT_CLOSED(self
);
2415 MYDB_BEGIN_ALLOW_THREADS
;
2416 err
= self
->db
->set_h_ffactor(self
->db
, ffactor
);
2417 MYDB_END_ALLOW_THREADS
;
2424 DB_set_h_nelem(DBObject
* self
, PyObject
* args
)
2428 if (!PyArg_ParseTuple(args
,"i:set_h_nelem", &nelem
))
2430 CHECK_DB_NOT_CLOSED(self
);
2432 MYDB_BEGIN_ALLOW_THREADS
;
2433 err
= self
->db
->set_h_nelem(self
->db
, nelem
);
2434 MYDB_END_ALLOW_THREADS
;
2441 DB_set_lorder(DBObject
* self
, PyObject
* args
)
2445 if (!PyArg_ParseTuple(args
,"i:set_lorder", &lorder
))
2447 CHECK_DB_NOT_CLOSED(self
);
2449 MYDB_BEGIN_ALLOW_THREADS
;
2450 err
= self
->db
->set_lorder(self
->db
, lorder
);
2451 MYDB_END_ALLOW_THREADS
;
2458 DB_set_pagesize(DBObject
* self
, PyObject
* args
)
2462 if (!PyArg_ParseTuple(args
,"i:set_pagesize", &pagesize
))
2464 CHECK_DB_NOT_CLOSED(self
);
2466 MYDB_BEGIN_ALLOW_THREADS
;
2467 err
= self
->db
->set_pagesize(self
->db
, pagesize
);
2468 MYDB_END_ALLOW_THREADS
;
2475 DB_set_re_delim(DBObject
* self
, PyObject
* args
)
2480 if (!PyArg_ParseTuple(args
,"b:set_re_delim", &delim
)) {
2482 if (!PyArg_ParseTuple(args
,"c:set_re_delim", &delim
))
2486 CHECK_DB_NOT_CLOSED(self
);
2488 MYDB_BEGIN_ALLOW_THREADS
;
2489 err
= self
->db
->set_re_delim(self
->db
, delim
);
2490 MYDB_END_ALLOW_THREADS
;
2496 DB_set_re_len(DBObject
* self
, PyObject
* args
)
2500 if (!PyArg_ParseTuple(args
,"i:set_re_len", &len
))
2502 CHECK_DB_NOT_CLOSED(self
);
2504 MYDB_BEGIN_ALLOW_THREADS
;
2505 err
= self
->db
->set_re_len(self
->db
, len
);
2506 MYDB_END_ALLOW_THREADS
;
2513 DB_set_re_pad(DBObject
* self
, PyObject
* args
)
2518 if (!PyArg_ParseTuple(args
,"b:set_re_pad", &pad
)) {
2520 if (!PyArg_ParseTuple(args
,"c:set_re_pad", &pad
))
2523 CHECK_DB_NOT_CLOSED(self
);
2525 MYDB_BEGIN_ALLOW_THREADS
;
2526 err
= self
->db
->set_re_pad(self
->db
, pad
);
2527 MYDB_END_ALLOW_THREADS
;
2534 DB_set_re_source(DBObject
* self
, PyObject
* args
)
2539 if (!PyArg_ParseTuple(args
,"s:set_re_source", &re_source
))
2541 CHECK_DB_NOT_CLOSED(self
);
2543 MYDB_BEGIN_ALLOW_THREADS
;
2544 err
= self
->db
->set_re_source(self
->db
, re_source
);
2545 MYDB_END_ALLOW_THREADS
;
2552 DB_set_q_extentsize(DBObject
* self
, PyObject
* args
)
2557 if (!PyArg_ParseTuple(args
,"i:set_q_extentsize", &extentsize
))
2559 CHECK_DB_NOT_CLOSED(self
);
2561 MYDB_BEGIN_ALLOW_THREADS
;
2562 err
= self
->db
->set_q_extentsize(self
->db
, extentsize
);
2563 MYDB_END_ALLOW_THREADS
;
2569 DB_stat(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2571 int err
, flags
= 0, type
;
2575 PyObject
* txnobj
= NULL
;
2577 static char* kwnames
[] = { "flags", "txn", NULL
};
2579 static char* kwnames
[] = { "flags", NULL
};
2583 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|iO:stat", kwnames
,
2586 if (!checkTxnObj(txnobj
, &txn
))
2589 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:stat", kwnames
, &flags
))
2592 CHECK_DB_NOT_CLOSED(self
);
2594 MYDB_BEGIN_ALLOW_THREADS
;
2596 err
= self
->db
->stat(self
->db
, txn
, &sp
, flags
);
2598 err
= self
->db
->stat(self
->db
, &sp
, flags
);
2600 err
= self
->db
->stat(self
->db
, &sp
, NULL
, flags
);
2602 MYDB_END_ALLOW_THREADS
;
2607 /* Turn the stat structure into a dictionary */
2608 type
= _DB_get_type(self
);
2609 if ((type
== -1) || ((d
= PyDict_New()) == NULL
)) {
2614 #define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2615 #define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2616 #define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2620 MAKE_HASH_ENTRY(magic
);
2621 MAKE_HASH_ENTRY(version
);
2622 MAKE_HASH_ENTRY(nkeys
);
2623 MAKE_HASH_ENTRY(ndata
);
2625 MAKE_HASH_ENTRY(pagecnt
);
2627 MAKE_HASH_ENTRY(pagesize
);
2629 MAKE_HASH_ENTRY(nelem
);
2631 MAKE_HASH_ENTRY(ffactor
);
2632 MAKE_HASH_ENTRY(buckets
);
2633 MAKE_HASH_ENTRY(free
);
2634 MAKE_HASH_ENTRY(bfree
);
2635 MAKE_HASH_ENTRY(bigpages
);
2636 MAKE_HASH_ENTRY(big_bfree
);
2637 MAKE_HASH_ENTRY(overflows
);
2638 MAKE_HASH_ENTRY(ovfl_free
);
2639 MAKE_HASH_ENTRY(dup
);
2640 MAKE_HASH_ENTRY(dup_free
);
2645 MAKE_BT_ENTRY(magic
);
2646 MAKE_BT_ENTRY(version
);
2647 MAKE_BT_ENTRY(nkeys
);
2648 MAKE_BT_ENTRY(ndata
);
2650 MAKE_BT_ENTRY(pagecnt
);
2652 MAKE_BT_ENTRY(pagesize
);
2653 MAKE_BT_ENTRY(minkey
);
2654 MAKE_BT_ENTRY(re_len
);
2655 MAKE_BT_ENTRY(re_pad
);
2656 MAKE_BT_ENTRY(levels
);
2657 MAKE_BT_ENTRY(int_pg
);
2658 MAKE_BT_ENTRY(leaf_pg
);
2659 MAKE_BT_ENTRY(dup_pg
);
2660 MAKE_BT_ENTRY(over_pg
);
2662 MAKE_BT_ENTRY(empty_pg
);
2664 MAKE_BT_ENTRY(free
);
2665 MAKE_BT_ENTRY(int_pgfree
);
2666 MAKE_BT_ENTRY(leaf_pgfree
);
2667 MAKE_BT_ENTRY(dup_pgfree
);
2668 MAKE_BT_ENTRY(over_pgfree
);
2672 MAKE_QUEUE_ENTRY(magic
);
2673 MAKE_QUEUE_ENTRY(version
);
2674 MAKE_QUEUE_ENTRY(nkeys
);
2675 MAKE_QUEUE_ENTRY(ndata
);
2676 MAKE_QUEUE_ENTRY(pagesize
);
2678 MAKE_QUEUE_ENTRY(extentsize
);
2680 MAKE_QUEUE_ENTRY(pages
);
2681 MAKE_QUEUE_ENTRY(re_len
);
2682 MAKE_QUEUE_ENTRY(re_pad
);
2683 MAKE_QUEUE_ENTRY(pgfree
);
2685 MAKE_QUEUE_ENTRY(start
);
2687 MAKE_QUEUE_ENTRY(first_recno
);
2688 MAKE_QUEUE_ENTRY(cur_recno
);
2692 PyErr_SetString(PyExc_TypeError
, "Unknown DB type, unable to stat");
2697 #undef MAKE_HASH_ENTRY
2698 #undef MAKE_BT_ENTRY
2699 #undef MAKE_QUEUE_ENTRY
2706 DB_sync(DBObject
* self
, PyObject
* args
)
2711 if (!PyArg_ParseTuple(args
,"|i:sync", &flags
))
2713 CHECK_DB_NOT_CLOSED(self
);
2715 MYDB_BEGIN_ALLOW_THREADS
;
2716 err
= self
->db
->sync(self
->db
, flags
);
2717 MYDB_END_ALLOW_THREADS
;
2725 DB_truncate(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2729 PyObject
* txnobj
= NULL
;
2731 static char* kwnames
[] = { "txn", "flags", NULL
};
2733 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:cursor", kwnames
,
2736 CHECK_DB_NOT_CLOSED(self
);
2737 if (!checkTxnObj(txnobj
, &txn
))
2740 MYDB_BEGIN_ALLOW_THREADS
;
2741 err
= self
->db
->truncate(self
->db
, txn
, &count
, flags
);
2742 MYDB_END_ALLOW_THREADS
;
2744 return PyInt_FromLong(count
);
2750 DB_upgrade(DBObject
* self
, PyObject
* args
)
2755 if (!PyArg_ParseTuple(args
,"s|i:upgrade", &filename
, &flags
))
2757 CHECK_DB_NOT_CLOSED(self
);
2759 MYDB_BEGIN_ALLOW_THREADS
;
2760 err
= self
->db
->upgrade(self
->db
, filename
, flags
);
2761 MYDB_END_ALLOW_THREADS
;
2768 DB_verify(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2773 char* outFileName
=NULL
;
2775 static char* kwnames
[] = { "filename", "dbname", "outfile", "flags",
2778 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zzi:verify", kwnames
,
2779 &fileName
, &dbName
, &outFileName
, &flags
))
2782 CHECK_DB_NOT_CLOSED(self
);
2784 outFile
= fopen(outFileName
, "w");
2785 /* XXX(nnorwitz): it should probably be an exception if outFile
2788 MYDB_BEGIN_ALLOW_THREADS
;
2789 err
= self
->db
->verify(self
->db
, fileName
, dbName
, outFile
, flags
);
2790 MYDB_END_ALLOW_THREADS
;
2794 { /* DB.verify acts as a DB handle destructor (like close) */
2797 error
=DB_close_internal(self
,0);
2809 DB_set_get_returns_none(DBObject
* self
, PyObject
* args
)
2814 if (!PyArg_ParseTuple(args
,"i:set_get_returns_none", &flags
))
2816 CHECK_DB_NOT_CLOSED(self
);
2818 if (self
->moduleFlags
.getReturnsNone
)
2820 if (self
->moduleFlags
.cursorSetReturnsNone
)
2822 self
->moduleFlags
.getReturnsNone
= (flags
>= 1);
2823 self
->moduleFlags
.cursorSetReturnsNone
= (flags
>= 2);
2824 return PyInt_FromLong(oldValue
);
2829 DB_set_encrypt(DBObject
* self
, PyObject
* args
, PyObject
* kwargs
)
2833 char *passwd
= NULL
;
2834 static char* kwnames
[] = { "passwd", "flags", NULL
};
2836 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|i:set_encrypt", kwnames
,
2841 MYDB_BEGIN_ALLOW_THREADS
;
2842 err
= self
->db
->set_encrypt(self
->db
, passwd
, flags
);
2843 MYDB_END_ALLOW_THREADS
;
2848 #endif /* DBVER >= 41 */
2851 /*-------------------------------------------------------------- */
2852 /* Mapping and Dictionary-like access routines */
2854 Py_ssize_t
DB_length(PyObject
* _self
)
2857 Py_ssize_t size
= 0;
2860 DBObject
* self
= (DBObject
*)_self
;
2862 if (self
->db
== NULL
) {
2863 PyObject
*t
= Py_BuildValue("(is)", 0, "DB object has been closed");
2864 PyErr_SetObject(DBError
, t
);
2869 if (self
->haveStat
) { /* Has the stat function been called recently? If
2870 so, we can use the cached value. */
2871 flags
= DB_FAST_STAT
;
2874 MYDB_BEGIN_ALLOW_THREADS
;
2875 redo_stat_for_length
:
2877 err
= self
->db
->stat(self
->db
, /*txnid*/ NULL
, &sp
, flags
);
2879 err
= self
->db
->stat(self
->db
, &sp
, flags
);
2881 err
= self
->db
->stat(self
->db
, &sp
, NULL
, flags
);
2884 /* All the stat structures have matching fields upto the ndata field,
2885 so we can use any of them for the type cast */
2886 size
= ((DB_BTREE_STAT
*)sp
)->bt_ndata
;
2888 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
2889 * redo a full stat to make sure.
2890 * Fixes SF python bug 1493322, pybsddb bug 1184012
2892 if (size
== 0 && (flags
& DB_FAST_STAT
)) {
2896 goto redo_stat_for_length
;
2899 MYDB_END_ALLOW_THREADS
;
2911 PyObject
* DB_subscript(DBObject
* self
, PyObject
* keyobj
)
2918 CHECK_DB_NOT_CLOSED(self
);
2919 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
2923 if (CHECK_DBFLAG(self
, DB_THREAD
)) {
2924 /* Tell Berkeley DB to malloc the return value (thread safe) */
2925 data
.flags
= DB_DBT_MALLOC
;
2927 MYDB_BEGIN_ALLOW_THREADS
;
2928 err
= self
->db
->get(self
->db
, NULL
, &key
, &data
, 0);
2929 MYDB_END_ALLOW_THREADS
;
2930 if (err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) {
2931 PyErr_SetObject(PyExc_KeyError
, keyobj
);
2934 else if (makeDBError(err
)) {
2938 retval
= Build_PyString(data
.data
, data
.size
);
2948 DB_ass_sub(DBObject
* self
, PyObject
* keyobj
, PyObject
* dataobj
)
2954 if (self
->db
== NULL
) {
2955 PyObject
*t
= Py_BuildValue("(is)", 0, "DB object has been closed");
2956 PyErr_SetObject(DBError
, t
);
2961 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
2964 if (dataobj
!= NULL
) {
2965 if (!make_dbt(dataobj
, &data
))
2968 if (self
->setflags
& (DB_DUP
|DB_DUPSORT
))
2969 /* dictionaries shouldn't have duplicate keys */
2970 flags
= DB_NOOVERWRITE
;
2971 retval
= _DB_put(self
, NULL
, &key
, &data
, flags
);
2973 if ((retval
== -1) && (self
->setflags
& (DB_DUP
|DB_DUPSORT
))) {
2974 /* try deleting any old record that matches and then PUT it
2976 _DB_delete(self
, NULL
, &key
, 0);
2978 retval
= _DB_put(self
, NULL
, &key
, &data
, flags
);
2983 /* dataobj == NULL, so delete the key */
2984 retval
= _DB_delete(self
, NULL
, &key
, 0);
2992 DB_has_key(DBObject
* self
, PyObject
* args
)
2997 PyObject
* txnobj
= NULL
;
3000 if (!PyArg_ParseTuple(args
,"O|O:has_key", &keyobj
, &txnobj
))
3002 CHECK_DB_NOT_CLOSED(self
);
3003 if (!make_key_dbt(self
, keyobj
, &key
, NULL
))
3005 if (!checkTxnObj(txnobj
, &txn
)) {
3010 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
3011 it has a record but can't allocate a buffer for the data. This saves
3012 having to deal with data we won't be using.
3015 data
.flags
= DB_DBT_USERMEM
;
3017 MYDB_BEGIN_ALLOW_THREADS
;
3018 err
= self
->db
->get(self
->db
, txn
, &key
, &data
, 0);
3019 MYDB_END_ALLOW_THREADS
;
3022 if (err
== DB_BUFFER_SMALL
|| err
== 0) {
3023 return PyInt_FromLong(1);
3024 } else if (err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) {
3025 return PyInt_FromLong(0);
3033 #define _KEYS_LIST 1
3034 #define _VALUES_LIST 2
3035 #define _ITEMS_LIST 3
3038 _DB_make_list(DBObject
* self
, DB_TXN
* txn
, int type
)
3045 PyObject
* item
= NULL
;
3047 CHECK_DB_NOT_CLOSED(self
);
3051 dbtype
= _DB_get_type(self
);
3055 list
= PyList_New(0);
3060 MYDB_BEGIN_ALLOW_THREADS
;
3061 err
= self
->db
->cursor(self
->db
, txn
, &cursor
, 0);
3062 MYDB_END_ALLOW_THREADS
;
3063 if (makeDBError(err
)) {
3068 while (1) { /* use the cursor to traverse the DB, collecting items */
3069 MYDB_BEGIN_ALLOW_THREADS
;
3070 err
= _DBC_get(cursor
, &key
, &data
, DB_NEXT
);
3071 MYDB_END_ALLOW_THREADS
;
3074 /* for any error, break out of the loop */
3084 item
= Build_PyString(key
.data
, key
.size
);
3088 item
= PyInt_FromLong(*((db_recno_t
*)key
.data
));
3094 item
= Build_PyString(data
.data
, data
.size
);
3102 item
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
3106 item
= BuildValue_IS(*((db_recno_t
*)key
.data
), data
.data
, data
.size
);
3111 PyErr_Format(PyExc_ValueError
, "Unknown key type 0x%x", type
);
3120 PyList_Append(list
, item
);
3124 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3125 if (err
!= DB_NOTFOUND
&& err
!= DB_KEYEMPTY
&& makeDBError(err
)) {
3131 MYDB_BEGIN_ALLOW_THREADS
;
3133 MYDB_END_ALLOW_THREADS
;
3139 DB_keys(DBObject
* self
, PyObject
* args
)
3141 PyObject
* txnobj
= NULL
;
3144 if (!PyArg_UnpackTuple(args
, "keys", 0, 1, &txnobj
))
3146 if (!checkTxnObj(txnobj
, &txn
))
3148 return _DB_make_list(self
, txn
, _KEYS_LIST
);
3153 DB_items(DBObject
* self
, PyObject
* args
)
3155 PyObject
* txnobj
= NULL
;
3158 if (!PyArg_UnpackTuple(args
, "items", 0, 1, &txnobj
))
3160 if (!checkTxnObj(txnobj
, &txn
))
3162 return _DB_make_list(self
, txn
, _ITEMS_LIST
);
3167 DB_values(DBObject
* self
, PyObject
* args
)
3169 PyObject
* txnobj
= NULL
;
3172 if (!PyArg_UnpackTuple(args
, "values", 0, 1, &txnobj
))
3174 if (!checkTxnObj(txnobj
, &txn
))
3176 return _DB_make_list(self
, txn
, _VALUES_LIST
);
3179 /* --------------------------------------------------------------------- */
3180 /* DBCursor methods */
3184 DBC_close_internal(DBCursorObject
* self
)
3188 if (self
->dbc
!= NULL
) {
3189 EXTRACT_FROM_DOUBLE_LINKED_LIST(self
);
3191 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self
);
3195 MYDB_BEGIN_ALLOW_THREADS
;
3196 err
= _DBC_close(self
->dbc
);
3197 MYDB_END_ALLOW_THREADS
;
3205 DBC_close(DBCursorObject
* self
, PyObject
* args
)
3207 if (!PyArg_ParseTuple(args
, ":close"))
3210 return DBC_close_internal(self
);
3215 DBC_count(DBCursorObject
* self
, PyObject
* args
)
3221 if (!PyArg_ParseTuple(args
, "|i:count", &flags
))
3224 CHECK_CURSOR_NOT_CLOSED(self
);
3226 MYDB_BEGIN_ALLOW_THREADS
;
3227 err
= _DBC_count(self
->dbc
, &count
, flags
);
3228 MYDB_END_ALLOW_THREADS
;
3231 return PyInt_FromLong(count
);
3236 DBC_current(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3238 return _DBCursor_get(self
,DB_CURRENT
,args
,kwargs
,"|iii:current");
3243 DBC_delete(DBCursorObject
* self
, PyObject
* args
)
3247 if (!PyArg_ParseTuple(args
, "|i:delete", &flags
))
3250 CHECK_CURSOR_NOT_CLOSED(self
);
3252 MYDB_BEGIN_ALLOW_THREADS
;
3253 err
= _DBC_del(self
->dbc
, flags
);
3254 MYDB_END_ALLOW_THREADS
;
3257 self
->mydb
->haveStat
= 0;
3263 DBC_dup(DBCursorObject
* self
, PyObject
* args
)
3268 if (!PyArg_ParseTuple(args
, "|i:dup", &flags
))
3271 CHECK_CURSOR_NOT_CLOSED(self
);
3273 MYDB_BEGIN_ALLOW_THREADS
;
3274 err
= _DBC_dup(self
->dbc
, &dbc
, flags
);
3275 MYDB_END_ALLOW_THREADS
;
3278 return (PyObject
*) newDBCursorObject(dbc
, self
->txn
, self
->mydb
);
3282 DBC_first(DBCursorObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3284 return _DBCursor_get(self
,DB_FIRST
,args
,kwargs
,"|iii:first");
3289 DBC_get(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3292 PyObject
* keyobj
= NULL
;
3293 PyObject
* dataobj
= NULL
;
3294 PyObject
* retval
= NULL
;
3298 static char* kwnames
[] = { "key","data", "flags", "dlen", "doff",
3303 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|ii:get", &kwnames
[2],
3304 &flags
, &dlen
, &doff
))
3307 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "Oi|ii:get",
3309 &keyobj
, &flags
, &dlen
, &doff
))
3312 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OOi|ii:get",
3313 kwnames
, &keyobj
, &dataobj
,
3314 &flags
, &dlen
, &doff
))
3321 CHECK_CURSOR_NOT_CLOSED(self
);
3323 if (keyobj
&& !make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3325 if ( (dataobj
&& !make_dbt(dataobj
, &data
)) ||
3326 (!add_partial_dbt(&data
, dlen
, doff
)) )
3328 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3332 MYDB_BEGIN_ALLOW_THREADS
;
3333 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
);
3334 MYDB_END_ALLOW_THREADS
;
3336 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3337 && self
->mydb
->moduleFlags
.getReturnsNone
) {
3341 else if (makeDBError(err
)) {
3345 switch (_DB_get_type(self
->mydb
)) {
3352 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
3356 retval
= BuildValue_IS(*((db_recno_t
*)key
.data
), data
.data
, data
.size
);
3360 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3366 DBC_pget(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3369 PyObject
* keyobj
= NULL
;
3370 PyObject
* dataobj
= NULL
;
3371 PyObject
* retval
= NULL
;
3374 DBT key
, pkey
, data
;
3375 static char* kwnames_keyOnly
[] = { "key", "flags", "dlen", "doff", NULL
};
3376 static char* kwnames
[] = { "key", "data", "flags", "dlen", "doff", NULL
};
3380 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|ii:pget", &kwnames
[2],
3381 &flags
, &dlen
, &doff
))
3384 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "Oi|ii:pget",
3386 &keyobj
, &flags
, &dlen
, &doff
))
3389 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OOi|ii:pget",
3390 kwnames
, &keyobj
, &dataobj
,
3391 &flags
, &dlen
, &doff
))
3398 CHECK_CURSOR_NOT_CLOSED(self
);
3400 if (keyobj
&& !make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3402 if ( (dataobj
&& !make_dbt(dataobj
, &data
)) ||
3403 (!add_partial_dbt(&data
, dlen
, doff
)) ) {
3404 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3409 pkey
.flags
= DB_DBT_MALLOC
;
3411 MYDB_BEGIN_ALLOW_THREADS
;
3412 err
= _DBC_pget(self
->dbc
, &key
, &pkey
, &data
, flags
);
3413 MYDB_END_ALLOW_THREADS
;
3415 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3416 && self
->mydb
->moduleFlags
.getReturnsNone
) {
3420 else if (makeDBError(err
)) {
3426 dataObj
= Build_PyString(data
.data
, data
.size
);
3428 if (self
->mydb
->primaryDBType
== DB_RECNO
||
3429 self
->mydb
->primaryDBType
== DB_QUEUE
)
3430 pkeyObj
= PyInt_FromLong(*(int *)pkey
.data
);
3432 pkeyObj
= Build_PyString(pkey
.data
, pkey
.size
);
3434 if (key
.data
&& key
.size
) /* return key, pkey and data */
3437 int type
= _DB_get_type(self
->mydb
);
3438 if (type
== DB_RECNO
|| type
== DB_QUEUE
)
3439 keyObj
= PyInt_FromLong(*(int *)key
.data
);
3441 keyObj
= Build_PyString(key
.data
, key
.size
);
3442 #if (PY_VERSION_HEX >= 0x02040000)
3443 retval
= PyTuple_Pack(3, keyObj
, pkeyObj
, dataObj
);
3445 retval
= Py_BuildValue("OOO", keyObj
, pkeyObj
, dataObj
);
3448 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3450 else /* return just the pkey and data */
3452 #if (PY_VERSION_HEX >= 0x02040000)
3453 retval
= PyTuple_Pack(2, pkeyObj
, dataObj
);
3455 retval
= Py_BuildValue("OO", pkeyObj
, dataObj
);
3462 /* the only time REALLOC should be set is if we used an integer
3463 * key that make_key_dbt malloc'd for us. always free these. */
3464 if (key
.flags
& DB_DBT_REALLOC
) { /* 'make_key_dbt' could do a 'malloc' */
3473 DBC_get_recno(DBCursorObject
* self
, PyObject
* args
)
3480 if (!PyArg_ParseTuple(args
, ":get_recno"))
3483 CHECK_CURSOR_NOT_CLOSED(self
);
3488 MYDB_BEGIN_ALLOW_THREADS
;
3489 err
= _DBC_get(self
->dbc
, &key
, &data
, DB_GET_RECNO
);
3490 MYDB_END_ALLOW_THREADS
;
3493 recno
= *((db_recno_t
*)data
.data
);
3494 return PyInt_FromLong(recno
);
3499 DBC_last(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3501 return _DBCursor_get(self
,DB_LAST
,args
,kwargs
,"|iii:last");
3506 DBC_next(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3508 return _DBCursor_get(self
,DB_NEXT
,args
,kwargs
,"|iii:next");
3513 DBC_prev(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3515 return _DBCursor_get(self
,DB_PREV
,args
,kwargs
,"|iii:prev");
3520 DBC_put(DBCursorObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3523 PyObject
* keyobj
, *dataobj
;
3525 static char* kwnames
[] = { "key", "data", "flags", "dlen", "doff",
3530 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "OO|iii:put", kwnames
,
3531 &keyobj
, &dataobj
, &flags
, &dlen
, &doff
))
3534 CHECK_CURSOR_NOT_CLOSED(self
);
3536 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3538 if (!make_dbt(dataobj
, &data
) ||
3539 !add_partial_dbt(&data
, dlen
, doff
) )
3541 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3545 MYDB_BEGIN_ALLOW_THREADS
;
3546 err
= _DBC_put(self
->dbc
, &key
, &data
, flags
);
3547 MYDB_END_ALLOW_THREADS
;
3548 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3550 self
->mydb
->haveStat
= 0;
3556 DBC_set(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3560 PyObject
* retval
, *keyobj
;
3561 static char* kwnames
[] = { "key", "flags", "dlen", "doff", NULL
};
3565 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|iii:set", kwnames
,
3566 &keyobj
, &flags
, &dlen
, &doff
))
3569 CHECK_CURSOR_NOT_CLOSED(self
);
3571 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3575 if (!add_partial_dbt(&data
, dlen
, doff
)) {
3576 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3580 MYDB_BEGIN_ALLOW_THREADS
;
3581 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
|DB_SET
);
3582 MYDB_END_ALLOW_THREADS
;
3583 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3584 && self
->mydb
->moduleFlags
.cursorSetReturnsNone
) {
3588 else if (makeDBError(err
)) {
3592 switch (_DB_get_type(self
->mydb
)) {
3599 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
3603 retval
= BuildValue_IS(*((db_recno_t
*)key
.data
), data
.data
, data
.size
);
3606 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3608 /* the only time REALLOC should be set is if we used an integer
3609 * key that make_key_dbt malloc'd for us. always free these. */
3610 if (key
.flags
& DB_DBT_REALLOC
) {
3611 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3619 DBC_set_range(DBCursorObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3623 PyObject
* retval
, *keyobj
;
3624 static char* kwnames
[] = { "key", "flags", "dlen", "doff", NULL
};
3628 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|iii:set_range", kwnames
,
3629 &keyobj
, &flags
, &dlen
, &doff
))
3632 CHECK_CURSOR_NOT_CLOSED(self
);
3634 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3638 if (!add_partial_dbt(&data
, dlen
, doff
)) {
3639 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3642 MYDB_BEGIN_ALLOW_THREADS
;
3643 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
|DB_SET_RANGE
);
3644 MYDB_END_ALLOW_THREADS
;
3645 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3646 && self
->mydb
->moduleFlags
.cursorSetReturnsNone
) {
3650 else if (makeDBError(err
)) {
3654 switch (_DB_get_type(self
->mydb
)) {
3661 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
3665 retval
= BuildValue_IS(*((db_recno_t
*)key
.data
), data
.data
, data
.size
);
3668 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3670 /* the only time REALLOC should be set is if we used an integer
3671 * key that make_key_dbt malloc'd for us. always free these. */
3672 if (key
.flags
& DB_DBT_REALLOC
) {
3673 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3680 _DBC_get_set_both(DBCursorObject
* self
, PyObject
* keyobj
, PyObject
* dataobj
,
3681 int flags
, unsigned int returnsNone
)
3687 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
3688 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
3690 if (!make_dbt(dataobj
, &data
)) {
3691 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3695 MYDB_BEGIN_ALLOW_THREADS
;
3696 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
|DB_GET_BOTH
);
3697 MYDB_END_ALLOW_THREADS
;
3698 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
) && returnsNone
) {
3702 else if (makeDBError(err
)) {
3706 switch (_DB_get_type(self
->mydb
)) {
3713 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
3717 retval
= BuildValue_IS(*((db_recno_t
*)key
.data
), data
.data
, data
.size
);
3722 FREE_DBT(key
); /* 'make_key_dbt' could do a 'malloc' */
3727 DBC_get_both(DBCursorObject
* self
, PyObject
* args
)
3730 PyObject
*keyobj
, *dataobj
;
3732 if (!PyArg_ParseTuple(args
, "OO|i:get_both", &keyobj
, &dataobj
, &flags
))
3735 /* if the cursor is closed, self->mydb may be invalid */
3736 CHECK_CURSOR_NOT_CLOSED(self
);
3738 return _DBC_get_set_both(self
, keyobj
, dataobj
, flags
,
3739 self
->mydb
->moduleFlags
.getReturnsNone
);
3742 /* Return size of entry */
3744 DBC_get_current_size(DBCursorObject
* self
, PyObject
* args
)
3746 int err
, flags
=DB_CURRENT
;
3747 PyObject
* retval
= NULL
;
3750 if (!PyArg_ParseTuple(args
, ":get_current_size"))
3752 CHECK_CURSOR_NOT_CLOSED(self
);
3756 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
3757 getting the record size. */
3758 data
.flags
= DB_DBT_USERMEM
;
3760 MYDB_BEGIN_ALLOW_THREADS
;
3761 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
);
3762 MYDB_END_ALLOW_THREADS
;
3763 if (err
== DB_BUFFER_SMALL
|| !err
) {
3764 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
3765 retval
= PyInt_FromLong((long)data
.size
);
3774 DBC_set_both(DBCursorObject
* self
, PyObject
* args
)
3777 PyObject
*keyobj
, *dataobj
;
3779 if (!PyArg_ParseTuple(args
, "OO|i:set_both", &keyobj
, &dataobj
, &flags
))
3782 /* if the cursor is closed, self->mydb may be invalid */
3783 CHECK_CURSOR_NOT_CLOSED(self
);
3785 return _DBC_get_set_both(self
, keyobj
, dataobj
, flags
,
3786 self
->mydb
->moduleFlags
.cursorSetReturnsNone
);
3791 DBC_set_recno(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3793 int err
, irecno
, flags
=0;
3799 static char* kwnames
[] = { "recno","flags", "dlen", "doff", NULL
};
3801 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "i|iii:set_recno", kwnames
,
3802 &irecno
, &flags
, &dlen
, &doff
))
3805 CHECK_CURSOR_NOT_CLOSED(self
);
3808 recno
= (db_recno_t
) irecno
;
3809 /* use allocated space so DB will be able to realloc room for the real
3811 key
.data
= malloc(sizeof(db_recno_t
));
3812 if (key
.data
== NULL
) {
3813 PyErr_SetString(PyExc_MemoryError
, "Key memory allocation failed");
3816 key
.size
= sizeof(db_recno_t
);
3817 key
.ulen
= key
.size
;
3818 memcpy(key
.data
, &recno
, sizeof(db_recno_t
));
3819 key
.flags
= DB_DBT_REALLOC
;
3822 if (!add_partial_dbt(&data
, dlen
, doff
)) {
3827 MYDB_BEGIN_ALLOW_THREADS
;
3828 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
|DB_SET_RECNO
);
3829 MYDB_END_ALLOW_THREADS
;
3830 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3831 && self
->mydb
->moduleFlags
.cursorSetReturnsNone
) {
3835 else if (makeDBError(err
)) {
3838 else { /* Can only be used for BTrees, so no need to return int key */
3839 retval
= BuildValue_SS(key
.data
, key
.size
, data
.data
, data
.size
);
3848 DBC_consume(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3850 return _DBCursor_get(self
,DB_CONSUME
,args
,kwargs
,"|iii:consume");
3855 DBC_next_dup(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3857 return _DBCursor_get(self
,DB_NEXT_DUP
,args
,kwargs
,"|iii:next_dup");
3862 DBC_next_nodup(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3864 return _DBCursor_get(self
,DB_NEXT_NODUP
,args
,kwargs
,"|iii:next_nodup");
3869 DBC_prev_nodup(DBCursorObject
* self
, PyObject
* args
, PyObject
*kwargs
)
3871 return _DBCursor_get(self
,DB_PREV_NODUP
,args
,kwargs
,"|iii:prev_nodup");
3876 DBC_join_item(DBCursorObject
* self
, PyObject
* args
)
3882 if (!PyArg_ParseTuple(args
, "|i:join_item", &flags
))
3885 CHECK_CURSOR_NOT_CLOSED(self
);
3890 MYDB_BEGIN_ALLOW_THREADS
;
3891 err
= _DBC_get(self
->dbc
, &key
, &data
, flags
| DB_JOIN_ITEM
);
3892 MYDB_END_ALLOW_THREADS
;
3893 if ((err
== DB_NOTFOUND
|| err
== DB_KEYEMPTY
)
3894 && self
->mydb
->moduleFlags
.getReturnsNone
) {
3898 else if (makeDBError(err
)) {
3902 retval
= BuildValue_S(key
.data
, key
.size
);
3910 /* --------------------------------------------------------------------- */
3915 DBEnv_close_internal(DBEnvObject
* self
, int flags
)
3920 if (!self
->closed
) { /* Don't close more than once */
3921 while(self
->children_txns
) {
3922 dummy
=DBTxn_abort_discard_internal(self
->children_txns
,0);
3925 while(self
->children_dbs
) {
3926 dummy
=DB_close_internal(self
->children_dbs
,0);
3930 MYDB_BEGIN_ALLOW_THREADS
;
3931 err
= self
->db_env
->close(self
->db_env
, flags
);
3932 MYDB_END_ALLOW_THREADS
;
3933 /* after calling DBEnv->close, regardless of error, this DBEnv
3934 * may not be accessed again (Berkeley DB docs). */
3936 self
->db_env
= NULL
;
3943 DBEnv_close(DBEnvObject
* self
, PyObject
* args
)
3947 if (!PyArg_ParseTuple(args
, "|i:close", &flags
))
3949 return DBEnv_close_internal(self
,flags
);
3954 DBEnv_open(DBEnvObject
* self
, PyObject
* args
)
3956 int err
, flags
=0, mode
=0660;
3959 if (!PyArg_ParseTuple(args
, "z|ii:open", &db_home
, &flags
, &mode
))
3962 CHECK_ENV_NOT_CLOSED(self
);
3964 MYDB_BEGIN_ALLOW_THREADS
;
3965 err
= self
->db_env
->open(self
->db_env
, db_home
, flags
, mode
);
3966 MYDB_END_ALLOW_THREADS
;
3969 self
->flags
= flags
;
3975 DBEnv_remove(DBEnvObject
* self
, PyObject
* args
)
3980 if (!PyArg_ParseTuple(args
, "s|i:remove", &db_home
, &flags
))
3982 CHECK_ENV_NOT_CLOSED(self
);
3983 MYDB_BEGIN_ALLOW_THREADS
;
3984 err
= self
->db_env
->remove(self
->db_env
, db_home
, flags
);
3985 MYDB_END_ALLOW_THREADS
;
3992 DBEnv_dbremove(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
3997 char *database
= NULL
;
3998 PyObject
*txnobj
= NULL
;
4000 static char* kwnames
[] = { "file", "database", "txn", "flags",
4003 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|zOi:dbremove", kwnames
,
4004 &file
, &database
, &txnobj
, &flags
)) {
4007 if (!checkTxnObj(txnobj
, &txn
)) {
4010 CHECK_ENV_NOT_CLOSED(self
);
4011 MYDB_BEGIN_ALLOW_THREADS
;
4012 err
= self
->db_env
->dbremove(self
->db_env
, txn
, file
, database
, flags
);
4013 MYDB_END_ALLOW_THREADS
;
4019 DBEnv_dbrename(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4024 char *database
= NULL
;
4025 char *newname
= NULL
;
4026 PyObject
*txnobj
= NULL
;
4028 static char* kwnames
[] = { "file", "database", "newname", "txn",
4031 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "szs|Oi:dbrename", kwnames
,
4032 &file
, &database
, &newname
, &txnobj
, &flags
)) {
4035 if (!checkTxnObj(txnobj
, &txn
)) {
4038 CHECK_ENV_NOT_CLOSED(self
);
4039 MYDB_BEGIN_ALLOW_THREADS
;
4040 err
= self
->db_env
->dbrename(self
->db_env
, txn
, file
, database
, newname
,
4042 MYDB_END_ALLOW_THREADS
;
4048 DBEnv_set_encrypt(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4052 char *passwd
= NULL
;
4053 static char* kwnames
[] = { "passwd", "flags", NULL
};
4055 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|i:set_encrypt", kwnames
,
4060 MYDB_BEGIN_ALLOW_THREADS
;
4061 err
= self
->db_env
->set_encrypt(self
->db_env
, passwd
, flags
);
4062 MYDB_END_ALLOW_THREADS
;
4067 #endif /* DBVER >= 41 */
4071 DBEnv_set_timeout(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4075 u_int32_t timeout
= 0;
4076 static char* kwnames
[] = { "timeout", "flags", NULL
};
4078 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "ii:set_timeout", kwnames
,
4079 &timeout
, &flags
)) {
4083 MYDB_BEGIN_ALLOW_THREADS
;
4084 err
= self
->db_env
->set_timeout(self
->db_env
, (db_timeout_t
)timeout
, flags
);
4085 MYDB_END_ALLOW_THREADS
;
4090 #endif /* DBVER >= 40 */
4093 DBEnv_set_shm_key(DBEnvObject
* self
, PyObject
* args
)
4098 if (!PyArg_ParseTuple(args
, "l:set_shm_key", &shm_key
))
4100 CHECK_ENV_NOT_CLOSED(self
);
4102 err
= self
->db_env
->set_shm_key(self
->db_env
, shm_key
);
4108 DBEnv_set_cachesize(DBEnvObject
* self
, PyObject
* args
)
4110 int err
, gbytes
=0, bytes
=0, ncache
=0;
4112 if (!PyArg_ParseTuple(args
, "ii|i:set_cachesize",
4113 &gbytes
, &bytes
, &ncache
))
4115 CHECK_ENV_NOT_CLOSED(self
);
4117 MYDB_BEGIN_ALLOW_THREADS
;
4118 err
= self
->db_env
->set_cachesize(self
->db_env
, gbytes
, bytes
, ncache
);
4119 MYDB_END_ALLOW_THREADS
;
4126 DBEnv_set_flags(DBEnvObject
* self
, PyObject
* args
)
4128 int err
, flags
=0, onoff
=0;
4130 if (!PyArg_ParseTuple(args
, "ii:set_flags",
4133 CHECK_ENV_NOT_CLOSED(self
);
4135 MYDB_BEGIN_ALLOW_THREADS
;
4136 err
= self
->db_env
->set_flags(self
->db_env
, flags
, onoff
);
4137 MYDB_END_ALLOW_THREADS
;
4145 DBEnv_log_set_config(DBEnvObject
* self
, PyObject
* args
)
4147 int err
, flags
, onoff
;
4149 if (!PyArg_ParseTuple(args
, "ii:log_set_config",
4152 CHECK_ENV_NOT_CLOSED(self
);
4154 MYDB_BEGIN_ALLOW_THREADS
;
4155 err
= self
->db_env
->log_set_config(self
->db_env
, flags
, onoff
);
4156 MYDB_END_ALLOW_THREADS
;
4160 #endif /* DBVER >= 47 */
4164 DBEnv_set_data_dir(DBEnvObject
* self
, PyObject
* args
)
4169 if (!PyArg_ParseTuple(args
, "s:set_data_dir", &dir
))
4171 CHECK_ENV_NOT_CLOSED(self
);
4173 MYDB_BEGIN_ALLOW_THREADS
;
4174 err
= self
->db_env
->set_data_dir(self
->db_env
, dir
);
4175 MYDB_END_ALLOW_THREADS
;
4182 DBEnv_set_lg_bsize(DBEnvObject
* self
, PyObject
* args
)
4186 if (!PyArg_ParseTuple(args
, "i:set_lg_bsize", &lg_bsize
))
4188 CHECK_ENV_NOT_CLOSED(self
);
4190 MYDB_BEGIN_ALLOW_THREADS
;
4191 err
= self
->db_env
->set_lg_bsize(self
->db_env
, lg_bsize
);
4192 MYDB_END_ALLOW_THREADS
;
4199 DBEnv_set_lg_dir(DBEnvObject
* self
, PyObject
* args
)
4204 if (!PyArg_ParseTuple(args
, "s:set_lg_dir", &dir
))
4206 CHECK_ENV_NOT_CLOSED(self
);
4208 MYDB_BEGIN_ALLOW_THREADS
;
4209 err
= self
->db_env
->set_lg_dir(self
->db_env
, dir
);
4210 MYDB_END_ALLOW_THREADS
;
4216 DBEnv_set_lg_max(DBEnvObject
* self
, PyObject
* args
)
4220 if (!PyArg_ParseTuple(args
, "i:set_lg_max", &lg_max
))
4222 CHECK_ENV_NOT_CLOSED(self
);
4224 MYDB_BEGIN_ALLOW_THREADS
;
4225 err
= self
->db_env
->set_lg_max(self
->db_env
, lg_max
);
4226 MYDB_END_ALLOW_THREADS
;
4233 DBEnv_get_lg_max(DBEnvObject
* self
, PyObject
* args
)
4238 if (!PyArg_ParseTuple(args
, ":get_lg_max"))
4240 CHECK_ENV_NOT_CLOSED(self
);
4242 MYDB_BEGIN_ALLOW_THREADS
;
4243 err
= self
->db_env
->get_lg_max(self
->db_env
, &lg_max
);
4244 MYDB_END_ALLOW_THREADS
;
4246 return PyInt_FromLong(lg_max
);
4253 DBEnv_set_lg_regionmax(DBEnvObject
* self
, PyObject
* args
)
4257 if (!PyArg_ParseTuple(args
, "i:set_lg_regionmax", &lg_max
))
4259 CHECK_ENV_NOT_CLOSED(self
);
4261 MYDB_BEGIN_ALLOW_THREADS
;
4262 err
= self
->db_env
->set_lg_regionmax(self
->db_env
, lg_max
);
4263 MYDB_END_ALLOW_THREADS
;
4271 DBEnv_set_lk_detect(DBEnvObject
* self
, PyObject
* args
)
4275 if (!PyArg_ParseTuple(args
, "i:set_lk_detect", &lk_detect
))
4277 CHECK_ENV_NOT_CLOSED(self
);
4279 MYDB_BEGIN_ALLOW_THREADS
;
4280 err
= self
->db_env
->set_lk_detect(self
->db_env
, lk_detect
);
4281 MYDB_END_ALLOW_THREADS
;
4289 DBEnv_set_lk_max(DBEnvObject
* self
, PyObject
* args
)
4293 if (!PyArg_ParseTuple(args
, "i:set_lk_max", &max
))
4295 CHECK_ENV_NOT_CLOSED(self
);
4297 MYDB_BEGIN_ALLOW_THREADS
;
4298 err
= self
->db_env
->set_lk_max(self
->db_env
, max
);
4299 MYDB_END_ALLOW_THREADS
;
4308 DBEnv_set_lk_max_locks(DBEnvObject
* self
, PyObject
* args
)
4312 if (!PyArg_ParseTuple(args
, "i:set_lk_max_locks", &max
))
4314 CHECK_ENV_NOT_CLOSED(self
);
4316 MYDB_BEGIN_ALLOW_THREADS
;
4317 err
= self
->db_env
->set_lk_max_locks(self
->db_env
, max
);
4318 MYDB_END_ALLOW_THREADS
;
4325 DBEnv_set_lk_max_lockers(DBEnvObject
* self
, PyObject
* args
)
4329 if (!PyArg_ParseTuple(args
, "i:set_lk_max_lockers", &max
))
4331 CHECK_ENV_NOT_CLOSED(self
);
4333 MYDB_BEGIN_ALLOW_THREADS
;
4334 err
= self
->db_env
->set_lk_max_lockers(self
->db_env
, max
);
4335 MYDB_END_ALLOW_THREADS
;
4342 DBEnv_set_lk_max_objects(DBEnvObject
* self
, PyObject
* args
)
4346 if (!PyArg_ParseTuple(args
, "i:set_lk_max_objects", &max
))
4348 CHECK_ENV_NOT_CLOSED(self
);
4350 MYDB_BEGIN_ALLOW_THREADS
;
4351 err
= self
->db_env
->set_lk_max_objects(self
->db_env
, max
);
4352 MYDB_END_ALLOW_THREADS
;
4359 DBEnv_set_mp_mmapsize(DBEnvObject
* self
, PyObject
* args
)
4361 int err
, mp_mmapsize
;
4363 if (!PyArg_ParseTuple(args
, "i:set_mp_mmapsize", &mp_mmapsize
))
4365 CHECK_ENV_NOT_CLOSED(self
);
4367 MYDB_BEGIN_ALLOW_THREADS
;
4368 err
= self
->db_env
->set_mp_mmapsize(self
->db_env
, mp_mmapsize
);
4369 MYDB_END_ALLOW_THREADS
;
4376 DBEnv_set_tmp_dir(DBEnvObject
* self
, PyObject
* args
)
4381 if (!PyArg_ParseTuple(args
, "s:set_tmp_dir", &dir
))
4383 CHECK_ENV_NOT_CLOSED(self
);
4385 MYDB_BEGIN_ALLOW_THREADS
;
4386 err
= self
->db_env
->set_tmp_dir(self
->db_env
, dir
);
4387 MYDB_END_ALLOW_THREADS
;
4395 DBEnv_txn_recover(DBEnvObject
* self
, PyObject
* args
)
4397 int flags
= DB_FIRST
;
4399 PyObject
*list
, *tuple
, *gid
;
4401 #define PREPLIST_LEN 16
4402 DB_PREPLIST preplist
[PREPLIST_LEN
];
4405 if (!PyArg_ParseTuple(args
, ":txn_recover"))
4408 CHECK_ENV_NOT_CLOSED(self
);
4414 MYDB_BEGIN_ALLOW_THREADS
4415 err
=self
->db_env
->txn_recover(self
->db_env
,
4416 preplist
, PREPLIST_LEN
, &retp
, flags
);
4418 MYDB_END_ALLOW_THREADS
4424 flags
=DB_NEXT
; /* Prepare for next loop pass */
4425 for (i
=0; i
<retp
; i
++) {
4426 gid
=PyBytes_FromStringAndSize((char *)(preplist
[i
].gid
),
4432 txn
=newDBTxnObject(self
, NULL
, preplist
[i
].txn
, flags
);
4438 txn
->flag_prepare
=1; /* Recover state */
4439 tuple
=PyTuple_New(2);
4446 if (PyTuple_SetItem(tuple
, 0, gid
)) {
4453 if (PyTuple_SetItem(tuple
, 1, (PyObject
*)txn
)) {
4456 Py_DECREF(tuple
); /* This delete the "gid" also */
4459 if (PyList_Append(list
, tuple
)) {
4461 Py_DECREF(tuple
);/* This delete the "gid" and the "txn" also */
4472 DBEnv_txn_begin(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4475 PyObject
* txnobj
= NULL
;
4477 static char* kwnames
[] = { "parent", "flags", NULL
};
4479 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:txn_begin", kwnames
,
4483 if (!checkTxnObj(txnobj
, &txn
))
4485 CHECK_ENV_NOT_CLOSED(self
);
4487 return (PyObject
*)newDBTxnObject(self
, (DBTxnObject
*)txnobj
, NULL
, flags
);
4492 DBEnv_txn_checkpoint(DBEnvObject
* self
, PyObject
* args
)
4494 int err
, kbyte
=0, min
=0, flags
=0;
4496 if (!PyArg_ParseTuple(args
, "|iii:txn_checkpoint", &kbyte
, &min
, &flags
))
4498 CHECK_ENV_NOT_CLOSED(self
);
4500 MYDB_BEGIN_ALLOW_THREADS
;
4502 err
= self
->db_env
->txn_checkpoint(self
->db_env
, kbyte
, min
, flags
);
4504 err
= txn_checkpoint(self
->db_env
, kbyte
, min
, flags
);
4506 MYDB_END_ALLOW_THREADS
;
4513 DBEnv_set_tx_max(DBEnvObject
* self
, PyObject
* args
)
4517 if (!PyArg_ParseTuple(args
, "i:set_tx_max", &max
))
4519 CHECK_ENV_NOT_CLOSED(self
);
4521 err
= self
->db_env
->set_tx_max(self
->db_env
, max
);
4528 DBEnv_set_tx_timestamp(DBEnvObject
* self
, PyObject
* args
)
4534 if (!PyArg_ParseTuple(args
, "l:set_tx_timestamp", &stamp
))
4536 CHECK_ENV_NOT_CLOSED(self
);
4537 timestamp
= (time_t)stamp
;
4538 err
= self
->db_env
->set_tx_timestamp(self
->db_env
, ×tamp
);
4545 DBEnv_lock_detect(DBEnvObject
* self
, PyObject
* args
)
4547 int err
, atype
, flags
=0;
4550 if (!PyArg_ParseTuple(args
, "i|i:lock_detect", &atype
, &flags
))
4552 CHECK_ENV_NOT_CLOSED(self
);
4554 MYDB_BEGIN_ALLOW_THREADS
;
4556 err
= self
->db_env
->lock_detect(self
->db_env
, flags
, atype
, &aborted
);
4558 err
= lock_detect(self
->db_env
, flags
, atype
, &aborted
);
4560 MYDB_END_ALLOW_THREADS
;
4562 return PyInt_FromLong(aborted
);
4567 DBEnv_lock_get(DBEnvObject
* self
, PyObject
* args
)
4570 int locker
, lock_mode
;
4574 if (!PyArg_ParseTuple(args
, "iOi|i:lock_get", &locker
, &objobj
, &lock_mode
, &flags
))
4578 if (!make_dbt(objobj
, &obj
))
4581 return (PyObject
*)newDBLockObject(self
, locker
, &obj
, lock_mode
, flags
);
4586 DBEnv_lock_id(DBEnvObject
* self
, PyObject
* args
)
4591 if (!PyArg_ParseTuple(args
, ":lock_id"))
4594 CHECK_ENV_NOT_CLOSED(self
);
4595 MYDB_BEGIN_ALLOW_THREADS
;
4597 err
= self
->db_env
->lock_id(self
->db_env
, &theID
);
4599 err
= lock_id(self
->db_env
, &theID
);
4601 MYDB_END_ALLOW_THREADS
;
4604 return PyInt_FromLong((long)theID
);
4609 DBEnv_lock_id_free(DBEnvObject
* self
, PyObject
* args
)
4614 if (!PyArg_ParseTuple(args
, "I:lock_id_free", &theID
))
4617 CHECK_ENV_NOT_CLOSED(self
);
4618 MYDB_BEGIN_ALLOW_THREADS
;
4619 err
= self
->db_env
->lock_id_free(self
->db_env
, theID
);
4620 MYDB_END_ALLOW_THREADS
;
4627 DBEnv_lock_put(DBEnvObject
* self
, PyObject
* args
)
4630 DBLockObject
* dblockobj
;
4632 if (!PyArg_ParseTuple(args
, "O!:lock_put", &DBLock_Type
, &dblockobj
))
4635 CHECK_ENV_NOT_CLOSED(self
);
4636 MYDB_BEGIN_ALLOW_THREADS
;
4638 err
= self
->db_env
->lock_put(self
->db_env
, &dblockobj
->lock
);
4640 err
= lock_put(self
->db_env
, &dblockobj
->lock
);
4642 MYDB_END_ALLOW_THREADS
;
4649 DBEnv_lsn_reset(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4653 u_int32_t flags
= 0;
4654 static char* kwnames
[] = { "file", "flags", NULL
};
4656 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "z|i:lsn_reset", kwnames
,
4659 CHECK_ENV_NOT_CLOSED(self
);
4661 MYDB_BEGIN_ALLOW_THREADS
;
4662 err
= self
->db_env
->lsn_reset(self
->db_env
, file
, flags
);
4663 MYDB_END_ALLOW_THREADS
;
4667 #endif /* DBVER >= 4.4 */
4671 DBEnv_log_stat(DBEnvObject
* self
, PyObject
* args
)
4674 DB_LOG_STAT
* statp
= NULL
;
4676 u_int32_t flags
= 0;
4678 if (!PyArg_ParseTuple(args
, "|i:log_stat", &flags
))
4680 CHECK_ENV_NOT_CLOSED(self
);
4682 MYDB_BEGIN_ALLOW_THREADS
;
4683 err
= self
->db_env
->log_stat(self
->db_env
, &statp
, flags
);
4684 MYDB_END_ALLOW_THREADS
;
4687 /* Turn the stat structure into a dictionary */
4695 #define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4698 MAKE_ENTRY(version
);
4700 MAKE_ENTRY(lg_bsize
);
4702 MAKE_ENTRY(lg_size
);
4708 MAKE_ENTRY(w_mbytes
);
4709 MAKE_ENTRY(w_bytes
);
4710 MAKE_ENTRY(wc_mbytes
);
4711 MAKE_ENTRY(wc_bytes
);
4713 MAKE_ENTRY(wcount_fill
);
4718 MAKE_ENTRY(cur_file
);
4719 MAKE_ENTRY(cur_offset
);
4720 MAKE_ENTRY(disk_file
);
4721 MAKE_ENTRY(disk_offset
);
4722 MAKE_ENTRY(maxcommitperflush
);
4723 MAKE_ENTRY(mincommitperflush
);
4724 MAKE_ENTRY(regsize
);
4725 MAKE_ENTRY(region_wait
);
4726 MAKE_ENTRY(region_nowait
);
4731 } /* DBEnv_log_stat */
4732 #endif /* DBVER >= 4.0 for log_stat method */
4736 DBEnv_lock_stat(DBEnvObject
* self
, PyObject
* args
)
4741 u_int32_t flags
= 0;
4743 if (!PyArg_ParseTuple(args
, "|i:lock_stat", &flags
))
4745 CHECK_ENV_NOT_CLOSED(self
);
4747 MYDB_BEGIN_ALLOW_THREADS
;
4749 err
= self
->db_env
->lock_stat(self
->db_env
, &sp
, flags
);
4752 err
= lock_stat(self
->db_env
, &sp
);
4754 err
= lock_stat(self
->db_env
, &sp
, NULL
);
4757 MYDB_END_ALLOW_THREADS
;
4760 /* Turn the stat structure into a dictionary */
4767 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4774 MAKE_ENTRY(cur_maxid
);
4777 MAKE_ENTRY(maxlocks
);
4778 MAKE_ENTRY(maxlockers
);
4779 MAKE_ENTRY(maxobjects
);
4781 MAKE_ENTRY(maxnlocks
);
4782 MAKE_ENTRY(nlockers
);
4783 MAKE_ENTRY(maxnlockers
);
4784 MAKE_ENTRY(nobjects
);
4785 MAKE_ENTRY(maxnobjects
);
4786 MAKE_ENTRY(nrequests
);
4787 MAKE_ENTRY(nreleases
);
4789 MAKE_ENTRY(nupgrade
);
4790 MAKE_ENTRY(ndowngrade
);
4793 MAKE_ENTRY(nnowaits
); /* these were renamed in 4.4 */
4794 MAKE_ENTRY(nconflicts
);
4796 MAKE_ENTRY(lock_nowait
);
4797 MAKE_ENTRY(lock_wait
);
4799 MAKE_ENTRY(ndeadlocks
);
4801 MAKE_ENTRY(locktimeout
);
4802 MAKE_ENTRY(txntimeout
);
4805 MAKE_ENTRY(nlocktimeouts
);
4806 MAKE_ENTRY(ntxntimeouts
);
4809 MAKE_ENTRY(objs_wait
);
4810 MAKE_ENTRY(objs_nowait
);
4811 MAKE_ENTRY(lockers_wait
);
4812 MAKE_ENTRY(lockers_nowait
);
4814 MAKE_ENTRY(lock_wait
);
4815 MAKE_ENTRY(lock_nowait
);
4817 MAKE_ENTRY(locks_wait
);
4818 MAKE_ENTRY(locks_nowait
);
4820 MAKE_ENTRY(hash_len
);
4822 MAKE_ENTRY(regsize
);
4823 MAKE_ENTRY(region_wait
);
4824 MAKE_ENTRY(region_nowait
);
4833 DBEnv_log_flush(DBEnvObject
* self
, PyObject
* args
)
4837 if (!PyArg_ParseTuple(args
, ":log_flush"))
4839 CHECK_ENV_NOT_CLOSED(self
);
4841 MYDB_BEGIN_ALLOW_THREADS
4842 err
= self
->db_env
->log_flush(self
->db_env
, NULL
);
4843 MYDB_END_ALLOW_THREADS
4851 DBEnv_log_archive(DBEnvObject
* self
, PyObject
* args
)
4855 char **log_list
= NULL
;
4857 PyObject
* item
= NULL
;
4859 if (!PyArg_ParseTuple(args
, "|i:log_archive", &flags
))
4862 CHECK_ENV_NOT_CLOSED(self
);
4863 MYDB_BEGIN_ALLOW_THREADS
;
4865 err
= self
->db_env
->log_archive(self
->db_env
, &log_list
, flags
);
4867 err
= log_archive(self
->db_env
, &log_list
, flags
);
4869 err
= log_archive(self
->db_env
, &log_list
, flags
, NULL
);
4871 MYDB_END_ALLOW_THREADS
;
4874 list
= PyList_New(0);
4882 char **log_list_start
;
4883 for (log_list_start
= log_list
; *log_list
!= NULL
; ++log_list
) {
4884 item
= PyBytes_FromString (*log_list
);
4890 PyList_Append(list
, item
);
4893 free(log_list_start
);
4900 DBEnv_txn_stat(DBEnvObject
* self
, PyObject
* args
)
4907 if (!PyArg_ParseTuple(args
, "|i:txn_stat", &flags
))
4909 CHECK_ENV_NOT_CLOSED(self
);
4911 MYDB_BEGIN_ALLOW_THREADS
;
4913 err
= self
->db_env
->txn_stat(self
->db_env
, &sp
, flags
);
4915 err
= txn_stat(self
->db_env
, &sp
);
4917 err
= txn_stat(self
->db_env
, &sp
, NULL
);
4919 MYDB_END_ALLOW_THREADS
;
4922 /* Turn the stat structure into a dictionary */
4929 #define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4930 #define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4931 #define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
4934 MAKE_DB_LSN_ENTRY(last_ckp
);
4936 MAKE_TIME_T_ENTRY(time_ckp
);
4937 MAKE_ENTRY(last_txnid
);
4938 MAKE_ENTRY(maxtxns
);
4939 MAKE_ENTRY(nactive
);
4940 MAKE_ENTRY(maxnactive
);
4942 MAKE_ENTRY(nsnapshot
);
4943 MAKE_ENTRY(maxnsnapshot
);
4945 MAKE_ENTRY(nbegins
);
4946 MAKE_ENTRY(naborts
);
4947 MAKE_ENTRY(ncommits
);
4949 MAKE_ENTRY(nrestores
);
4951 MAKE_ENTRY(regsize
);
4952 MAKE_ENTRY(region_wait
);
4953 MAKE_ENTRY(region_nowait
);
4955 #undef MAKE_DB_LSN_ENTRY
4957 #undef MAKE_TIME_T_ENTRY
4964 DBEnv_set_get_returns_none(DBEnvObject
* self
, PyObject
* args
)
4969 if (!PyArg_ParseTuple(args
,"i:set_get_returns_none", &flags
))
4971 CHECK_ENV_NOT_CLOSED(self
);
4973 if (self
->moduleFlags
.getReturnsNone
)
4975 if (self
->moduleFlags
.cursorSetReturnsNone
)
4977 self
->moduleFlags
.getReturnsNone
= (flags
>= 1);
4978 self
->moduleFlags
.cursorSetReturnsNone
= (flags
>= 2);
4979 return PyInt_FromLong(oldValue
);
4984 DBEnv_set_rpc_server(DBEnvObject
* self
, PyObject
* args
, PyObject
* kwargs
)
4988 long cl_timeout
=0, sv_timeout
=0;
4990 static char* kwnames
[] = { "host", "cl_timeout", "sv_timeout", NULL
};
4992 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "s|ll:set_rpc_server", kwnames
,
4993 &host
, &cl_timeout
, &sv_timeout
))
4995 CHECK_ENV_NOT_CLOSED(self
);
4997 MYDB_BEGIN_ALLOW_THREADS
;
4998 err
= self
->db_env
->set_rpc_server(self
->db_env
, NULL
, host
, cl_timeout
,
5000 MYDB_END_ALLOW_THREADS
;
5008 DBEnv_set_verbose(DBEnvObject
* self
, PyObject
* args
)
5013 if (!PyArg_ParseTuple(args
, "ii:set_verbose", &which
, &onoff
)) {
5016 CHECK_ENV_NOT_CLOSED(self
);
5017 MYDB_BEGIN_ALLOW_THREADS
;
5018 err
= self
->db_env
->set_verbose(self
->db_env
, which
, onoff
);
5019 MYDB_END_ALLOW_THREADS
;
5026 DBEnv_get_verbose(DBEnvObject
* self
, PyObject
* args
)
5032 if (!PyArg_ParseTuple(args
, "i:get_verbose", &which
)) {
5035 CHECK_ENV_NOT_CLOSED(self
);
5036 MYDB_BEGIN_ALLOW_THREADS
;
5037 err
= self
->db_env
->get_verbose(self
->db_env
, which
, &verbose
);
5038 MYDB_END_ALLOW_THREADS
;
5040 return PyBool_FromLong(verbose
);
5047 _dbenv_event_notifyCallback(DB_ENV
* db_env
, u_int32_t event
, void *event_info
)
5052 PyObject
* result
= NULL
;
5054 MYDB_BEGIN_BLOCK_THREADS
;
5055 dbenv
= (DBEnvObject
*)db_env
->app_private
;
5056 callback
= dbenv
->event_notifyCallback
;
5058 if (event
== DB_EVENT_REP_NEWMASTER
) {
5059 args
= Py_BuildValue("(Oii)", dbenv
, event
, *((int *)event_info
));
5061 args
= Py_BuildValue("(OiO)", dbenv
, event
, Py_None
);
5064 result
= PyEval_CallObject(callback
, args
);
5066 if ((!args
) || (!result
)) {
5072 MYDB_END_BLOCK_THREADS
;
5078 DBEnv_set_event_notify(DBEnvObject
* self
, PyObject
* args
)
5081 PyObject
*notifyFunc
;
5083 if (!PyArg_ParseTuple(args
, "O:set_event_notify", ¬ifyFunc
)) {
5087 CHECK_ENV_NOT_CLOSED(self
);
5089 if (!PyCallable_Check(notifyFunc
)) {
5090 makeTypeError("Callable", notifyFunc
);
5094 Py_XDECREF(self
->event_notifyCallback
);
5095 Py_INCREF(notifyFunc
);
5096 self
->event_notifyCallback
= notifyFunc
;
5098 MYDB_BEGIN_ALLOW_THREADS
;
5099 err
= self
->db_env
->set_event_notify(self
->db_env
, _dbenv_event_notifyCallback
);
5100 MYDB_END_ALLOW_THREADS
;
5103 Py_DECREF(notifyFunc
);
5104 self
->event_notifyCallback
= NULL
;
5113 /* --------------------------------------------------------------------- */
5114 /* REPLICATION METHODS: Base Replication */
5118 DBEnv_rep_set_nsites(DBEnvObject
* self
, PyObject
* args
)
5123 if (!PyArg_ParseTuple(args
, "i:rep_set_nsites", &nsites
)) {
5126 CHECK_ENV_NOT_CLOSED(self
);
5127 MYDB_BEGIN_ALLOW_THREADS
;
5128 err
= self
->db_env
->rep_set_nsites(self
->db_env
, nsites
);
5129 MYDB_END_ALLOW_THREADS
;
5135 DBEnv_rep_get_nsites(DBEnvObject
* self
, PyObject
* args
)
5144 if (!PyArg_ParseTuple(args
, ":rep_get_nsites")) {
5147 CHECK_ENV_NOT_CLOSED(self
);
5148 MYDB_BEGIN_ALLOW_THREADS
;
5149 err
= self
->db_env
->rep_get_nsites(self
->db_env
, &nsites
);
5150 MYDB_END_ALLOW_THREADS
;
5152 return PyInt_FromLong(nsites
);
5156 DBEnv_rep_set_priority(DBEnvObject
* self
, PyObject
* args
)
5161 if (!PyArg_ParseTuple(args
, "i:rep_set_priority", &priority
)) {
5164 CHECK_ENV_NOT_CLOSED(self
);
5165 MYDB_BEGIN_ALLOW_THREADS
;
5166 err
= self
->db_env
->rep_set_priority(self
->db_env
, priority
);
5167 MYDB_END_ALLOW_THREADS
;
5173 DBEnv_rep_get_priority(DBEnvObject
* self
, PyObject
* args
)
5182 if (!PyArg_ParseTuple(args
, ":rep_get_priority")) {
5185 CHECK_ENV_NOT_CLOSED(self
);
5186 MYDB_BEGIN_ALLOW_THREADS
;
5187 err
= self
->db_env
->rep_get_priority(self
->db_env
, &priority
);
5188 MYDB_END_ALLOW_THREADS
;
5190 return PyInt_FromLong(priority
);
5194 DBEnv_rep_set_timeout(DBEnvObject
* self
, PyObject
* args
)
5199 if (!PyArg_ParseTuple(args
, "ii:rep_set_timeout", &which
, &timeout
)) {
5202 CHECK_ENV_NOT_CLOSED(self
);
5203 MYDB_BEGIN_ALLOW_THREADS
;
5204 err
= self
->db_env
->rep_set_timeout(self
->db_env
, which
, timeout
);
5205 MYDB_END_ALLOW_THREADS
;
5211 DBEnv_rep_get_timeout(DBEnvObject
* self
, PyObject
* args
)
5217 if (!PyArg_ParseTuple(args
, "i:rep_get_timeout", &which
)) {
5220 CHECK_ENV_NOT_CLOSED(self
);
5221 MYDB_BEGIN_ALLOW_THREADS
;
5222 err
= self
->db_env
->rep_get_timeout(self
->db_env
, which
, &timeout
);
5223 MYDB_END_ALLOW_THREADS
;
5225 return PyInt_FromLong(timeout
);
5229 /* --------------------------------------------------------------------- */
5230 /* REPLICATION METHODS: Replication Manager */
5234 DBEnv_repmgr_start(DBEnvObject
* self
, PyObject
* args
, PyObject
*
5238 int nthreads
, flags
;
5239 static char* kwnames
[] = {"nthreads","flags", NULL
};
5241 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,
5242 "ii:repmgr_start", kwnames
, &nthreads
, &flags
))
5246 CHECK_ENV_NOT_CLOSED(self
);
5247 MYDB_BEGIN_ALLOW_THREADS
;
5248 err
= self
->db_env
->repmgr_start(self
->db_env
, nthreads
, flags
);
5249 MYDB_END_ALLOW_THREADS
;
5255 DBEnv_repmgr_set_local_site(DBEnvObject
* self
, PyObject
* args
, PyObject
*
5262 static char* kwnames
[] = {"host", "port", "flags", NULL
};
5264 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,
5265 "si|i:repmgr_set_local_site", kwnames
, &host
, &port
, &flags
))
5269 CHECK_ENV_NOT_CLOSED(self
);
5270 MYDB_BEGIN_ALLOW_THREADS
;
5271 err
= self
->db_env
->repmgr_set_local_site(self
->db_env
, host
, port
, flags
);
5272 MYDB_END_ALLOW_THREADS
;
5278 DBEnv_repmgr_add_remote_site(DBEnvObject
* self
, PyObject
* args
, PyObject
*
5286 static char* kwnames
[] = {"host", "port", "flags", NULL
};
5288 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
,
5289 "si|i:repmgr_add_remote_site", kwnames
, &host
, &port
, &flags
))
5293 CHECK_ENV_NOT_CLOSED(self
);
5294 MYDB_BEGIN_ALLOW_THREADS
;
5295 err
= self
->db_env
->repmgr_add_remote_site(self
->db_env
, host
, port
, &eidp
, flags
);
5296 MYDB_END_ALLOW_THREADS
;
5298 return PyInt_FromLong(eidp
);
5302 DBEnv_repmgr_set_ack_policy(DBEnvObject
* self
, PyObject
* args
)
5307 if (!PyArg_ParseTuple(args
, "i:repmgr_set_ack_policy", &ack_policy
))
5311 CHECK_ENV_NOT_CLOSED(self
);
5312 MYDB_BEGIN_ALLOW_THREADS
;
5313 err
= self
->db_env
->repmgr_set_ack_policy(self
->db_env
, ack_policy
);
5314 MYDB_END_ALLOW_THREADS
;
5320 DBEnv_repmgr_get_ack_policy(DBEnvObject
* self
, PyObject
* args
)
5325 if (!PyArg_ParseTuple(args
, ":repmgr_get_ack_policy"))
5329 CHECK_ENV_NOT_CLOSED(self
);
5330 MYDB_BEGIN_ALLOW_THREADS
;
5331 err
= self
->db_env
->repmgr_get_ack_policy(self
->db_env
, &ack_policy
);
5332 MYDB_END_ALLOW_THREADS
;
5334 return PyInt_FromLong(ack_policy
);
5338 DBEnv_repmgr_site_list(DBEnvObject
* self
, PyObject
* args
)
5341 unsigned int countp
;
5342 DB_REPMGR_SITE
*listp
;
5343 PyObject
*stats
, *key
, *tuple
;
5345 if (!PyArg_ParseTuple(args
, ":repmgr_site_list"))
5349 CHECK_ENV_NOT_CLOSED(self
);
5350 MYDB_BEGIN_ALLOW_THREADS
;
5351 err
= self
->db_env
->repmgr_site_list(self
->db_env
, &countp
, &listp
);
5352 MYDB_END_ALLOW_THREADS
;
5356 if (stats
== NULL
) {
5362 key
=PyInt_FromLong(listp
[countp
].eid
);
5368 #if (PY_VERSION_HEX >= 0x02040000)
5369 tuple
=Py_BuildValue("(sII)", listp
[countp
].host
,
5370 listp
[countp
].port
, listp
[countp
].status
);
5372 tuple
=Py_BuildValue("(sii)", listp
[countp
].host
,
5373 listp
[countp
].port
, listp
[countp
].status
);
5381 if(PyDict_SetItem(stats
, key
, tuple
)) {
5396 DBEnv_repmgr_stat_print(DBEnvObject
* self
, PyObject
* args
, PyObject
*kwargs
)
5400 static char* kwnames
[] = { "flags", NULL
};
5402 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:repmgr_stat_print",
5407 CHECK_ENV_NOT_CLOSED(self
);
5408 MYDB_BEGIN_ALLOW_THREADS
;
5409 err
= self
->db_env
->repmgr_stat_print(self
->db_env
, flags
);
5410 MYDB_END_ALLOW_THREADS
;
5416 DBEnv_repmgr_stat(DBEnvObject
* self
, PyObject
* args
, PyObject
*kwargs
)
5420 DB_REPMGR_STAT
*statp
;
5422 static char* kwnames
[] = { "flags", NULL
};
5424 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:repmgr_stat",
5429 CHECK_ENV_NOT_CLOSED(self
);
5430 MYDB_BEGIN_ALLOW_THREADS
;
5431 err
= self
->db_env
->repmgr_stat(self
->db_env
, &statp
, flags
);
5432 MYDB_END_ALLOW_THREADS
;
5436 if (stats
== NULL
) {
5441 #define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5443 MAKE_ENTRY(perm_failed
);
5444 MAKE_ENTRY(msgs_queued
);
5445 MAKE_ENTRY(msgs_dropped
);
5446 MAKE_ENTRY(connection_drop
);
5447 MAKE_ENTRY(connect_fail
);
5457 /* --------------------------------------------------------------------- */
5461 static void _close_transaction_cursors(DBTxnObject
* txn
)
5465 while(txn
->children_cursors
) {
5466 PyErr_Warn(PyExc_RuntimeWarning
,
5467 "Must close cursors before resolving a transaction.");
5468 dummy
=DBC_close_internal(txn
->children_cursors
);
5473 static void _promote_transaction_dbs_and_sequences(DBTxnObject
*txn
)
5477 DBSequenceObject
*dbs
;
5480 while (txn
->children_dbs
) {
5481 db
=txn
->children_dbs
;
5482 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db
);
5483 if (txn
->parent_txn
) {
5484 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn
->parent_txn
->children_dbs
,db
);
5485 db
->txn
=txn
->parent_txn
;
5487 /* The db is already linked to its environment,
5488 ** so nothing to do.
5495 while (txn
->children_sequences
) {
5496 dbs
=txn
->children_sequences
;
5497 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs
);
5498 if (txn
->parent_txn
) {
5499 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn
->parent_txn
->children_sequences
,dbs
);
5500 dbs
->txn
=txn
->parent_txn
;
5502 /* The sequence is already linked to its
5503 ** parent db. Nothing to do.
5513 DBTxn_commit(DBTxnObject
* self
, PyObject
* args
)
5518 if (!PyArg_ParseTuple(args
, "|i:commit", &flags
))
5521 _close_transaction_cursors(self
);
5524 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
5525 "after txn_commit, txn_abort "
5527 PyErr_SetObject(DBError
, t
);
5531 self
->flag_prepare
=0;
5533 self
->txn
= NULL
; /* this DB_TXN is no longer valid after this call */
5535 EXTRACT_FROM_DOUBLE_LINKED_LIST(self
);
5537 MYDB_BEGIN_ALLOW_THREADS
;
5539 err
= txn
->commit(txn
, flags
);
5541 err
= txn_commit(txn
, flags
);
5543 MYDB_END_ALLOW_THREADS
;
5545 _promote_transaction_dbs_and_sequences(self
);
5552 DBTxn_prepare(DBTxnObject
* self
, PyObject
* args
)
5559 if (!PyArg_ParseTuple(args
, "s#:prepare", &gid
, &gid_size
))
5562 if (gid_size
!= DB_XIDDATASIZE
) {
5563 PyErr_SetString(PyExc_TypeError
,
5564 "gid must be DB_XIDDATASIZE bytes long");
5569 PyObject
*t
= Py_BuildValue("(is)", 0,"DBTxn must not be used "
5570 "after txn_commit, txn_abort "
5572 PyErr_SetObject(DBError
, t
);
5576 self
->flag_prepare
=1; /* Prepare state */
5577 MYDB_BEGIN_ALLOW_THREADS
;
5579 err
= self
->txn
->prepare(self
->txn
, (u_int8_t
*)gid
);
5581 err
= txn_prepare(self
->txn
, (u_int8_t
*)gid
);
5583 MYDB_END_ALLOW_THREADS
;
5589 if (!PyArg_ParseTuple(args
, ":prepare"))
5593 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
5594 "after txn_commit, txn_abort "
5596 PyErr_SetObject(DBError
, t
);
5600 MYDB_BEGIN_ALLOW_THREADS
;
5601 err
= txn_prepare(self
->txn
);
5602 MYDB_END_ALLOW_THREADS
;
5610 DBTxn_abort_discard_internal(DBTxnObject
* self
, int discard
)
5617 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
5618 "after txn_commit, txn_abort "
5620 PyErr_SetObject(DBError
, t
);
5625 self
->txn
= NULL
; /* this DB_TXN is no longer valid after this call */
5627 _close_transaction_cursors(self
);
5629 while (self
->children_sequences
) {
5630 dummy
=DBSequence_close_internal(self
->children_sequences
,0,0);
5634 while (self
->children_dbs
) {
5635 dummy
=DB_close_internal(self
->children_dbs
,0);
5639 EXTRACT_FROM_DOUBLE_LINKED_LIST(self
);
5641 MYDB_BEGIN_ALLOW_THREADS
;
5643 assert(!self
->flag_prepare
);
5645 err
= txn
->discard(txn
,0);
5647 err
= txn_discard(txn
);
5651 ** If the transaction is in the "prepare" or "recover" state,
5652 ** we better do not implicitly abort it.
5654 if (!self
->flag_prepare
) {
5656 err
= txn
->abort(txn
);
5658 err
= txn_abort(txn
);
5662 MYDB_END_ALLOW_THREADS
;
5668 DBTxn_abort(DBTxnObject
* self
, PyObject
* args
)
5670 if (!PyArg_ParseTuple(args
, ":abort"))
5673 self
->flag_prepare
=0;
5674 _close_transaction_cursors(self
);
5676 return DBTxn_abort_discard_internal(self
,0);
5680 DBTxn_discard(DBTxnObject
* self
, PyObject
* args
)
5682 if (!PyArg_ParseTuple(args
, ":discard"))
5685 self
->flag_prepare
=0;
5686 _close_transaction_cursors(self
);
5688 return DBTxn_abort_discard_internal(self
,1);
5693 DBTxn_id(DBTxnObject
* self
, PyObject
* args
)
5697 if (!PyArg_ParseTuple(args
, ":id"))
5701 PyObject
*t
= Py_BuildValue("(is)", 0, "DBTxn must not be used "
5702 "after txn_commit, txn_abort "
5704 PyErr_SetObject(DBError
, t
);
5708 MYDB_BEGIN_ALLOW_THREADS
;
5710 id
= self
->txn
->id(self
->txn
);
5712 id
= txn_id(self
->txn
);
5714 MYDB_END_ALLOW_THREADS
;
5715 return PyInt_FromLong(id
);
5719 /* --------------------------------------------------------------------- */
5720 /* DBSequence methods */
5724 DBSequence_close_internal(DBSequenceObject
* self
, int flags
, int do_not_close
)
5728 if (self
->sequence
!=NULL
) {
5729 EXTRACT_FROM_DOUBLE_LINKED_LIST(self
);
5731 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self
);
5735 if (!do_not_close
) {
5736 MYDB_BEGIN_ALLOW_THREADS
5737 err
= self
->sequence
->close(self
->sequence
, flags
);
5738 MYDB_END_ALLOW_THREADS
5740 self
->sequence
= NULL
;
5749 DBSequence_close(DBSequenceObject
* self
, PyObject
* args
)
5752 if (!PyArg_ParseTuple(args
,"|i:close", &flags
))
5755 return DBSequence_close_internal(self
,flags
,0);
5759 DBSequence_get(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
5764 PyObject
*txnobj
= NULL
;
5766 static char* kwnames
[] = {"delta", "txn", "flags", NULL
};
5767 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|iOi:get", kwnames
, &delta
, &txnobj
, &flags
))
5769 CHECK_SEQUENCE_NOT_CLOSED(self
)
5771 if (!checkTxnObj(txnobj
, &txn
))
5774 MYDB_BEGIN_ALLOW_THREADS
5775 err
= self
->sequence
->get(self
->sequence
, txn
, delta
, &value
, flags
);
5776 MYDB_END_ALLOW_THREADS
5779 return PyLong_FromLongLong(value
);
5783 DBSequence_get_dbp(DBSequenceObject
* self
, PyObject
* args
)
5785 if (!PyArg_ParseTuple(args
,":get_dbp"))
5787 CHECK_SEQUENCE_NOT_CLOSED(self
)
5788 Py_INCREF(self
->mydb
);
5789 return (PyObject
* )self
->mydb
;
5793 DBSequence_get_key(DBSequenceObject
* self
, PyObject
* args
)
5797 PyObject
*retval
= NULL
;
5799 if (!PyArg_ParseTuple(args
,":get_key"))
5802 key
.flags
= DB_DBT_MALLOC
;
5803 CHECK_SEQUENCE_NOT_CLOSED(self
)
5804 MYDB_BEGIN_ALLOW_THREADS
5805 err
= self
->sequence
->get_key(self
->sequence
, &key
);
5806 MYDB_END_ALLOW_THREADS
5809 retval
= Build_PyString(key
.data
, key
.size
);
5818 DBSequence_init_value(DBSequenceObject
* self
, PyObject
* args
)
5823 if (!PyArg_ParseTuple(args
,"L:init_value", &value
))
5825 CHECK_SEQUENCE_NOT_CLOSED(self
)
5827 value2
=value
; /* If truncation, compiler should show a warning */
5828 MYDB_BEGIN_ALLOW_THREADS
5829 err
= self
->sequence
->initial_value(self
->sequence
, value2
);
5830 MYDB_END_ALLOW_THREADS
5838 DBSequence_open(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
5842 PyObject
*txnobj
= NULL
;
5846 static char* kwnames
[] = {"key", "txn", "flags", NULL
};
5847 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|Oi:open", kwnames
, &keyobj
, &txnobj
, &flags
))
5850 if (!checkTxnObj(txnobj
, &txn
))
5853 if (!make_key_dbt(self
->mydb
, keyobj
, &key
, NULL
))
5856 MYDB_BEGIN_ALLOW_THREADS
5857 err
= self
->sequence
->open(self
->sequence
, txn
, &key
, flags
);
5858 MYDB_END_ALLOW_THREADS
5864 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject
*)txnobj
)->children_sequences
,self
);
5865 self
->txn
=(DBTxnObject
*)txnobj
;
5872 DBSequence_remove(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
5876 PyObject
*txnobj
= NULL
;
5879 static char* kwnames
[] = {"txn", "flags", NULL
};
5880 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:remove", kwnames
, &txnobj
, &flags
))
5883 if (!checkTxnObj(txnobj
, &txn
))
5886 CHECK_SEQUENCE_NOT_CLOSED(self
)
5888 MYDB_BEGIN_ALLOW_THREADS
5889 err
= self
->sequence
->remove(self
->sequence
, txn
, flags
);
5890 MYDB_END_ALLOW_THREADS
5892 dummy
=DBSequence_close_internal(self
,flags
,1);
5900 DBSequence_set_cachesize(DBSequenceObject
* self
, PyObject
* args
)
5903 if (!PyArg_ParseTuple(args
,"i:set_cachesize", &size
))
5905 CHECK_SEQUENCE_NOT_CLOSED(self
)
5907 MYDB_BEGIN_ALLOW_THREADS
5908 err
= self
->sequence
->set_cachesize(self
->sequence
, size
);
5909 MYDB_END_ALLOW_THREADS
5916 DBSequence_get_cachesize(DBSequenceObject
* self
, PyObject
* args
)
5919 if (!PyArg_ParseTuple(args
,":get_cachesize"))
5921 CHECK_SEQUENCE_NOT_CLOSED(self
)
5923 MYDB_BEGIN_ALLOW_THREADS
5924 err
= self
->sequence
->get_cachesize(self
->sequence
, &size
);
5925 MYDB_END_ALLOW_THREADS
5928 return PyInt_FromLong(size
);
5932 DBSequence_set_flags(DBSequenceObject
* self
, PyObject
* args
)
5935 if (!PyArg_ParseTuple(args
,"i:set_flags", &flags
))
5937 CHECK_SEQUENCE_NOT_CLOSED(self
)
5939 MYDB_BEGIN_ALLOW_THREADS
5940 err
= self
->sequence
->set_flags(self
->sequence
, flags
);
5941 MYDB_END_ALLOW_THREADS
5948 DBSequence_get_flags(DBSequenceObject
* self
, PyObject
* args
)
5952 if (!PyArg_ParseTuple(args
,":get_flags"))
5954 CHECK_SEQUENCE_NOT_CLOSED(self
)
5956 MYDB_BEGIN_ALLOW_THREADS
5957 err
= self
->sequence
->get_flags(self
->sequence
, &flags
);
5958 MYDB_END_ALLOW_THREADS
5961 return PyInt_FromLong((int)flags
);
5965 DBSequence_set_range(DBSequenceObject
* self
, PyObject
* args
)
5968 PY_LONG_LONG min
, max
;
5969 db_seq_t min2
, max2
;
5970 if (!PyArg_ParseTuple(args
,"(LL):set_range", &min
, &max
))
5972 CHECK_SEQUENCE_NOT_CLOSED(self
)
5974 min2
=min
; /* If truncation, compiler should show a warning */
5976 MYDB_BEGIN_ALLOW_THREADS
5977 err
= self
->sequence
->set_range(self
->sequence
, min2
, max2
);
5978 MYDB_END_ALLOW_THREADS
5985 DBSequence_get_range(DBSequenceObject
* self
, PyObject
* args
)
5988 PY_LONG_LONG min
, max
;
5989 db_seq_t min2
, max2
;
5990 if (!PyArg_ParseTuple(args
,":get_range"))
5992 CHECK_SEQUENCE_NOT_CLOSED(self
)
5994 MYDB_BEGIN_ALLOW_THREADS
5995 err
= self
->sequence
->get_range(self
->sequence
, &min2
, &max2
);
5996 MYDB_END_ALLOW_THREADS
5999 min
=min2
; /* If truncation, compiler should show a warning */
6001 return Py_BuildValue("(LL)", min
, max
);
6005 DBSequence_stat(DBSequenceObject
* self
, PyObject
* args
, PyObject
* kwargs
)
6008 DB_SEQUENCE_STAT
* sp
= NULL
;
6009 PyObject
* dict_stat
;
6010 static char* kwnames
[] = {"flags", NULL
};
6011 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|i:stat", kwnames
, &flags
))
6013 CHECK_SEQUENCE_NOT_CLOSED(self
);
6015 MYDB_BEGIN_ALLOW_THREADS
;
6016 err
= self
->sequence
->stat(self
->sequence
, &sp
, flags
);
6017 MYDB_END_ALLOW_THREADS
;
6020 if ((dict_stat
= PyDict_New()) == NULL
) {
6026 #define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6027 #define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6029 MAKE_INT_ENTRY(wait
);
6030 MAKE_INT_ENTRY(nowait
);
6031 MAKE_LONG_LONG_ENTRY(current
);
6032 MAKE_LONG_LONG_ENTRY(value
);
6033 MAKE_LONG_LONG_ENTRY(last_value
);
6034 MAKE_LONG_LONG_ENTRY(min
);
6035 MAKE_LONG_LONG_ENTRY(max
);
6036 MAKE_INT_ENTRY(cache_size
);
6037 MAKE_INT_ENTRY(flags
);
6039 #undef MAKE_INT_ENTRY
6040 #undef MAKE_LONG_LONG_ENTRY
6048 /* --------------------------------------------------------------------- */
6049 /* Method definition tables and type objects */
6051 static PyMethodDef DB_methods
[] = {
6052 {"append", (PyCFunction
)DB_append
, METH_VARARGS
},
6054 {"associate", (PyCFunction
)DB_associate
, METH_VARARGS
|METH_KEYWORDS
},
6056 {"close", (PyCFunction
)DB_close
, METH_VARARGS
},
6057 {"consume", (PyCFunction
)DB_consume
, METH_VARARGS
|METH_KEYWORDS
},
6058 {"consume_wait", (PyCFunction
)DB_consume_wait
, METH_VARARGS
|METH_KEYWORDS
},
6059 {"cursor", (PyCFunction
)DB_cursor
, METH_VARARGS
|METH_KEYWORDS
},
6060 {"delete", (PyCFunction
)DB_delete
, METH_VARARGS
|METH_KEYWORDS
},
6061 {"fd", (PyCFunction
)DB_fd
, METH_VARARGS
},
6062 {"get", (PyCFunction
)DB_get
, METH_VARARGS
|METH_KEYWORDS
},
6064 {"pget", (PyCFunction
)DB_pget
, METH_VARARGS
|METH_KEYWORDS
},
6066 {"get_both", (PyCFunction
)DB_get_both
, METH_VARARGS
|METH_KEYWORDS
},
6067 {"get_byteswapped", (PyCFunction
)DB_get_byteswapped
,METH_VARARGS
},
6068 {"get_size", (PyCFunction
)DB_get_size
, METH_VARARGS
|METH_KEYWORDS
},
6069 {"get_type", (PyCFunction
)DB_get_type
, METH_VARARGS
},
6070 {"join", (PyCFunction
)DB_join
, METH_VARARGS
},
6071 {"key_range", (PyCFunction
)DB_key_range
, METH_VARARGS
|METH_KEYWORDS
},
6072 {"has_key", (PyCFunction
)DB_has_key
, METH_VARARGS
},
6073 {"items", (PyCFunction
)DB_items
, METH_VARARGS
},
6074 {"keys", (PyCFunction
)DB_keys
, METH_VARARGS
},
6075 {"open", (PyCFunction
)DB_open
, METH_VARARGS
|METH_KEYWORDS
},
6076 {"put", (PyCFunction
)DB_put
, METH_VARARGS
|METH_KEYWORDS
},
6077 {"remove", (PyCFunction
)DB_remove
, METH_VARARGS
|METH_KEYWORDS
},
6078 {"rename", (PyCFunction
)DB_rename
, METH_VARARGS
},
6079 {"set_bt_minkey", (PyCFunction
)DB_set_bt_minkey
, METH_VARARGS
},
6081 {"set_bt_compare", (PyCFunction
)DB_set_bt_compare
, METH_VARARGS
},
6083 {"set_cachesize", (PyCFunction
)DB_set_cachesize
, METH_VARARGS
},
6085 {"set_encrypt", (PyCFunction
)DB_set_encrypt
, METH_VARARGS
|METH_KEYWORDS
},
6087 {"set_flags", (PyCFunction
)DB_set_flags
, METH_VARARGS
},
6088 {"set_h_ffactor", (PyCFunction
)DB_set_h_ffactor
, METH_VARARGS
},
6089 {"set_h_nelem", (PyCFunction
)DB_set_h_nelem
, METH_VARARGS
},
6090 {"set_lorder", (PyCFunction
)DB_set_lorder
, METH_VARARGS
},
6091 {"set_pagesize", (PyCFunction
)DB_set_pagesize
, METH_VARARGS
},
6092 {"set_re_delim", (PyCFunction
)DB_set_re_delim
, METH_VARARGS
},
6093 {"set_re_len", (PyCFunction
)DB_set_re_len
, METH_VARARGS
},
6094 {"set_re_pad", (PyCFunction
)DB_set_re_pad
, METH_VARARGS
},
6095 {"set_re_source", (PyCFunction
)DB_set_re_source
, METH_VARARGS
},
6096 {"set_q_extentsize",(PyCFunction
)DB_set_q_extentsize
,METH_VARARGS
},
6097 {"stat", (PyCFunction
)DB_stat
, METH_VARARGS
|METH_KEYWORDS
},
6098 {"sync", (PyCFunction
)DB_sync
, METH_VARARGS
},
6100 {"truncate", (PyCFunction
)DB_truncate
, METH_VARARGS
|METH_KEYWORDS
},
6102 {"type", (PyCFunction
)DB_get_type
, METH_VARARGS
},
6103 {"upgrade", (PyCFunction
)DB_upgrade
, METH_VARARGS
},
6104 {"values", (PyCFunction
)DB_values
, METH_VARARGS
},
6105 {"verify", (PyCFunction
)DB_verify
, METH_VARARGS
|METH_KEYWORDS
},
6106 {"set_get_returns_none",(PyCFunction
)DB_set_get_returns_none
, METH_VARARGS
},
6107 {NULL
, NULL
} /* sentinel */
6111 static PyMappingMethods DB_mapping
= {
6112 DB_length
, /*mp_length*/
6113 (binaryfunc
)DB_subscript
, /*mp_subscript*/
6114 (objobjargproc
)DB_ass_sub
, /*mp_ass_subscript*/
6118 static PyMethodDef DBCursor_methods
[] = {
6119 {"close", (PyCFunction
)DBC_close
, METH_VARARGS
},
6120 {"count", (PyCFunction
)DBC_count
, METH_VARARGS
},
6121 {"current", (PyCFunction
)DBC_current
, METH_VARARGS
|METH_KEYWORDS
},
6122 {"delete", (PyCFunction
)DBC_delete
, METH_VARARGS
},
6123 {"dup", (PyCFunction
)DBC_dup
, METH_VARARGS
},
6124 {"first", (PyCFunction
)DBC_first
, METH_VARARGS
|METH_KEYWORDS
},
6125 {"get", (PyCFunction
)DBC_get
, METH_VARARGS
|METH_KEYWORDS
},
6127 {"pget", (PyCFunction
)DBC_pget
, METH_VARARGS
|METH_KEYWORDS
},
6129 {"get_recno", (PyCFunction
)DBC_get_recno
, METH_VARARGS
},
6130 {"last", (PyCFunction
)DBC_last
, METH_VARARGS
|METH_KEYWORDS
},
6131 {"next", (PyCFunction
)DBC_next
, METH_VARARGS
|METH_KEYWORDS
},
6132 {"prev", (PyCFunction
)DBC_prev
, METH_VARARGS
|METH_KEYWORDS
},
6133 {"put", (PyCFunction
)DBC_put
, METH_VARARGS
|METH_KEYWORDS
},
6134 {"set", (PyCFunction
)DBC_set
, METH_VARARGS
|METH_KEYWORDS
},
6135 {"set_range", (PyCFunction
)DBC_set_range
, METH_VARARGS
|METH_KEYWORDS
},
6136 {"get_both", (PyCFunction
)DBC_get_both
, METH_VARARGS
},
6137 {"get_current_size",(PyCFunction
)DBC_get_current_size
, METH_VARARGS
},
6138 {"set_both", (PyCFunction
)DBC_set_both
, METH_VARARGS
},
6139 {"set_recno", (PyCFunction
)DBC_set_recno
, METH_VARARGS
|METH_KEYWORDS
},
6140 {"consume", (PyCFunction
)DBC_consume
, METH_VARARGS
|METH_KEYWORDS
},
6141 {"next_dup", (PyCFunction
)DBC_next_dup
, METH_VARARGS
|METH_KEYWORDS
},
6142 {"next_nodup", (PyCFunction
)DBC_next_nodup
, METH_VARARGS
|METH_KEYWORDS
},
6143 {"prev_nodup", (PyCFunction
)DBC_prev_nodup
, METH_VARARGS
|METH_KEYWORDS
},
6144 {"join_item", (PyCFunction
)DBC_join_item
, METH_VARARGS
},
6145 {NULL
, NULL
} /* sentinel */
6149 static PyMethodDef DBEnv_methods
[] = {
6150 {"close", (PyCFunction
)DBEnv_close
, METH_VARARGS
},
6151 {"open", (PyCFunction
)DBEnv_open
, METH_VARARGS
},
6152 {"remove", (PyCFunction
)DBEnv_remove
, METH_VARARGS
},
6154 {"dbremove", (PyCFunction
)DBEnv_dbremove
, METH_VARARGS
|METH_KEYWORDS
},
6155 {"dbrename", (PyCFunction
)DBEnv_dbrename
, METH_VARARGS
|METH_KEYWORDS
},
6156 {"set_encrypt", (PyCFunction
)DBEnv_set_encrypt
, METH_VARARGS
|METH_KEYWORDS
},
6159 {"set_timeout", (PyCFunction
)DBEnv_set_timeout
, METH_VARARGS
|METH_KEYWORDS
},
6161 {"set_shm_key", (PyCFunction
)DBEnv_set_shm_key
, METH_VARARGS
},
6162 {"set_cachesize", (PyCFunction
)DBEnv_set_cachesize
, METH_VARARGS
},
6163 {"set_data_dir", (PyCFunction
)DBEnv_set_data_dir
, METH_VARARGS
},
6164 {"set_flags", (PyCFunction
)DBEnv_set_flags
, METH_VARARGS
},
6166 {"log_set_config", (PyCFunction
)DBEnv_log_set_config
, METH_VARARGS
},
6168 {"set_lg_bsize", (PyCFunction
)DBEnv_set_lg_bsize
, METH_VARARGS
},
6169 {"set_lg_dir", (PyCFunction
)DBEnv_set_lg_dir
, METH_VARARGS
},
6170 {"set_lg_max", (PyCFunction
)DBEnv_set_lg_max
, METH_VARARGS
},
6172 {"get_lg_max", (PyCFunction
)DBEnv_get_lg_max
, METH_VARARGS
},
6175 {"set_lg_regionmax",(PyCFunction
)DBEnv_set_lg_regionmax
, METH_VARARGS
},
6177 {"set_lk_detect", (PyCFunction
)DBEnv_set_lk_detect
, METH_VARARGS
},
6179 {"set_lk_max", (PyCFunction
)DBEnv_set_lk_max
, METH_VARARGS
},
6181 {"set_lk_max_locks", (PyCFunction
)DBEnv_set_lk_max_locks
, METH_VARARGS
},
6182 {"set_lk_max_lockers", (PyCFunction
)DBEnv_set_lk_max_lockers
, METH_VARARGS
},
6183 {"set_lk_max_objects", (PyCFunction
)DBEnv_set_lk_max_objects
, METH_VARARGS
},
6184 {"set_mp_mmapsize", (PyCFunction
)DBEnv_set_mp_mmapsize
, METH_VARARGS
},
6185 {"set_tmp_dir", (PyCFunction
)DBEnv_set_tmp_dir
, METH_VARARGS
},
6186 {"txn_begin", (PyCFunction
)DBEnv_txn_begin
, METH_VARARGS
|METH_KEYWORDS
},
6187 {"txn_checkpoint", (PyCFunction
)DBEnv_txn_checkpoint
, METH_VARARGS
},
6188 {"txn_stat", (PyCFunction
)DBEnv_txn_stat
, METH_VARARGS
},
6189 {"set_tx_max", (PyCFunction
)DBEnv_set_tx_max
, METH_VARARGS
},
6190 {"set_tx_timestamp", (PyCFunction
)DBEnv_set_tx_timestamp
, METH_VARARGS
},
6191 {"lock_detect", (PyCFunction
)DBEnv_lock_detect
, METH_VARARGS
},
6192 {"lock_get", (PyCFunction
)DBEnv_lock_get
, METH_VARARGS
},
6193 {"lock_id", (PyCFunction
)DBEnv_lock_id
, METH_VARARGS
},
6195 {"lock_id_free", (PyCFunction
)DBEnv_lock_id_free
, METH_VARARGS
},
6197 {"lock_put", (PyCFunction
)DBEnv_lock_put
, METH_VARARGS
},
6198 {"lock_stat", (PyCFunction
)DBEnv_lock_stat
, METH_VARARGS
},
6199 {"log_archive", (PyCFunction
)DBEnv_log_archive
, METH_VARARGS
},
6201 {"log_flush", (PyCFunction
)DBEnv_log_flush
, METH_VARARGS
},
6204 {"log_stat", (PyCFunction
)DBEnv_log_stat
, METH_VARARGS
},
6207 {"lsn_reset", (PyCFunction
)DBEnv_lsn_reset
, METH_VARARGS
|METH_KEYWORDS
},
6209 {"set_get_returns_none",(PyCFunction
)DBEnv_set_get_returns_none
, METH_VARARGS
},
6211 {"txn_recover", (PyCFunction
)DBEnv_txn_recover
, METH_VARARGS
},
6214 {"set_rpc_server", (PyCFunction
)DBEnv_set_rpc_server
,
6215 METH_VARARGS
||METH_KEYWORDS
},
6218 {"set_verbose", (PyCFunction
)DBEnv_set_verbose
, METH_VARARGS
},
6220 {"get_verbose", (PyCFunction
)DBEnv_get_verbose
, METH_VARARGS
},
6224 {"set_event_notify", (PyCFunction
)DBEnv_set_event_notify
, METH_VARARGS
},
6227 {"rep_set_nsites", (PyCFunction
)DBEnv_rep_set_nsites
, METH_VARARGS
},
6228 {"rep_get_nsites", (PyCFunction
)DBEnv_rep_get_nsites
, METH_VARARGS
},
6229 {"rep_set_priority", (PyCFunction
)DBEnv_rep_set_priority
, METH_VARARGS
},
6230 {"rep_get_priority", (PyCFunction
)DBEnv_rep_get_priority
, METH_VARARGS
},
6231 {"rep_set_timeout", (PyCFunction
)DBEnv_rep_set_timeout
, METH_VARARGS
},
6232 {"rep_get_timeout", (PyCFunction
)DBEnv_rep_get_timeout
, METH_VARARGS
},
6235 {"repmgr_start", (PyCFunction
)DBEnv_repmgr_start
,
6236 METH_VARARGS
|METH_KEYWORDS
},
6237 {"repmgr_set_local_site", (PyCFunction
)DBEnv_repmgr_set_local_site
,
6238 METH_VARARGS
|METH_KEYWORDS
},
6239 {"repmgr_add_remote_site", (PyCFunction
)DBEnv_repmgr_add_remote_site
,
6240 METH_VARARGS
|METH_KEYWORDS
},
6241 {"repmgr_set_ack_policy", (PyCFunction
)DBEnv_repmgr_set_ack_policy
,
6243 {"repmgr_get_ack_policy", (PyCFunction
)DBEnv_repmgr_get_ack_policy
,
6245 {"repmgr_site_list", (PyCFunction
)DBEnv_repmgr_site_list
,
6249 {"repmgr_stat", (PyCFunction
)DBEnv_repmgr_stat
,
6250 METH_VARARGS
|METH_KEYWORDS
},
6251 {"repmgr_stat_print", (PyCFunction
)DBEnv_repmgr_stat_print
,
6252 METH_VARARGS
|METH_KEYWORDS
},
6254 {NULL
, NULL
} /* sentinel */
6258 static PyMethodDef DBTxn_methods
[] = {
6259 {"commit", (PyCFunction
)DBTxn_commit
, METH_VARARGS
},
6260 {"prepare", (PyCFunction
)DBTxn_prepare
, METH_VARARGS
},
6261 {"discard", (PyCFunction
)DBTxn_discard
, METH_VARARGS
},
6262 {"abort", (PyCFunction
)DBTxn_abort
, METH_VARARGS
},
6263 {"id", (PyCFunction
)DBTxn_id
, METH_VARARGS
},
6264 {NULL
, NULL
} /* sentinel */
6269 static PyMethodDef DBSequence_methods
[] = {
6270 {"close", (PyCFunction
)DBSequence_close
, METH_VARARGS
},
6271 {"get", (PyCFunction
)DBSequence_get
, METH_VARARGS
|METH_KEYWORDS
},
6272 {"get_dbp", (PyCFunction
)DBSequence_get_dbp
, METH_VARARGS
},
6273 {"get_key", (PyCFunction
)DBSequence_get_key
, METH_VARARGS
},
6274 {"init_value", (PyCFunction
)DBSequence_init_value
, METH_VARARGS
},
6275 {"open", (PyCFunction
)DBSequence_open
, METH_VARARGS
|METH_KEYWORDS
},
6276 {"remove", (PyCFunction
)DBSequence_remove
, METH_VARARGS
|METH_KEYWORDS
},
6277 {"set_cachesize", (PyCFunction
)DBSequence_set_cachesize
, METH_VARARGS
},
6278 {"get_cachesize", (PyCFunction
)DBSequence_get_cachesize
, METH_VARARGS
},
6279 {"set_flags", (PyCFunction
)DBSequence_set_flags
, METH_VARARGS
},
6280 {"get_flags", (PyCFunction
)DBSequence_get_flags
, METH_VARARGS
},
6281 {"set_range", (PyCFunction
)DBSequence_set_range
, METH_VARARGS
},
6282 {"get_range", (PyCFunction
)DBSequence_get_range
, METH_VARARGS
},
6283 {"stat", (PyCFunction
)DBSequence_stat
, METH_VARARGS
|METH_KEYWORDS
},
6284 {NULL
, NULL
} /* sentinel */
6290 DB_getattr(DBObject
* self
, char *name
)
6292 return Py_FindMethod(DB_methods
, (PyObject
* )self
, name
);
6297 DBEnv_getattr(DBEnvObject
* self
, char *name
)
6299 if (!strcmp(name
, "db_home")) {
6300 const char *home
= NULL
;
6301 CHECK_ENV_NOT_CLOSED(self
);
6303 self
->db_env
->get_home(self
->db_env
, &home
);
6305 home
=self
->db_env
->db_home
;
6310 return PyBytes_FromString(home
);
6313 return Py_FindMethod(DBEnv_methods
, (PyObject
* )self
, name
);
6318 DBCursor_getattr(DBCursorObject
* self
, char *name
)
6320 return Py_FindMethod(DBCursor_methods
, (PyObject
* )self
, name
);
6324 DBTxn_getattr(DBTxnObject
* self
, char *name
)
6326 return Py_FindMethod(DBTxn_methods
, (PyObject
* )self
, name
);
6330 DBLock_getattr(DBLockObject
* self
, char *name
)
6337 DBSequence_getattr(DBSequenceObject
* self
, char *name
)
6339 return Py_FindMethod(DBSequence_methods
, (PyObject
* )self
, name
);
6343 statichere PyTypeObject DB_Type
= {
6344 PyObject_HEAD_INIT(NULL
)
6347 sizeof(DBObject
), /*tp_basicsize*/
6350 (destructor
)DB_dealloc
, /*tp_dealloc*/
6352 (getattrfunc
)DB_getattr
, /*tp_getattr*/
6357 0, /*tp_as_sequence*/
6358 &DB_mapping
,/*tp_as_mapping*/
6362 0, /* tp_getattro */
6363 0, /* tp_setattro */
6364 0, /* tp_as_buffer */
6365 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
6367 0, /* tp_traverse */
6369 0, /* tp_richcompare */
6370 offsetof(DBObject
, in_weakreflist
), /* tp_weaklistoffset */
6374 statichere PyTypeObject DBCursor_Type
= {
6375 PyObject_HEAD_INIT(NULL
)
6377 "DBCursor", /*tp_name*/
6378 sizeof(DBCursorObject
), /*tp_basicsize*/
6381 (destructor
)DBCursor_dealloc
,/*tp_dealloc*/
6383 (getattrfunc
)DBCursor_getattr
, /*tp_getattr*/
6388 0, /*tp_as_sequence*/
6389 0, /*tp_as_mapping*/
6393 0, /* tp_getattro */
6394 0, /* tp_setattro */
6395 0, /* tp_as_buffer */
6396 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
6398 0, /* tp_traverse */
6400 0, /* tp_richcompare */
6401 offsetof(DBCursorObject
, in_weakreflist
), /* tp_weaklistoffset */
6405 statichere PyTypeObject DBEnv_Type
= {
6406 PyObject_HEAD_INIT(NULL
)
6408 "DBEnv", /*tp_name*/
6409 sizeof(DBEnvObject
), /*tp_basicsize*/
6412 (destructor
)DBEnv_dealloc
, /*tp_dealloc*/
6414 (getattrfunc
)DBEnv_getattr
, /*tp_getattr*/
6419 0, /*tp_as_sequence*/
6420 0, /*tp_as_mapping*/
6424 0, /* tp_getattro */
6425 0, /* tp_setattro */
6426 0, /* tp_as_buffer */
6427 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
6429 0, /* tp_traverse */
6431 0, /* tp_richcompare */
6432 offsetof(DBEnvObject
, in_weakreflist
), /* tp_weaklistoffset */
6435 statichere PyTypeObject DBTxn_Type
= {
6436 PyObject_HEAD_INIT(NULL
)
6438 "DBTxn", /*tp_name*/
6439 sizeof(DBTxnObject
), /*tp_basicsize*/
6442 (destructor
)DBTxn_dealloc
, /*tp_dealloc*/
6444 (getattrfunc
)DBTxn_getattr
, /*tp_getattr*/
6449 0, /*tp_as_sequence*/
6450 0, /*tp_as_mapping*/
6454 0, /* tp_getattro */
6455 0, /* tp_setattro */
6456 0, /* tp_as_buffer */
6457 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
6459 0, /* tp_traverse */
6461 0, /* tp_richcompare */
6462 offsetof(DBTxnObject
, in_weakreflist
), /* tp_weaklistoffset */
6466 statichere PyTypeObject DBLock_Type
= {
6467 PyObject_HEAD_INIT(NULL
)
6469 "DBLock", /*tp_name*/
6470 sizeof(DBLockObject
), /*tp_basicsize*/
6473 (destructor
)DBLock_dealloc
, /*tp_dealloc*/
6475 (getattrfunc
)DBLock_getattr
, /*tp_getattr*/
6480 0, /*tp_as_sequence*/
6481 0, /*tp_as_mapping*/
6485 0, /* tp_getattro */
6486 0, /* tp_setattro */
6487 0, /* tp_as_buffer */
6488 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
6490 0, /* tp_traverse */
6492 0, /* tp_richcompare */
6493 offsetof(DBLockObject
, in_weakreflist
), /* tp_weaklistoffset */
6497 statichere PyTypeObject DBSequence_Type
= {
6498 PyObject_HEAD_INIT(NULL
)
6500 "DBSequence", /*tp_name*/
6501 sizeof(DBSequenceObject
), /*tp_basicsize*/
6504 (destructor
)DBSequence_dealloc
, /*tp_dealloc*/
6506 (getattrfunc
)DBSequence_getattr
,/*tp_getattr*/
6511 0, /*tp_as_sequence*/
6512 0, /*tp_as_mapping*/
6516 0, /* tp_getattro */
6517 0, /* tp_setattro */
6518 0, /* tp_as_buffer */
6519 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_WEAKREFS
, /* tp_flags */
6521 0, /* tp_traverse */
6523 0, /* tp_richcompare */
6524 offsetof(DBSequenceObject
, in_weakreflist
), /* tp_weaklistoffset */
6528 /* --------------------------------------------------------------------- */
6529 /* Module-level functions */
6532 DB_construct(PyObject
* self
, PyObject
* args
, PyObject
* kwargs
)
6534 PyObject
* dbenvobj
= NULL
;
6536 static char* kwnames
[] = { "dbEnv", "flags", NULL
};
6538 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "|Oi:DB", kwnames
,
6541 if (dbenvobj
== Py_None
)
6543 else if (dbenvobj
&& !DBEnvObject_Check(dbenvobj
)) {
6544 makeTypeError("DBEnv", dbenvobj
);
6548 return (PyObject
* )newDBObject((DBEnvObject
*)dbenvobj
, flags
);
6553 DBEnv_construct(PyObject
* self
, PyObject
* args
)
6556 if (!PyArg_ParseTuple(args
, "|i:DbEnv", &flags
)) return NULL
;
6557 return (PyObject
* )newDBEnvObject(flags
);
6562 DBSequence_construct(PyObject
* self
, PyObject
* args
, PyObject
* kwargs
)
6566 static char* kwnames
[] = { "db", "flags", NULL
};
6568 if (!PyArg_ParseTupleAndKeywords(args
, kwargs
, "O|i:DBSequence", kwnames
, &dbobj
, &flags
))
6570 if (!DBObject_Check(dbobj
)) {
6571 makeTypeError("DB", dbobj
);
6574 return (PyObject
* )newDBSequenceObject((DBObject
*)dbobj
, flags
);
6578 static char bsddb_version_doc
[] =
6579 "Returns a tuple of major, minor, and patch release numbers of the\n\
6580 underlying DB library.";
6583 bsddb_version(PyObject
* self
, PyObject
* args
)
6585 int major
, minor
, patch
;
6587 if (!PyArg_ParseTuple(args
, ":version"))
6589 db_version(&major
, &minor
, &patch
);
6590 return Py_BuildValue("(iii)", major
, minor
, patch
);
6594 /* List of functions defined in the module */
6596 static PyMethodDef bsddb_methods
[] = {
6597 {"DB", (PyCFunction
)DB_construct
, METH_VARARGS
| METH_KEYWORDS
},
6598 {"DBEnv", (PyCFunction
)DBEnv_construct
, METH_VARARGS
},
6600 {"DBSequence", (PyCFunction
)DBSequence_construct
, METH_VARARGS
| METH_KEYWORDS
},
6602 {"version", (PyCFunction
)bsddb_version
, METH_VARARGS
, bsddb_version_doc
},
6603 {NULL
, NULL
} /* sentinel */
6607 static BSDDB_api bsddb_api
;
6610 /* --------------------------------------------------------------------- */
6611 /* Module initialization */
6614 /* Convenience routine to export an integer value.
6615 * Errors are silently ignored, for better or for worse...
6617 #define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6619 #define MODULE_NAME_MAX_LEN 11
6620 static char _bsddbModuleName
[MODULE_NAME_MAX_LEN
+1] = "_bsddb";
6622 DL_EXPORT(void) init_bsddb(void)
6626 PyObject
* pybsddb_version_s
= PyBytes_FromString( PY_BSDDB_VERSION
);
6627 PyObject
* db_version_s
= PyBytes_FromString( DB_VERSION_STRING
);
6628 PyObject
* cvsid_s
= PyBytes_FromString( rcs_id
);
6631 /* Initialize the type of the new type objects here; doing it here
6632 is required for portability to Windows without requiring C++. */
6633 Py_TYPE(&DB_Type
) = &PyType_Type
;
6634 Py_TYPE(&DBCursor_Type
) = &PyType_Type
;
6635 Py_TYPE(&DBEnv_Type
) = &PyType_Type
;
6636 Py_TYPE(&DBTxn_Type
) = &PyType_Type
;
6637 Py_TYPE(&DBLock_Type
) = &PyType_Type
;
6639 Py_TYPE(&DBSequence_Type
) = &PyType_Type
;
6643 #if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
6644 /* Save the current interpreter, so callbacks can do the right thing. */
6645 _db_interpreterState
= PyThreadState_GET()->interp
;
6648 /* Create the module and add the functions */
6649 m
= Py_InitModule(_bsddbModuleName
, bsddb_methods
);
6653 /* Add some symbolic constants to the module */
6654 d
= PyModule_GetDict(m
);
6655 PyDict_SetItemString(d
, "__version__", pybsddb_version_s
);
6656 PyDict_SetItemString(d
, "cvsid", cvsid_s
);
6657 PyDict_SetItemString(d
, "DB_VERSION_STRING", db_version_s
);
6658 Py_DECREF(pybsddb_version_s
);
6659 pybsddb_version_s
= NULL
;
6662 Py_DECREF(db_version_s
);
6663 db_version_s
= NULL
;
6665 ADD_INT(d
, DB_VERSION_MAJOR
);
6666 ADD_INT(d
, DB_VERSION_MINOR
);
6667 ADD_INT(d
, DB_VERSION_PATCH
);
6669 ADD_INT(d
, DB_MAX_PAGES
);
6670 ADD_INT(d
, DB_MAX_RECORDS
);
6673 ADD_INT(d
, DB_RPCCLIENT
);
6675 ADD_INT(d
, DB_CLIENT
);
6676 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
6677 _addIntToDict(d
, "DB_RPCCLIENT", DB_CLIENT
);
6679 ADD_INT(d
, DB_XA_CREATE
);
6681 ADD_INT(d
, DB_CREATE
);
6682 ADD_INT(d
, DB_NOMMAP
);
6683 ADD_INT(d
, DB_THREAD
);
6685 ADD_INT(d
, DB_MULTIVERSION
);
6688 ADD_INT(d
, DB_FORCE
);
6689 ADD_INT(d
, DB_INIT_CDB
);
6690 ADD_INT(d
, DB_INIT_LOCK
);
6691 ADD_INT(d
, DB_INIT_LOG
);
6692 ADD_INT(d
, DB_INIT_MPOOL
);
6693 ADD_INT(d
, DB_INIT_TXN
);
6694 ADD_INT(d
, DB_JOINENV
);
6697 ADD_INT(d
, DB_XIDDATASIZE
);
6700 ADD_INT(d
, DB_RECOVER
);
6701 ADD_INT(d
, DB_RECOVER_FATAL
);
6702 ADD_INT(d
, DB_TXN_NOSYNC
);
6703 ADD_INT(d
, DB_USE_ENVIRON
);
6704 ADD_INT(d
, DB_USE_ENVIRON_ROOT
);
6706 ADD_INT(d
, DB_LOCKDOWN
);
6707 ADD_INT(d
, DB_PRIVATE
);
6708 ADD_INT(d
, DB_SYSTEM_MEM
);
6710 ADD_INT(d
, DB_TXN_SYNC
);
6711 ADD_INT(d
, DB_TXN_NOWAIT
);
6713 ADD_INT(d
, DB_EXCL
);
6714 ADD_INT(d
, DB_FCNTL_LOCKING
);
6715 ADD_INT(d
, DB_ODDFILESIZE
);
6716 ADD_INT(d
, DB_RDWRMASTER
);
6717 ADD_INT(d
, DB_RDONLY
);
6718 ADD_INT(d
, DB_TRUNCATE
);
6719 ADD_INT(d
, DB_EXTENT
);
6720 ADD_INT(d
, DB_CDB_ALLDB
);
6721 ADD_INT(d
, DB_VERIFY
);
6722 ADD_INT(d
, DB_UPGRADE
);
6724 ADD_INT(d
, DB_AGGRESSIVE
);
6725 ADD_INT(d
, DB_NOORDERCHK
);
6726 ADD_INT(d
, DB_ORDERCHKONLY
);
6727 ADD_INT(d
, DB_PR_PAGE
);
6729 ADD_INT(d
, DB_VRFY_FLAGMASK
);
6730 ADD_INT(d
, DB_PR_HEADERS
);
6732 ADD_INT(d
, DB_PR_RECOVERYTEST
);
6733 ADD_INT(d
, DB_SALVAGE
);
6735 ADD_INT(d
, DB_LOCK_NORUN
);
6736 ADD_INT(d
, DB_LOCK_DEFAULT
);
6737 ADD_INT(d
, DB_LOCK_OLDEST
);
6738 ADD_INT(d
, DB_LOCK_RANDOM
);
6739 ADD_INT(d
, DB_LOCK_YOUNGEST
);
6741 ADD_INT(d
, DB_LOCK_MAXLOCKS
);
6742 ADD_INT(d
, DB_LOCK_MINLOCKS
);
6743 ADD_INT(d
, DB_LOCK_MINWRITE
);
6747 ADD_INT(d
, DB_LOCK_EXPIRE
);
6750 ADD_INT(d
, DB_LOCK_MAXWRITE
);
6755 /* docs say to use zero instead */
6756 _addIntToDict(d
, "DB_LOCK_CONFLICT", 0);
6758 ADD_INT(d
, DB_LOCK_CONFLICT
);
6761 ADD_INT(d
, DB_LOCK_DUMP
);
6762 ADD_INT(d
, DB_LOCK_GET
);
6763 ADD_INT(d
, DB_LOCK_INHERIT
);
6764 ADD_INT(d
, DB_LOCK_PUT
);
6765 ADD_INT(d
, DB_LOCK_PUT_ALL
);
6766 ADD_INT(d
, DB_LOCK_PUT_OBJ
);
6768 ADD_INT(d
, DB_LOCK_NG
);
6769 ADD_INT(d
, DB_LOCK_READ
);
6770 ADD_INT(d
, DB_LOCK_WRITE
);
6771 ADD_INT(d
, DB_LOCK_NOWAIT
);
6772 ADD_INT(d
, DB_LOCK_WAIT
);
6773 ADD_INT(d
, DB_LOCK_IWRITE
);
6774 ADD_INT(d
, DB_LOCK_IREAD
);
6775 ADD_INT(d
, DB_LOCK_IWR
);
6778 ADD_INT(d
, DB_LOCK_DIRTY
);
6780 ADD_INT(d
, DB_LOCK_READ_UNCOMMITTED
); /* renamed in 4.4 */
6782 ADD_INT(d
, DB_LOCK_WWRITE
);
6785 ADD_INT(d
, DB_LOCK_RECORD
);
6786 ADD_INT(d
, DB_LOCK_UPGRADE
);
6787 ADD_INT(d
, DB_LOCK_SWITCH
);
6789 ADD_INT(d
, DB_LOCK_UPGRADE_WRITE
);
6792 ADD_INT(d
, DB_LOCK_NOWAIT
);
6793 ADD_INT(d
, DB_LOCK_RECORD
);
6794 ADD_INT(d
, DB_LOCK_UPGRADE
);
6797 ADD_INT(d
, DB_LSTAT_ABORTED
);
6799 ADD_INT(d
, DB_LSTAT_ERR
);
6801 ADD_INT(d
, DB_LSTAT_FREE
);
6802 ADD_INT(d
, DB_LSTAT_HELD
);
6804 ADD_INT(d
, DB_LSTAT_NOGRANT
);
6806 ADD_INT(d
, DB_LSTAT_PENDING
);
6807 ADD_INT(d
, DB_LSTAT_WAITING
);
6810 ADD_INT(d
, DB_ARCH_ABS
);
6811 ADD_INT(d
, DB_ARCH_DATA
);
6812 ADD_INT(d
, DB_ARCH_LOG
);
6814 ADD_INT(d
, DB_ARCH_REMOVE
);
6817 ADD_INT(d
, DB_BTREE
);
6818 ADD_INT(d
, DB_HASH
);
6819 ADD_INT(d
, DB_RECNO
);
6820 ADD_INT(d
, DB_QUEUE
);
6821 ADD_INT(d
, DB_UNKNOWN
);
6824 ADD_INT(d
, DB_DUPSORT
);
6825 ADD_INT(d
, DB_RECNUM
);
6826 ADD_INT(d
, DB_RENUMBER
);
6827 ADD_INT(d
, DB_REVSPLITOFF
);
6828 ADD_INT(d
, DB_SNAPSHOT
);
6830 ADD_INT(d
, DB_JOIN_NOSORT
);
6832 ADD_INT(d
, DB_AFTER
);
6833 ADD_INT(d
, DB_APPEND
);
6834 ADD_INT(d
, DB_BEFORE
);
6836 ADD_INT(d
, DB_CACHED_COUNTS
);
6840 _addIntToDict(d
, "DB_CHECKPOINT", 0);
6842 ADD_INT(d
, DB_CHECKPOINT
);
6843 ADD_INT(d
, DB_CURLSN
);
6845 #if ((DBVER >= 33) && (DBVER <= 41))
6846 ADD_INT(d
, DB_COMMIT
);
6848 ADD_INT(d
, DB_CONSUME
);
6849 ADD_INT(d
, DB_CONSUME_WAIT
);
6850 ADD_INT(d
, DB_CURRENT
);
6852 ADD_INT(d
, DB_FAST_STAT
);
6854 ADD_INT(d
, DB_FIRST
);
6855 ADD_INT(d
, DB_FLUSH
);
6856 ADD_INT(d
, DB_GET_BOTH
);
6857 ADD_INT(d
, DB_GET_RECNO
);
6858 ADD_INT(d
, DB_JOIN_ITEM
);
6859 ADD_INT(d
, DB_KEYFIRST
);
6860 ADD_INT(d
, DB_KEYLAST
);
6861 ADD_INT(d
, DB_LAST
);
6862 ADD_INT(d
, DB_NEXT
);
6863 ADD_INT(d
, DB_NEXT_DUP
);
6864 ADD_INT(d
, DB_NEXT_NODUP
);
6865 ADD_INT(d
, DB_NODUPDATA
);
6866 ADD_INT(d
, DB_NOOVERWRITE
);
6867 ADD_INT(d
, DB_NOSYNC
);
6868 ADD_INT(d
, DB_POSITION
);
6869 ADD_INT(d
, DB_PREV
);
6870 ADD_INT(d
, DB_PREV_NODUP
);
6872 ADD_INT(d
, DB_RECORDCOUNT
);
6875 ADD_INT(d
, DB_SET_RANGE
);
6876 ADD_INT(d
, DB_SET_RECNO
);
6877 ADD_INT(d
, DB_WRITECURSOR
);
6879 ADD_INT(d
, DB_OPFLAGS_MASK
);
6882 ADD_INT(d
, DB_DIRTY_READ
);
6883 ADD_INT(d
, DB_MULTIPLE
);
6884 ADD_INT(d
, DB_MULTIPLE_KEY
);
6888 ADD_INT(d
, DB_READ_UNCOMMITTED
); /* replaces DB_DIRTY_READ in 4.4 */
6889 ADD_INT(d
, DB_READ_COMMITTED
);
6893 ADD_INT(d
, DB_DONOTINDEX
);
6897 _addIntToDict(d
, "DB_INCOMPLETE", 0);
6899 ADD_INT(d
, DB_INCOMPLETE
);
6901 ADD_INT(d
, DB_KEYEMPTY
);
6902 ADD_INT(d
, DB_KEYEXIST
);
6903 ADD_INT(d
, DB_LOCK_DEADLOCK
);
6904 ADD_INT(d
, DB_LOCK_NOTGRANTED
);
6905 ADD_INT(d
, DB_NOSERVER
);
6906 ADD_INT(d
, DB_NOSERVER_HOME
);
6907 ADD_INT(d
, DB_NOSERVER_ID
);
6908 ADD_INT(d
, DB_NOTFOUND
);
6909 ADD_INT(d
, DB_OLD_VERSION
);
6910 ADD_INT(d
, DB_RUNRECOVERY
);
6911 ADD_INT(d
, DB_VERIFY_BAD
);
6913 ADD_INT(d
, DB_PAGE_NOTFOUND
);
6914 ADD_INT(d
, DB_SECONDARY_BAD
);
6917 ADD_INT(d
, DB_STAT_CLEAR
);
6918 ADD_INT(d
, DB_REGION_INIT
);
6919 ADD_INT(d
, DB_NOLOCKING
);
6920 ADD_INT(d
, DB_YIELDCPU
);
6921 ADD_INT(d
, DB_PANIC_ENVIRONMENT
);
6922 ADD_INT(d
, DB_NOPANIC
);
6926 ADD_INT(d
, DB_OVERWRITE
);
6930 ADD_INT(d
, DB_REGISTER
);
6934 ADD_INT(d
, DB_TIME_NOTGRANTED
);
6935 ADD_INT(d
, DB_TXN_NOT_DURABLE
);
6936 ADD_INT(d
, DB_TXN_WRITE_NOSYNC
);
6937 ADD_INT(d
, DB_DIRECT_DB
);
6938 ADD_INT(d
, DB_INIT_REP
);
6939 ADD_INT(d
, DB_ENCRYPT
);
6940 ADD_INT(d
, DB_CHKSUM
);
6943 #if (DBVER >= 42) && (DBVER < 47)
6944 ADD_INT(d
, DB_LOG_AUTOREMOVE
);
6945 ADD_INT(d
, DB_DIRECT_LOG
);
6949 ADD_INT(d
, DB_LOG_DIRECT
);
6950 ADD_INT(d
, DB_LOG_DSYNC
);
6951 ADD_INT(d
, DB_LOG_IN_MEMORY
);
6952 ADD_INT(d
, DB_LOG_AUTO_REMOVE
);
6953 ADD_INT(d
, DB_LOG_ZERO
);
6957 ADD_INT(d
, DB_DSYNC_DB
);
6961 ADD_INT(d
, DB_TXN_SNAPSHOT
);
6965 ADD_INT(d
, DB_VERB_DEADLOCK
);
6967 ADD_INT(d
, DB_VERB_FILEOPS
);
6968 ADD_INT(d
, DB_VERB_FILEOPS_ALL
);
6970 ADD_INT(d
, DB_VERB_RECOVERY
);
6972 ADD_INT(d
, DB_VERB_REGISTER
);
6974 ADD_INT(d
, DB_VERB_REPLICATION
);
6975 ADD_INT(d
, DB_VERB_WAITSFOR
);
6979 ADD_INT(d
, DB_EVENT_PANIC
);
6980 ADD_INT(d
, DB_EVENT_REP_CLIENT
);
6982 ADD_INT(d
, DB_EVENT_REP_ELECTED
);
6984 ADD_INT(d
, DB_EVENT_REP_MASTER
);
6985 ADD_INT(d
, DB_EVENT_REP_NEWMASTER
);
6987 ADD_INT(d
, DB_EVENT_REP_PERM_FAILED
);
6989 ADD_INT(d
, DB_EVENT_REP_STARTUPDONE
);
6990 ADD_INT(d
, DB_EVENT_WRITE_FAILED
);
6994 ADD_INT(d
, DB_REP_MASTER
);
6995 ADD_INT(d
, DB_REP_CLIENT
);
6997 ADD_INT(d
, DB_REP_ELECTION
);
6999 ADD_INT(d
, DB_REP_ACK_TIMEOUT
);
7000 ADD_INT(d
, DB_REP_CONNECTION_RETRY
);
7001 ADD_INT(d
, DB_REP_ELECTION_TIMEOUT
);
7002 ADD_INT(d
, DB_REP_ELECTION_RETRY
);
7005 ADD_INT(d
, DB_REP_CHECKPOINT_DELAY
);
7006 ADD_INT(d
, DB_REP_FULL_ELECTION_TIMEOUT
);
7011 ADD_INT(d
, DB_REPMGR_PEER
);
7012 ADD_INT(d
, DB_REPMGR_ACKS_ALL
);
7013 ADD_INT(d
, DB_REPMGR_ACKS_ALL_PEERS
);
7014 ADD_INT(d
, DB_REPMGR_ACKS_NONE
);
7015 ADD_INT(d
, DB_REPMGR_ACKS_ONE
);
7016 ADD_INT(d
, DB_REPMGR_ACKS_ONE_PEER
);
7017 ADD_INT(d
, DB_REPMGR_ACKS_QUORUM
);
7018 ADD_INT(d
, DB_REPMGR_CONNECTED
);
7019 ADD_INT(d
, DB_REPMGR_DISCONNECTED
);
7020 ADD_INT(d
, DB_STAT_CLEAR
);
7021 ADD_INT(d
, DB_STAT_ALL
);
7025 ADD_INT(d
, DB_BUFFER_SMALL
);
7026 ADD_INT(d
, DB_SEQ_DEC
);
7027 ADD_INT(d
, DB_SEQ_INC
);
7028 ADD_INT(d
, DB_SEQ_WRAP
);
7031 #if (DBVER >= 43) && (DBVER < 47)
7032 ADD_INT(d
, DB_LOG_INMEMORY
);
7033 ADD_INT(d
, DB_DSYNC_LOG
);
7037 ADD_INT(d
, DB_ENCRYPT_AES
);
7038 ADD_INT(d
, DB_AUTO_COMMIT
);
7040 /* allow Berkeley DB 4.1 aware apps to run on older versions */
7041 _addIntToDict(d
, "DB_AUTO_COMMIT", 0);
7055 ADD_INT(d
, DB_SET_LOCK_TIMEOUT
);
7056 ADD_INT(d
, DB_SET_TXN_TIMEOUT
);
7059 /* The exception name must be correct for pickled exception *
7060 * objects to unpickle properly. */
7061 #ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7062 #define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7064 #define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7067 /* All the rest of the exceptions derive only from DBError */
7068 #define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7069 PyDict_SetItemString(d, #name, name)
7071 /* The base exception class is DBError */
7072 DBError
= NULL
; /* used in MAKE_EX so that it derives from nothing */
7075 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7076 * from both DBError and KeyError, since the API only supports
7077 * using one base class. */
7078 PyDict_SetItemString(d
, "KeyError", PyExc_KeyError
);
7079 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7080 "class DBKeyEmptyError(DBError, KeyError): pass",
7081 Py_file_input
, d
, d
);
7082 DBNotFoundError
= PyDict_GetItemString(d
, "DBNotFoundError");
7083 DBKeyEmptyError
= PyDict_GetItemString(d
, "DBKeyEmptyError");
7084 PyDict_DelItemString(d
, "KeyError");
7087 #if !INCOMPLETE_IS_WARNING
7088 MAKE_EX(DBIncompleteError
);
7090 MAKE_EX(DBCursorClosedError
);
7091 MAKE_EX(DBKeyEmptyError
);
7092 MAKE_EX(DBKeyExistError
);
7093 MAKE_EX(DBLockDeadlockError
);
7094 MAKE_EX(DBLockNotGrantedError
);
7095 MAKE_EX(DBOldVersionError
);
7096 MAKE_EX(DBRunRecoveryError
);
7097 MAKE_EX(DBVerifyBadError
);
7098 MAKE_EX(DBNoServerError
);
7099 MAKE_EX(DBNoServerHomeError
);
7100 MAKE_EX(DBNoServerIDError
);
7102 MAKE_EX(DBPageNotFoundError
);
7103 MAKE_EX(DBSecondaryBadError
);
7106 MAKE_EX(DBInvalidArgError
);
7107 MAKE_EX(DBAccessError
);
7108 MAKE_EX(DBNoSpaceError
);
7109 MAKE_EX(DBNoMemoryError
);
7110 MAKE_EX(DBAgainError
);
7111 MAKE_EX(DBBusyError
);
7112 MAKE_EX(DBFileExistsError
);
7113 MAKE_EX(DBNoSuchFileError
);
7114 MAKE_EX(DBPermissionsError
);
7117 MAKE_EX(DBRepHandleDeadError
);
7122 /* Initiliase the C API structure and add it to the module */
7123 bsddb_api
.db_type
= &DB_Type
;
7124 bsddb_api
.dbcursor_type
= &DBCursor_Type
;
7125 bsddb_api
.dbenv_type
= &DBEnv_Type
;
7126 bsddb_api
.dbtxn_type
= &DBTxn_Type
;
7127 bsddb_api
.dblock_type
= &DBLock_Type
;
7129 bsddb_api
.dbsequence_type
= &DBSequence_Type
;
7131 bsddb_api
.makeDBError
= makeDBError
;
7133 py_api
= PyCObject_FromVoidPtr((void*)&bsddb_api
, NULL
);
7134 PyDict_SetItemString(d
, "api", py_api
);
7137 /* Check for errors */
7138 if (PyErr_Occurred()) {
7140 Py_FatalError("can't initialize module _bsddb");
7144 /* allow this module to be named _pybsddb so that it can be installed
7145 * and imported on top of python >= 2.3 that includes its own older
7146 * copy of the library named _bsddb without importing the old version. */
7147 DL_EXPORT(void) init_pybsddb(void)
7149 strncpy(_bsddbModuleName
, "_pybsddb", MODULE_NAME_MAX_LEN
);