blob: e2929ca7db1d6293a31091284bd34012a6aa4bb1 [file] [log] [blame]
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001/*----------------------------------------------------------------------
2 Copyright (c) 1999-2001, Digital Creations, Fredericksburg, VA, USA
3 and Andrew Kuchling. All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8
9 o Redistributions of source code must retain the above copyright
10 notice, this list of conditions, and the disclaimer that follows.
11
12 o Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions, and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
16
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.
20
21 THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS AND CONTRIBUTORS *AS
22 IS* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DIGITAL
25 CREATIONS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
28 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
30 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
31 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
32 DAMAGE.
33------------------------------------------------------------------------*/
34
35
36/*
37 * Handwritten code to wrap version 3.x of the Berkeley DB library,
Barry Warsaw9a0d7792002-12-30 20:53:52 +000038 * written to replace a SWIG-generated file. It has since been updated
Jesus Ceaef9764f2008-05-13 18:45:46 +000039 * to compile with Berkeley DB versions 3.2 through 4.2.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000040 *
41 * This module was started by Andrew Kuchling to remove the dependency
Gregory P. Smithf8057852007-09-09 20:25:00 +000042 * 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
44 * Berkeley DB 2.7.x.
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000045 *
Barry Warsaw9a0d7792002-12-30 20:53:52 +000046 * 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).
50 *
Jesus Ceaef9764f2008-05-13 18:45:46 +000051 * Gregory P. Smith <greg@krypto.org> was once again the maintainer.
52 *
Jesus Ceaca3939c2008-05-22 15:27:38 +000053 * Since January 2008, new maintainer is Jesus Cea <jcea@jcea.es>.
Jesus Ceaef9764f2008-05-13 18:45:46 +000054 * Jesus Cea licenses this code to PSF under a Contributor Agreement.
Barry Warsaw9a0d7792002-12-30 20:53:52 +000055 *
56 * Use the pybsddb-users@lists.sf.net mailing list for all questions.
Barry Warsawc74e4a52003-04-24 14:28:08 +000057 * Things can change faster than the header of this file is updated. This
58 * file is shared with the PyBSDDB project at SourceForge:
59 *
60 * http://pybsddb.sf.net
61 *
62 * This file should remain backward compatible with Python 2.1, but see PEP
63 * 291 for the most current backward compatibility requirements:
64 *
65 * http://www.python.org/peps/pep-0291.html
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000066 *
Gregory P. Smithf0547d02006-06-05 17:38:04 +000067 * This module contains 6 types:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000068 *
69 * DB (Database)
70 * DBCursor (Database Cursor)
71 * DBEnv (database environment)
72 * DBTxn (An explicit database transaction)
73 * DBLock (A lock handle)
Gregory P. Smithf0547d02006-06-05 17:38:04 +000074 * DBSequence (Sequence)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000075 *
76 */
77
78/* --------------------------------------------------------------------- */
79
80/*
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.
85 *
86 * --Robin
87 */
88
89/* --------------------------------------------------------------------- */
90
Gregory P. Smitha703a212003-11-03 01:04:41 +000091#include <stddef.h> /* for offsetof() */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000092#include <Python.h>
Gregory P. Smith39250532007-10-09 06:02:21 +000093
94#define COMPILING_BSDDB_C
95#include "bsddb.h"
96#undef COMPILING_BSDDB_C
97
98static char *rcs_id = "$Id$";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +000099
100/* --------------------------------------------------------------------- */
101/* Various macro definitions */
102
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000103#if (PY_VERSION_HEX < 0x02050000)
Neal Norwitz09a29fa2006-06-12 02:05:55 +0000104typedef int Py_ssize_t;
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +0000105#endif
106
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000107#ifdef WITH_THREAD
108
109/* These are for when calling Python --> C */
110#define MYDB_BEGIN_ALLOW_THREADS Py_BEGIN_ALLOW_THREADS;
111#define MYDB_END_ALLOW_THREADS Py_END_ALLOW_THREADS;
112
Mark Hammonda69d4092003-04-22 23:13:27 +0000113/* For 2.3, use the PyGILState_ calls */
114#if (PY_VERSION_HEX >= 0x02030000)
115#define MYDB_USE_GILSTATE
116#endif
117
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000118/* and these are for calling C --> Python */
Mark Hammonda69d4092003-04-22 23:13:27 +0000119#if defined(MYDB_USE_GILSTATE)
120#define MYDB_BEGIN_BLOCK_THREADS \
121 PyGILState_STATE __savestate = PyGILState_Ensure();
122#define MYDB_END_BLOCK_THREADS \
123 PyGILState_Release(__savestate);
124#else /* MYDB_USE_GILSTATE */
125/* Pre GILState API - do it the long old way */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000126static PyInterpreterState* _db_interpreterState = NULL;
127#define MYDB_BEGIN_BLOCK_THREADS { \
128 PyThreadState* prevState; \
129 PyThreadState* newState; \
130 PyEval_AcquireLock(); \
131 newState = PyThreadState_New(_db_interpreterState); \
132 prevState = PyThreadState_Swap(newState);
133
134#define MYDB_END_BLOCK_THREADS \
135 newState = PyThreadState_Swap(prevState); \
136 PyThreadState_Clear(newState); \
137 PyEval_ReleaseLock(); \
138 PyThreadState_Delete(newState); \
139 }
Mark Hammonda69d4092003-04-22 23:13:27 +0000140#endif /* MYDB_USE_GILSTATE */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000141
142#else
Mark Hammonda69d4092003-04-22 23:13:27 +0000143/* Compiled without threads - avoid all this cruft */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000144#define MYDB_BEGIN_ALLOW_THREADS
145#define MYDB_END_ALLOW_THREADS
146#define MYDB_BEGIN_BLOCK_THREADS
147#define MYDB_END_BLOCK_THREADS
148
149#endif
150
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000151/* Should DB_INCOMPLETE be turned into a warning or an exception? */
152#define INCOMPLETE_IS_WARNING 1
153
154/* --------------------------------------------------------------------- */
155/* Exceptions */
156
157static PyObject* DBError; /* Base class, all others derive from this */
Gregory P. Smithe2767172003-11-02 08:06:29 +0000158static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
Gregory P. Smithe9477062005-06-04 06:46:59 +0000159static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY: also derives from KeyError */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000160static PyObject* DBKeyExistError; /* DB_KEYEXIST */
161static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
162static PyObject* DBLockNotGrantedError; /* DB_LOCK_NOTGRANTED */
163static PyObject* DBNotFoundError; /* DB_NOTFOUND: also derives from KeyError */
164static PyObject* DBOldVersionError; /* DB_OLD_VERSION */
165static PyObject* DBRunRecoveryError; /* DB_RUNRECOVERY */
166static PyObject* DBVerifyBadError; /* DB_VERIFY_BAD */
167static PyObject* DBNoServerError; /* DB_NOSERVER */
168static PyObject* DBNoServerHomeError; /* DB_NOSERVER_HOME */
169static PyObject* DBNoServerIDError; /* DB_NOSERVER_ID */
170#if (DBVER >= 33)
171static PyObject* DBPageNotFoundError; /* DB_PAGE_NOTFOUND */
172static PyObject* DBSecondaryBadError; /* DB_SECONDARY_BAD */
173#endif
174
175#if !INCOMPLETE_IS_WARNING
176static PyObject* DBIncompleteError; /* DB_INCOMPLETE */
177#endif
178
179static PyObject* DBInvalidArgError; /* EINVAL */
180static PyObject* DBAccessError; /* EACCES */
181static PyObject* DBNoSpaceError; /* ENOSPC */
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000182static PyObject* DBNoMemoryError; /* DB_BUFFER_SMALL (ENOMEM when < 4.3) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000183static PyObject* DBAgainError; /* EAGAIN */
184static PyObject* DBBusyError; /* EBUSY */
185static PyObject* DBFileExistsError; /* EEXIST */
186static PyObject* DBNoSuchFileError; /* ENOENT */
187static PyObject* DBPermissionsError; /* EPERM */
188
Jesus Ceaef9764f2008-05-13 18:45:46 +0000189#if (DBVER >= 42)
190static PyObject* DBRepHandleDeadError; /* DB_REP_HANDLE_DEAD */
191#endif
192
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000193#if (DBVER < 43)
194#define DB_BUFFER_SMALL ENOMEM
195#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000196
197
198/* --------------------------------------------------------------------- */
199/* Structure definitions */
200
Gregory P. Smith39250532007-10-09 06:02:21 +0000201#if PYTHON_API_VERSION < 1010
202#error "Python 2.1 or later required"
Gregory P. Smitha703a212003-11-03 01:04:41 +0000203#endif
204
Gregory P. Smith31c50652004-06-28 01:20:40 +0000205
Gregory P. Smith39250532007-10-09 06:02:21 +0000206/* Defaults for moduleFlags in DBEnvObject and DBObject. */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000207#define DEFAULT_GET_RETURNS_NONE 1
Gregory P. Smitha703a212003-11-03 01:04:41 +0000208#define DEFAULT_CURSOR_SET_RETURNS_NONE 1 /* 0 in pybsddb < 4.2, python < 2.4 */
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000209
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000210
211staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLock_Type;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000212#if (DBVER >= 43)
213staticforward PyTypeObject DBSequence_Type;
214#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000215
Martin v. Löwis83c92012008-04-24 13:17:24 +0000216#ifndef Py_TYPE
Gregory P. Smithfc006692007-11-05 09:06:28 +0000217/* for compatibility with Python 2.5 and earlier */
Christian Heimese93237d2007-12-19 02:37:44 +0000218#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
Gregory P. Smithfc006692007-11-05 09:06:28 +0000219#endif
220
Christian Heimese93237d2007-12-19 02:37:44 +0000221#define DBObject_Check(v) (Py_TYPE(v) == &DB_Type)
222#define DBCursorObject_Check(v) (Py_TYPE(v) == &DBCursor_Type)
223#define DBEnvObject_Check(v) (Py_TYPE(v) == &DBEnv_Type)
224#define DBTxnObject_Check(v) (Py_TYPE(v) == &DBTxn_Type)
225#define DBLockObject_Check(v) (Py_TYPE(v) == &DBLock_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000226#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +0000227#define DBSequenceObject_Check(v) (Py_TYPE(v) == &DBSequence_Type)
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000228#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000229
Jesus Ceaef9764f2008-05-13 18:45:46 +0000230#if (DBVER < 46)
231 #define _DBC_close(dbc) dbc->c_close(dbc)
232 #define _DBC_count(dbc,a,b) dbc->c_count(dbc,a,b)
233 #define _DBC_del(dbc,a) dbc->c_del(dbc,a)
234 #define _DBC_dup(dbc,a,b) dbc->c_dup(dbc,a,b)
235 #define _DBC_get(dbc,a,b,c) dbc->c_get(dbc,a,b,c)
236 #define _DBC_pget(dbc,a,b,c,d) dbc->c_pget(dbc,a,b,c,d)
237 #define _DBC_put(dbc,a,b,c) dbc->c_put(dbc,a,b,c)
238#else
239 #define _DBC_close(dbc) dbc->close(dbc)
240 #define _DBC_count(dbc,a,b) dbc->count(dbc,a,b)
241 #define _DBC_del(dbc,a) dbc->del(dbc,a)
242 #define _DBC_dup(dbc,a,b) dbc->dup(dbc,a,b)
243 #define _DBC_get(dbc,a,b,c) dbc->get(dbc,a,b,c)
244 #define _DBC_pget(dbc,a,b,c,d) dbc->pget(dbc,a,b,c,d)
245 #define _DBC_put(dbc,a,b,c) dbc->put(dbc,a,b,c)
246#endif
247
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000248
249/* --------------------------------------------------------------------- */
250/* Utility macros and functions */
251
Jesus Ceaef9764f2008-05-13 18:45:46 +0000252#define INSERT_IN_DOUBLE_LINKED_LIST(backlink,object) \
253 { \
254 object->sibling_next=backlink; \
255 object->sibling_prev_p=&(backlink); \
256 backlink=object; \
257 if (object->sibling_next) { \
258 object->sibling_next->sibling_prev_p=&(object->sibling_next); \
259 } \
260 }
261
262#define EXTRACT_FROM_DOUBLE_LINKED_LIST(object) \
263 { \
264 if (object->sibling_next) { \
265 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
266 } \
267 *(object->sibling_prev_p)=object->sibling_next; \
268 }
269
270#define EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(object) \
271 { \
272 if (object->sibling_next) { \
273 object->sibling_next->sibling_prev_p=object->sibling_prev_p; \
274 } \
275 if (object->sibling_prev_p) { \
276 *(object->sibling_prev_p)=object->sibling_next; \
277 } \
278 }
279
280#define INSERT_IN_DOUBLE_LINKED_LIST_TXN(backlink,object) \
281 { \
282 object->sibling_next_txn=backlink; \
283 object->sibling_prev_p_txn=&(backlink); \
284 backlink=object; \
285 if (object->sibling_next_txn) { \
286 object->sibling_next_txn->sibling_prev_p_txn= \
287 &(object->sibling_next_txn); \
288 } \
289 }
290
291#define EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(object) \
292 { \
293 if (object->sibling_next_txn) { \
294 object->sibling_next_txn->sibling_prev_p_txn= \
295 object->sibling_prev_p_txn; \
296 } \
297 *(object->sibling_prev_p_txn)=object->sibling_next_txn; \
298 }
299
300
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000301#define RETURN_IF_ERR() \
302 if (makeDBError(err)) { \
303 return NULL; \
304 }
305
306#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
307
Gregory P. Smithe2767172003-11-02 08:06:29 +0000308#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
309 if ((nonNull) == NULL) { \
310 PyObject *errTuple = NULL; \
311 errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
312 PyErr_SetObject((pyErrObj), errTuple); \
313 Py_DECREF(errTuple); \
314 return NULL; \
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000315 }
316
Gregory P. Smithe2767172003-11-02 08:06:29 +0000317#define CHECK_DB_NOT_CLOSED(dbobj) \
318 _CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
319
320#define CHECK_ENV_NOT_CLOSED(env) \
321 _CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000322
323#define CHECK_CURSOR_NOT_CLOSED(curs) \
Gregory P. Smithe2767172003-11-02 08:06:29 +0000324 _CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000325
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000326#if (DBVER >= 43)
327#define CHECK_SEQUENCE_NOT_CLOSED(curs) \
328 _CHECK_OBJECT_NOT_CLOSED(curs->sequence, DBError, DBSequence)
329#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000330
331#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
332 (((mydb)->myenvobj != NULL) && ((mydb)->myenvobj->flags & (flag))))
333
334#define CLEAR_DBT(dbt) (memset(&(dbt), 0, sizeof(dbt)))
335
336#define FREE_DBT(dbt) if ((dbt.flags & (DB_DBT_MALLOC|DB_DBT_REALLOC)) && \
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000337 dbt.data != NULL) { free(dbt.data); dbt.data = NULL; }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000338
339
340static int makeDBError(int err);
341
342
343/* Return the access method type of the DBObject */
344static int _DB_get_type(DBObject* self)
345{
346#if (DBVER >= 33)
347 DBTYPE type;
348 int err;
349 err = self->db->get_type(self->db, &type);
350 if (makeDBError(err)) {
351 return -1;
352 }
353 return type;
354#else
355 return self->db->get_type(self->db);
356#endif
357}
358
359
360/* Create a DBT structure (containing key and data values) from Python
361 strings. Returns 1 on success, 0 on an error. */
362static int make_dbt(PyObject* obj, DBT* dbt)
363{
364 CLEAR_DBT(*dbt);
365 if (obj == Py_None) {
366 /* no need to do anything, the structure has already been zeroed */
367 }
368 else if (!PyArg_Parse(obj, "s#", &dbt->data, &dbt->size)) {
369 PyErr_SetString(PyExc_TypeError,
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000370 "Data values must be of type string or None.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000371 return 0;
372 }
373 return 1;
374}
375
376
377/* Recno and Queue DBs can have integer keys. This function figures out
378 what's been given, verifies that it's allowed, and then makes the DBT.
379
Gregory P. Smithdc5af702004-06-27 23:32:34 +0000380 Caller MUST call FREE_DBT(key) when done. */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000381static int
382make_key_dbt(DBObject* self, PyObject* keyobj, DBT* key, int* pflags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000383{
384 db_recno_t recno;
385 int type;
386
387 CLEAR_DBT(*key);
Gustavo Niemeyerf073b752004-01-20 15:24:29 +0000388 if (keyobj == Py_None) {
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000389 type = _DB_get_type(self);
Gustavo Niemeyer8974f722004-01-20 15:20:03 +0000390 if (type == -1)
391 return 0;
Gustavo Niemeyer024f2de2004-01-20 15:14:55 +0000392 if (type == DB_RECNO || type == DB_QUEUE) {
393 PyErr_SetString(
394 PyExc_TypeError,
395 "None keys not allowed for Recno and Queue DB's");
396 return 0;
397 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000398 /* no need to do anything, the structure has already been zeroed */
399 }
400
401 else if (PyString_Check(keyobj)) {
402 /* verify access method type */
403 type = _DB_get_type(self);
404 if (type == -1)
405 return 0;
406 if (type == DB_RECNO || type == DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000407 PyErr_SetString(
408 PyExc_TypeError,
409 "String keys not allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000410 return 0;
411 }
412
Gregory P. Smith10bed542007-10-09 06:50:43 +0000413 /*
414 * NOTE(gps): I don't like doing a data copy here, it seems
415 * wasteful. But without a clean way to tell FREE_DBT if it
416 * should free key->data or not we have to. Other places in
417 * the code check for DB_THREAD and forceably set DBT_MALLOC
418 * when we otherwise would leave flags 0 to indicate that.
419 */
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000420 key->data = malloc(PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000421 if (key->data == NULL) {
422 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
423 return 0;
424 }
Gregory P. Smithaae141a2007-11-01 21:08:14 +0000425 memcpy(key->data, PyString_AS_STRING(keyobj),
426 PyString_GET_SIZE(keyobj));
Gregory P. Smith10bed542007-10-09 06:50:43 +0000427 key->flags = DB_DBT_REALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000428 key->size = PyString_GET_SIZE(keyobj);
429 }
430
431 else if (PyInt_Check(keyobj)) {
432 /* verify access method type */
433 type = _DB_get_type(self);
434 if (type == -1)
435 return 0;
436 if (type == DB_BTREE && pflags != NULL) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000437 /* if BTREE then an Integer key is allowed with the
438 * DB_SET_RECNO flag */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000439 *pflags |= DB_SET_RECNO;
440 }
441 else if (type != DB_RECNO && type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000442 PyErr_SetString(
443 PyExc_TypeError,
444 "Integer keys only allowed for Recno and Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000445 return 0;
446 }
447
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000448 /* Make a key out of the requested recno, use allocated space so DB
449 * will be able to realloc room for the real key if needed. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000450 recno = PyInt_AS_LONG(keyobj);
451 key->data = malloc(sizeof(db_recno_t));
452 if (key->data == NULL) {
453 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
454 return 0;
455 }
456 key->ulen = key->size = sizeof(db_recno_t);
457 memcpy(key->data, &recno, sizeof(db_recno_t));
458 key->flags = DB_DBT_REALLOC;
459 }
460 else {
461 PyErr_Format(PyExc_TypeError,
462 "String or Integer object expected for key, %s found",
Christian Heimese93237d2007-12-19 02:37:44 +0000463 Py_TYPE(keyobj)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000464 return 0;
465 }
466
467 return 1;
468}
469
470
471/* Add partial record access to an existing DBT data struct.
472 If dlen and doff are set, then the DB_DBT_PARTIAL flag will be set
473 and the data storage/retrieval will be done using dlen and doff. */
474static int add_partial_dbt(DBT* d, int dlen, int doff) {
475 /* if neither were set we do nothing (-1 is the default value) */
476 if ((dlen == -1) && (doff == -1)) {
477 return 1;
478 }
479
480 if ((dlen < 0) || (doff < 0)) {
481 PyErr_SetString(PyExc_TypeError, "dlen and doff must both be >= 0");
482 return 0;
483 }
484
485 d->flags = d->flags | DB_DBT_PARTIAL;
486 d->dlen = (unsigned int) dlen;
487 d->doff = (unsigned int) doff;
488 return 1;
489}
490
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000491/* a safe strcpy() without the zeroing behaviour and semantics of strncpy. */
492/* TODO: make this use the native libc strlcpy() when available (BSD) */
493unsigned int our_strlcpy(char* dest, const char* src, unsigned int n)
494{
495 unsigned int srclen, copylen;
496
497 srclen = strlen(src);
498 if (n <= 0)
499 return srclen;
500 copylen = (srclen > n-1) ? n-1 : srclen;
501 /* populate dest[0] thru dest[copylen-1] */
502 memcpy(dest, src, copylen);
503 /* guarantee null termination */
504 dest[copylen] = 0;
505
506 return srclen;
507}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000508
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000509/* Callback used to save away more information about errors from the DB
510 * library. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000511static char _db_errmsg[1024];
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000512#if (DBVER <= 42)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000513static void _db_errorCallback(const char* prefix, char* msg)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000514#else
515static void _db_errorCallback(const DB_ENV *db_env,
516 const char* prefix, const char* msg)
517#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000518{
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000519 our_strlcpy(_db_errmsg, msg, sizeof(_db_errmsg));
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000520}
521
522
Jesus Ceaef9764f2008-05-13 18:45:46 +0000523/*
524** We need these functions because some results
525** are undefined if pointer is NULL. Some other
526** give None instead of "".
527**
528** This functions are static and will be
529** -I hope- inlined.
530*/
531static const char *DummyString = "This string is a simple placeholder";
532static PyObject *Build_PyString(const char *p,int s)
533{
534 if (!p) {
535 p=DummyString;
536 assert(s==0);
537 }
538 return PyString_FromStringAndSize(p,s);
539}
540
541static PyObject *BuildValue_S(const void *p,int s)
542{
543 if (!p) {
544 p=DummyString;
545 assert(s==0);
546 }
547 return Py_BuildValue("s#",p,s);
548}
549
550static PyObject *BuildValue_SS(const void *p1,int s1,const void *p2,int s2)
551{
552 if (!p1) {
553 p1=DummyString;
554 assert(s1==0);
555 }
556 if (!p2) {
557 p2=DummyString;
558 assert(s2==0);
559 }
560 return Py_BuildValue("s#s#",p1,s1,p2,s2);
561}
562
563static PyObject *BuildValue_IS(int i,const void *p,int s)
564{
565 if (!p) {
566 p=DummyString;
567 assert(s==0);
568 }
569 return Py_BuildValue("is#",i,p,s);
570}
571
572static PyObject *BuildValue_LS(long i,const void *p,int s)
573{
574 if (!p) {
575 p=DummyString;
576 assert(s==0);
577 }
578 return Py_BuildValue("ls#",i,p,s);
579}
580
581
582
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000583/* make a nice exception object to raise for errors. */
584static int makeDBError(int err)
585{
586 char errTxt[2048]; /* really big, just in case... */
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000587 PyObject *errObj = NULL;
588 PyObject *errTuple = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000589 int exceptionRaised = 0;
Neal Norwitzdce937f2006-07-23 08:01:43 +0000590 unsigned int bytes_left;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000591
592 switch (err) {
593 case 0: /* successful, no error */ break;
594
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000595#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000596 case DB_INCOMPLETE:
597#if INCOMPLETE_IS_WARNING
Neal Norwitzdce937f2006-07-23 08:01:43 +0000598 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
599 /* Ensure that bytes_left never goes negative */
600 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
601 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
602 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000603 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000604 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000605 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000606 _db_errmsg[0] = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000607 exceptionRaised = PyErr_Warn(PyExc_RuntimeWarning, errTxt);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000608
609#else /* do an exception instead */
610 errObj = DBIncompleteError;
611#endif
612 break;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000613#endif /* DBVER < 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000614
615 case DB_KEYEMPTY: errObj = DBKeyEmptyError; break;
616 case DB_KEYEXIST: errObj = DBKeyExistError; break;
617 case DB_LOCK_DEADLOCK: errObj = DBLockDeadlockError; break;
618 case DB_LOCK_NOTGRANTED: errObj = DBLockNotGrantedError; break;
619 case DB_NOTFOUND: errObj = DBNotFoundError; break;
620 case DB_OLD_VERSION: errObj = DBOldVersionError; break;
621 case DB_RUNRECOVERY: errObj = DBRunRecoveryError; break;
622 case DB_VERIFY_BAD: errObj = DBVerifyBadError; break;
623 case DB_NOSERVER: errObj = DBNoServerError; break;
624 case DB_NOSERVER_HOME: errObj = DBNoServerHomeError; break;
625 case DB_NOSERVER_ID: errObj = DBNoServerIDError; break;
626#if (DBVER >= 33)
627 case DB_PAGE_NOTFOUND: errObj = DBPageNotFoundError; break;
628 case DB_SECONDARY_BAD: errObj = DBSecondaryBadError; break;
629#endif
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000630 case DB_BUFFER_SMALL: errObj = DBNoMemoryError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000631
Gregory P. Smith8b7e9172004-12-13 09:51:23 +0000632#if (DBVER >= 43)
633 /* ENOMEM and DB_BUFFER_SMALL were one and the same until 4.3 */
634 case ENOMEM: errObj = PyExc_MemoryError; break;
635#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000636 case EINVAL: errObj = DBInvalidArgError; break;
637 case EACCES: errObj = DBAccessError; break;
638 case ENOSPC: errObj = DBNoSpaceError; break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000639 case EAGAIN: errObj = DBAgainError; break;
640 case EBUSY : errObj = DBBusyError; break;
641 case EEXIST: errObj = DBFileExistsError; break;
642 case ENOENT: errObj = DBNoSuchFileError; break;
643 case EPERM : errObj = DBPermissionsError; break;
644
Jesus Ceaef9764f2008-05-13 18:45:46 +0000645#if (DBVER >= 42)
646 case DB_REP_HANDLE_DEAD : errObj = DBRepHandleDeadError; break;
647#endif
648
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000649 default: errObj = DBError; break;
650 }
651
652 if (errObj != NULL) {
Neal Norwitzdce937f2006-07-23 08:01:43 +0000653 bytes_left = our_strlcpy(errTxt, db_strerror(err), sizeof(errTxt));
654 /* Ensure that bytes_left never goes negative */
655 if (_db_errmsg[0] && bytes_left < (sizeof(errTxt) - 4)) {
656 bytes_left = sizeof(errTxt) - bytes_left - 4 - 1;
657 assert(bytes_left >= 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000658 strcat(errTxt, " -- ");
Neal Norwitzdce937f2006-07-23 08:01:43 +0000659 strncat(errTxt, _db_errmsg, bytes_left);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000660 }
Neal Norwitzdce937f2006-07-23 08:01:43 +0000661 _db_errmsg[0] = 0;
Barry Warsaw9a0d7792002-12-30 20:53:52 +0000662
663 errTuple = Py_BuildValue("(is)", err, errTxt);
664 PyErr_SetObject(errObj, errTuple);
665 Py_DECREF(errTuple);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000666 }
667
668 return ((errObj != NULL) || exceptionRaised);
669}
670
671
672
673/* set a type exception */
674static void makeTypeError(char* expected, PyObject* found)
675{
676 PyErr_Format(PyExc_TypeError, "Expected %s argument, %s found.",
Christian Heimese93237d2007-12-19 02:37:44 +0000677 expected, Py_TYPE(found)->tp_name);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000678}
679
680
681/* verify that an obj is either None or a DBTxn, and set the txn pointer */
682static int checkTxnObj(PyObject* txnobj, DB_TXN** txn)
683{
684 if (txnobj == Py_None || txnobj == NULL) {
685 *txn = NULL;
686 return 1;
687 }
688 if (DBTxnObject_Check(txnobj)) {
689 *txn = ((DBTxnObject*)txnobj)->txn;
690 return 1;
691 }
692 else
693 makeTypeError("DBTxn", txnobj);
694 return 0;
695}
696
697
698/* Delete a key from a database
699 Returns 0 on success, -1 on an error. */
700static int _DB_delete(DBObject* self, DB_TXN *txn, DBT *key, int flags)
701{
702 int err;
703
704 MYDB_BEGIN_ALLOW_THREADS;
705 err = self->db->del(self->db, txn, key, 0);
706 MYDB_END_ALLOW_THREADS;
707 if (makeDBError(err)) {
708 return -1;
709 }
710 self->haveStat = 0;
711 return 0;
712}
713
714
715/* Store a key into a database
716 Returns 0 on success, -1 on an error. */
717static int _DB_put(DBObject* self, DB_TXN *txn, DBT *key, DBT *data, int flags)
718{
719 int err;
720
721 MYDB_BEGIN_ALLOW_THREADS;
722 err = self->db->put(self->db, txn, key, data, flags);
723 MYDB_END_ALLOW_THREADS;
724 if (makeDBError(err)) {
725 return -1;
726 }
727 self->haveStat = 0;
728 return 0;
729}
730
731/* Get a key/data pair from a cursor */
732static PyObject* _DBCursor_get(DBCursorObject* self, int extra_flags,
733 PyObject *args, PyObject *kwargs, char *format)
734{
735 int err;
736 PyObject* retval = NULL;
737 DBT key, data;
738 int dlen = -1;
739 int doff = -1;
740 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +0000741 static char* kwnames[] = { "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000742
743 if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwnames,
744 &flags, &dlen, &doff))
745 return NULL;
746
747 CHECK_CURSOR_NOT_CLOSED(self);
748
749 flags |= extra_flags;
750 CLEAR_DBT(key);
751 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000752 if (!add_partial_dbt(&data, dlen, doff))
753 return NULL;
754
755 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000756 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000757 MYDB_END_ALLOW_THREADS;
758
Gregory P. Smithe9477062005-06-04 06:46:59 +0000759 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
760 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000761 Py_INCREF(Py_None);
762 retval = Py_None;
763 }
764 else if (makeDBError(err)) {
765 retval = NULL;
766 }
767 else { /* otherwise, success! */
768
769 /* if Recno or Queue, return the key as an Int */
770 switch (_DB_get_type(self->mydb)) {
771 case -1:
772 retval = NULL;
773 break;
774
775 case DB_RECNO:
776 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000777 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000778 break;
779 case DB_HASH:
780 case DB_BTREE:
781 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +0000782 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000783 break;
784 }
785 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000786 return retval;
787}
788
789
790/* add an integer to a dictionary using the given name as a key */
791static void _addIntToDict(PyObject* dict, char *name, int value)
792{
793 PyObject* v = PyInt_FromLong((long) value);
794 if (!v || PyDict_SetItemString(dict, name, v))
795 PyErr_Clear();
796
797 Py_XDECREF(v);
798}
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000799
800/* The same, when the value is a time_t */
801static void _addTimeTToDict(PyObject* dict, char *name, time_t value)
802{
803 PyObject* v;
804 /* if the value fits in regular int, use that. */
Jesus Ceaef9764f2008-05-13 18:45:46 +0000805#ifdef PY_LONG_LONG
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +0000806 if (sizeof(time_t) > sizeof(long))
807 v = PyLong_FromLongLong((PY_LONG_LONG) value);
808 else
809#endif
810 v = PyInt_FromLong((long) value);
811 if (!v || PyDict_SetItemString(dict, name, v))
812 PyErr_Clear();
813
814 Py_XDECREF(v);
815}
816
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000817#if (DBVER >= 43)
818/* add an db_seq_t to a dictionary using the given name as a key */
819static void _addDb_seq_tToDict(PyObject* dict, char *name, db_seq_t value)
820{
821 PyObject* v = PyLong_FromLongLong(value);
822 if (!v || PyDict_SetItemString(dict, name, v))
823 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000824
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000825 Py_XDECREF(v);
826}
827#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000828
Jesus Ceaef9764f2008-05-13 18:45:46 +0000829#if (DBVER >= 40)
830static void _addDB_lsnToDict(PyObject* dict, char *name, DB_LSN value)
831{
832 PyObject *v = Py_BuildValue("(ll)",value.file,value.offset);
833 if (!v || PyDict_SetItemString(dict, name, v))
834 PyErr_Clear();
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000835
Jesus Ceaef9764f2008-05-13 18:45:46 +0000836 Py_XDECREF(v);
837}
838#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000839
840/* --------------------------------------------------------------------- */
841/* Allocators and deallocators */
842
843static DBObject*
844newDBObject(DBEnvObject* arg, int flags)
845{
846 DBObject* self;
847 DB_ENV* db_env = NULL;
848 int err;
849
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000850 self = PyObject_New(DBObject, &DB_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000851 if (self == NULL)
852 return NULL;
853
854 self->haveStat = 0;
855 self->flags = 0;
856 self->setflags = 0;
857 self->myenvobj = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000858 self->children_cursors = NULL;
859#if (DBVER >=43)
860 self->children_sequences = NULL;
861#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000862#if (DBVER >= 33)
863 self->associateCallback = NULL;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000864 self->btCompareCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000865 self->primaryDBType = 0;
866#endif
Gregory P. Smith31c50652004-06-28 01:20:40 +0000867 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000868
869 /* keep a reference to our python DBEnv object */
870 if (arg) {
871 Py_INCREF(arg);
872 self->myenvobj = arg;
873 db_env = arg->db_env;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000874 INSERT_IN_DOUBLE_LINKED_LIST(self->myenvobj->children_dbs,self);
875 } else {
876 self->sibling_prev_p=NULL;
877 self->sibling_next=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000878 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000879 self->txn=NULL;
880 self->sibling_prev_p_txn=NULL;
881 self->sibling_next_txn=NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000882
883 if (self->myenvobj)
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000884 self->moduleFlags = self->myenvobj->moduleFlags;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000885 else
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000886 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
887 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000888
889 MYDB_BEGIN_ALLOW_THREADS;
890 err = db_create(&self->db, db_env, flags);
Neal Norwitzdce937f2006-07-23 08:01:43 +0000891 if (self->db != NULL) {
892 self->db->set_errcall(self->db, _db_errorCallback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000893#if (DBVER >= 33)
Neal Norwitzdce937f2006-07-23 08:01:43 +0000894 self->db->app_private = (void*)self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000895#endif
Neal Norwitzdce937f2006-07-23 08:01:43 +0000896 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000897 MYDB_END_ALLOW_THREADS;
Gregory P. Smith31c50652004-06-28 01:20:40 +0000898 /* TODO add a weakref(self) to the self->myenvobj->open_child_weakrefs
899 * list so that a DBEnv can refuse to close without aborting any open
Gregory P. Smithf0547d02006-06-05 17:38:04 +0000900 * DBTxns and closing any open DBs first. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000901 if (makeDBError(err)) {
902 if (self->myenvobj) {
903 Py_DECREF(self->myenvobj);
904 self->myenvobj = NULL;
905 }
Gregory P. Smith664782e2008-05-17 06:12:02 +0000906 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000907 self = NULL;
908 }
909 return self;
910}
911
912
Jesus Ceaef9764f2008-05-13 18:45:46 +0000913/* Forward declaration */
914static PyObject *DB_close_internal(DBObject* self, int flags);
915
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000916static void
917DB_dealloc(DBObject* self)
918{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000919 PyObject *dummy;
920
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000921 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +0000922 dummy=DB_close_internal(self,0);
923 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000924 }
Gregory P. Smith31c50652004-06-28 01:20:40 +0000925 if (self->in_weakreflist != NULL) {
926 PyObject_ClearWeakRefs((PyObject *) self);
927 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000928 if (self->myenvobj) {
929 Py_DECREF(self->myenvobj);
930 self->myenvobj = NULL;
931 }
932#if (DBVER >= 33)
933 if (self->associateCallback != NULL) {
934 Py_DECREF(self->associateCallback);
935 self->associateCallback = NULL;
936 }
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +0000937 if (self->btCompareCallback != NULL) {
938 Py_DECREF(self->btCompareCallback);
939 self->btCompareCallback = NULL;
940 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000941#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000942 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000943}
944
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000945static DBCursorObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +0000946newDBCursorObject(DBC* dbc, DBTxnObject *txn, DBObject* db)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000947{
Neal Norwitzb4a55812004-07-09 23:30:57 +0000948 DBCursorObject* self = PyObject_New(DBCursorObject, &DBCursor_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000949 if (self == NULL)
950 return NULL;
951
952 self->dbc = dbc;
953 self->mydb = db;
Jesus Ceaef9764f2008-05-13 18:45:46 +0000954
955 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_cursors,self);
956 if (txn && ((PyObject *)txn!=Py_None)) {
957 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->children_cursors,self);
958 self->txn=txn;
959 } else {
960 self->txn=NULL;
961 }
962
Gregory P. Smitha703a212003-11-03 01:04:41 +0000963 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000964 Py_INCREF(self->mydb);
965 return self;
966}
967
968
Jesus Ceaef9764f2008-05-13 18:45:46 +0000969/* Forward declaration */
970static PyObject *DBC_close_internal(DBCursorObject* self);
971
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000972static void
973DBCursor_dealloc(DBCursorObject* self)
974{
Jesus Ceaef9764f2008-05-13 18:45:46 +0000975 PyObject *dummy;
Gregory P. Smitha703a212003-11-03 01:04:41 +0000976
Jesus Ceaef9764f2008-05-13 18:45:46 +0000977 if (self->dbc != NULL) {
978 dummy=DBC_close_internal(self);
979 Py_XDECREF(dummy);
980 }
Gregory P. Smitha703a212003-11-03 01:04:41 +0000981 if (self->in_weakreflist != NULL) {
982 PyObject_ClearWeakRefs((PyObject *) self);
983 }
Jesus Ceaef9764f2008-05-13 18:45:46 +0000984 Py_DECREF(self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000985 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000986}
987
988
989static DBEnvObject*
990newDBEnvObject(int flags)
991{
992 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +0000993 DBEnvObject* self = PyObject_New(DBEnvObject, &DBEnv_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +0000994 if (self == NULL)
995 return NULL;
996
997 self->closed = 1;
998 self->flags = flags;
Gregory P. Smith455d46f2003-07-09 04:45:59 +0000999 self->moduleFlags.getReturnsNone = DEFAULT_GET_RETURNS_NONE;
1000 self->moduleFlags.cursorSetReturnsNone = DEFAULT_CURSOR_SET_RETURNS_NONE;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001001 self->children_dbs = NULL;
1002 self->children_txns = NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001003 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001004
Jesus Ceaef9764f2008-05-13 18:45:46 +00001005#if (DBVER >= 40)
1006 self->event_notifyCallback = NULL;
1007#endif
1008
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001009 MYDB_BEGIN_ALLOW_THREADS;
1010 err = db_env_create(&self->db_env, flags);
1011 MYDB_END_ALLOW_THREADS;
1012 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001013 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001014 self = NULL;
1015 }
1016 else {
1017 self->db_env->set_errcall(self->db_env, _db_errorCallback);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001018 self->db_env->app_private=self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001019 }
1020 return self;
1021}
1022
Jesus Ceaef9764f2008-05-13 18:45:46 +00001023/* Forward declaration */
1024static PyObject *DBEnv_close_internal(DBEnvObject* self, int flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001025
1026static void
1027DBEnv_dealloc(DBEnvObject* self)
1028{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001029 PyObject *dummy;
1030
1031 if (self->db_env && !self->closed) {
1032 dummy=DBEnv_close_internal(self,0);
1033 Py_XDECREF(dummy);
1034 }
1035
1036#if (DBVER >= 40)
1037 Py_XDECREF(self->event_notifyCallback);
1038 self->event_notifyCallback = NULL;
1039#endif
1040
Gregory P. Smith31c50652004-06-28 01:20:40 +00001041 if (self->in_weakreflist != NULL) {
1042 PyObject_ClearWeakRefs((PyObject *) self);
1043 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001044
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001045 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001046}
1047
1048
1049static DBTxnObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001050newDBTxnObject(DBEnvObject* myenv, DBTxnObject *parent, DB_TXN *txn, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001051{
1052 int err;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001053 DB_TXN *parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001054
Neal Norwitzb4a55812004-07-09 23:30:57 +00001055 DBTxnObject* self = PyObject_New(DBTxnObject, &DBTxn_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001056 if (self == NULL)
1057 return NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001058
Gregory P. Smith31c50652004-06-28 01:20:40 +00001059 self->in_weakreflist = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001060 self->children_txns = NULL;
1061 self->children_dbs = NULL;
1062 self->children_cursors = NULL;
1063 self->children_sequences = NULL;
1064 self->flag_prepare = 0;
1065 self->parent_txn = NULL;
1066 self->env = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001067
Jesus Ceaef9764f2008-05-13 18:45:46 +00001068 if (parent && ((PyObject *)parent!=Py_None)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001069 parent_txn = parent->txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001070 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00001071
1072 if (txn) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001073 self->txn = txn;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001074 } else {
1075 MYDB_BEGIN_ALLOW_THREADS;
1076#if (DBVER >= 40)
1077 err = myenv->db_env->txn_begin(myenv->db_env, parent_txn, &(self->txn), flags);
1078#else
1079 err = txn_begin(myenv->db_env, parent->txn, &(self_txn), flags);
1080#endif
1081 MYDB_END_ALLOW_THREADS;
1082
1083 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001084 Py_DECREF(self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001085 return NULL;
1086 }
1087 }
1088
Gregory P. Smith664782e2008-05-17 06:12:02 +00001089 /* Can't use 'parent' because could be 'parent==Py_None' */
1090 if (parent_txn) {
1091 self->parent_txn = parent;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001092 Py_INCREF(parent);
1093 self->env = NULL;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001094 INSERT_IN_DOUBLE_LINKED_LIST(parent->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001095 } else {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001096 self->parent_txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001097 Py_INCREF(myenv);
1098 self->env = myenv;
Gregory P. Smith664782e2008-05-17 06:12:02 +00001099 INSERT_IN_DOUBLE_LINKED_LIST(myenv->children_txns, self);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001100 }
1101
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001102 return self;
1103}
1104
Jesus Ceaef9764f2008-05-13 18:45:46 +00001105/* Forward declaration */
1106static PyObject *
1107DBTxn_abort_discard_internal(DBTxnObject* self, int discard);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001108
1109static void
1110DBTxn_dealloc(DBTxnObject* self)
1111{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001112 PyObject *dummy;
1113
1114 if (self->txn) {
1115 int flag_prepare = self->flag_prepare;
1116 dummy=DBTxn_abort_discard_internal(self,0);
1117 Py_XDECREF(dummy);
1118 if (!flag_prepare) {
1119 PyErr_Warn(PyExc_RuntimeWarning,
1120 "DBTxn aborted in destructor. No prior commit() or abort().");
1121 }
1122 }
1123
Gregory P. Smith31c50652004-06-28 01:20:40 +00001124 if (self->in_weakreflist != NULL) {
1125 PyObject_ClearWeakRefs((PyObject *) self);
1126 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001127
Jesus Ceaef9764f2008-05-13 18:45:46 +00001128 if (self->env) {
1129 Py_DECREF(self->env);
1130 } else {
1131 Py_DECREF(self->parent_txn);
Gregory P. Smith31c50652004-06-28 01:20:40 +00001132 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001133 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001134}
1135
1136
1137static DBLockObject*
1138newDBLockObject(DBEnvObject* myenv, u_int32_t locker, DBT* obj,
1139 db_lockmode_t lock_mode, int flags)
1140{
1141 int err;
Neal Norwitzb4a55812004-07-09 23:30:57 +00001142 DBLockObject* self = PyObject_New(DBLockObject, &DBLock_Type);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001143 if (self == NULL)
1144 return NULL;
Gregory P. Smith31c50652004-06-28 01:20:40 +00001145 self->in_weakreflist = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001146
1147 MYDB_BEGIN_ALLOW_THREADS;
1148#if (DBVER >= 40)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001149 err = myenv->db_env->lock_get(myenv->db_env, locker, flags, obj, lock_mode,
1150 &self->lock);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001151#else
1152 err = lock_get(myenv->db_env, locker, flags, obj, lock_mode, &self->lock);
1153#endif
1154 MYDB_END_ALLOW_THREADS;
1155 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001156 Py_DECREF(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001157 self = NULL;
1158 }
1159
1160 return self;
1161}
1162
1163
1164static void
1165DBLock_dealloc(DBLockObject* self)
1166{
Gregory P. Smith31c50652004-06-28 01:20:40 +00001167 if (self->in_weakreflist != NULL) {
1168 PyObject_ClearWeakRefs((PyObject *) self);
1169 }
Gregory P. Smith31c50652004-06-28 01:20:40 +00001170 /* TODO: is this lock held? should we release it? */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001171
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001172 PyObject_Del(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001173}
1174
1175
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001176#if (DBVER >= 43)
1177static DBSequenceObject*
1178newDBSequenceObject(DBObject* mydb, int flags)
1179{
1180 int err;
1181 DBSequenceObject* self = PyObject_New(DBSequenceObject, &DBSequence_Type);
1182 if (self == NULL)
1183 return NULL;
1184 Py_INCREF(mydb);
1185 self->mydb = mydb;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001186
Jesus Ceaef9764f2008-05-13 18:45:46 +00001187 INSERT_IN_DOUBLE_LINKED_LIST(self->mydb->children_sequences,self);
Gregory P. Smith664782e2008-05-17 06:12:02 +00001188 self->txn = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001189
1190 self->in_weakreflist = NULL;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001191
1192 MYDB_BEGIN_ALLOW_THREADS;
1193 err = db_sequence_create(&self->sequence, self->mydb->db, flags);
1194 MYDB_END_ALLOW_THREADS;
1195 if (makeDBError(err)) {
Gregory P. Smith664782e2008-05-17 06:12:02 +00001196 Py_DECREF(self);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001197 self = NULL;
1198 }
1199
1200 return self;
1201}
1202
Jesus Ceaef9764f2008-05-13 18:45:46 +00001203/* Forward declaration */
1204static PyObject
1205*DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001206
1207static void
1208DBSequence_dealloc(DBSequenceObject* self)
1209{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001210 PyObject *dummy;
1211
1212 if (self->sequence != NULL) {
1213 dummy=DBSequence_close_internal(self,0,0);
1214 Py_XDECREF(dummy);
1215 }
1216
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001217 if (self->in_weakreflist != NULL) {
1218 PyObject_ClearWeakRefs((PyObject *) self);
1219 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00001220
1221 Py_DECREF(self->mydb);
1222 PyObject_Del(self);
1223}
1224#endif
1225
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001226/* --------------------------------------------------------------------- */
1227/* DB methods */
1228
1229static PyObject*
1230DB_append(DBObject* self, PyObject* args)
1231{
1232 PyObject* txnobj = NULL;
1233 PyObject* dataobj;
1234 db_recno_t recno;
1235 DBT key, data;
1236 DB_TXN *txn = NULL;
1237
Georg Brandl96a8c392006-05-29 21:04:52 +00001238 if (!PyArg_UnpackTuple(args, "append", 1, 2, &dataobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001239 return NULL;
1240
1241 CHECK_DB_NOT_CLOSED(self);
1242
1243 /* make a dummy key out of a recno */
1244 recno = 0;
1245 CLEAR_DBT(key);
1246 key.data = &recno;
1247 key.size = sizeof(recno);
1248 key.ulen = key.size;
1249 key.flags = DB_DBT_USERMEM;
1250
1251 if (!make_dbt(dataobj, &data)) return NULL;
1252 if (!checkTxnObj(txnobj, &txn)) return NULL;
1253
1254 if (-1 == _DB_put(self, txn, &key, &data, DB_APPEND))
1255 return NULL;
1256
1257 return PyInt_FromLong(recno);
1258}
1259
1260
1261#if (DBVER >= 33)
1262
1263static int
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001264_db_associateCallback(DB* db, const DBT* priKey, const DBT* priData,
1265 DBT* secKey)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001266{
1267 int retval = DB_DONOTINDEX;
1268 DBObject* secondaryDB = (DBObject*)db->app_private;
1269 PyObject* callback = secondaryDB->associateCallback;
1270 int type = secondaryDB->primaryDBType;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001271 PyObject* args;
Thomas Wouters89ba3812006-03-07 14:14:51 +00001272 PyObject* result = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001273
1274
1275 if (callback != NULL) {
1276 MYDB_BEGIN_BLOCK_THREADS;
1277
Thomas Woutersb3153832006-03-08 01:47:19 +00001278 if (type == DB_RECNO || type == DB_QUEUE)
Jesus Ceaef9764f2008-05-13 18:45:46 +00001279 args = BuildValue_LS(*((db_recno_t*)priKey->data), priData->data, priData->size);
Thomas Woutersb3153832006-03-08 01:47:19 +00001280 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001281 args = BuildValue_SS(priKey->data, priKey->size, priData->data, priData->size);
Thomas Wouters098f6942006-03-07 14:13:17 +00001282 if (args != NULL) {
Thomas Wouters098f6942006-03-07 14:13:17 +00001283 result = PyEval_CallObject(callback, args);
1284 }
1285 if (args == NULL || result == NULL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001286 PyErr_Print();
1287 }
1288 else if (result == Py_None) {
1289 retval = DB_DONOTINDEX;
1290 }
1291 else if (PyInt_Check(result)) {
1292 retval = PyInt_AsLong(result);
1293 }
1294 else if (PyString_Check(result)) {
1295 char* data;
Martin v. Löwis18e16552006-02-15 17:27:45 +00001296 Py_ssize_t size;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001297
1298 CLEAR_DBT(*secKey);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001299 PyString_AsStringAndSize(result, &data, &size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001300 secKey->flags = DB_DBT_APPMALLOC; /* DB will free */
1301 secKey->data = malloc(size); /* TODO, check this */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001302 if (secKey->data) {
1303 memcpy(secKey->data, data, size);
1304 secKey->size = size;
1305 retval = 0;
1306 }
1307 else {
1308 PyErr_SetString(PyExc_MemoryError,
1309 "malloc failed in _db_associateCallback");
1310 PyErr_Print();
1311 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001312 }
1313 else {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001314 PyErr_SetString(
1315 PyExc_TypeError,
1316 "DB associate callback should return DB_DONOTINDEX or string.");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001317 PyErr_Print();
1318 }
1319
Thomas Woutersb3153832006-03-08 01:47:19 +00001320 Py_XDECREF(args);
1321 Py_XDECREF(result);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001322
1323 MYDB_END_BLOCK_THREADS;
1324 }
1325 return retval;
1326}
1327
1328
1329static PyObject*
1330DB_associate(DBObject* self, PyObject* args, PyObject* kwargs)
1331{
1332 int err, flags=0;
1333 DBObject* secondaryDB;
1334 PyObject* callback;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001335#if (DBVER >= 41)
1336 PyObject *txnobj = NULL;
1337 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001338 static char* kwnames[] = {"secondaryDB", "callback", "flags", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001339 NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001340#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001341 static char* kwnames[] = {"secondaryDB", "callback", "flags", NULL};
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001342#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001343
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001344#if (DBVER >= 41)
1345 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iO:associate", kwnames,
1346 &secondaryDB, &callback, &flags,
1347 &txnobj)) {
1348#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001349 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:associate", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001350 &secondaryDB, &callback, &flags)) {
1351#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001352 return NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001353 }
1354
1355#if (DBVER >= 41)
1356 if (!checkTxnObj(txnobj, &txn)) return NULL;
1357#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001358
1359 CHECK_DB_NOT_CLOSED(self);
1360 if (!DBObject_Check(secondaryDB)) {
1361 makeTypeError("DB", (PyObject*)secondaryDB);
1362 return NULL;
1363 }
Gregory P. Smith91116b62005-06-06 10:28:06 +00001364 CHECK_DB_NOT_CLOSED(secondaryDB);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001365 if (callback == Py_None) {
1366 callback = NULL;
1367 }
1368 else if (!PyCallable_Check(callback)) {
1369 makeTypeError("Callable", callback);
1370 return NULL;
1371 }
1372
1373 /* Save a reference to the callback in the secondary DB. */
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001374 Py_XDECREF(secondaryDB->associateCallback);
Thomas Woutersb3153832006-03-08 01:47:19 +00001375 Py_XINCREF(callback);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001376 secondaryDB->associateCallback = callback;
1377 secondaryDB->primaryDBType = _DB_get_type(self);
1378
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001379 /* PyEval_InitThreads is called here due to a quirk in python 1.5
1380 * - 2.2.1 (at least) according to Russell Williamson <merel@wt.net>:
1381 * The global interepreter lock is not initialized until the first
1382 * thread is created using thread.start_new_thread() or fork() is
1383 * called. that would cause the ALLOW_THREADS here to segfault due
1384 * to a null pointer reference if no threads or child processes
1385 * have been created. This works around that and is a no-op if
1386 * threads have already been initialized.
1387 * (see pybsddb-users mailing list post on 2002-08-07)
1388 */
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001389#ifdef WITH_THREAD
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00001390 PyEval_InitThreads();
Gregory P. Smithaa71f5f2003-01-17 07:56:16 +00001391#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001392 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001393#if (DBVER >= 41)
1394 err = self->db->associate(self->db,
1395 txn,
1396 secondaryDB->db,
1397 _db_associateCallback,
1398 flags);
1399#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001400 err = self->db->associate(self->db,
1401 secondaryDB->db,
1402 _db_associateCallback,
1403 flags);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001404#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001405 MYDB_END_ALLOW_THREADS;
1406
1407 if (err) {
Gregory P. Smith692ca9a2005-06-06 09:55:06 +00001408 Py_XDECREF(secondaryDB->associateCallback);
1409 secondaryDB->associateCallback = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001410 secondaryDB->primaryDBType = 0;
1411 }
1412
1413 RETURN_IF_ERR();
1414 RETURN_NONE();
1415}
1416
1417
1418#endif
1419
1420
1421static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00001422DB_close_internal(DBObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001423{
Jesus Ceaef9764f2008-05-13 18:45:46 +00001424 PyObject *dummy;
1425 int err;
1426
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001427 if (self->db != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001428 /* Can be NULL if db is not in an environment */
1429 EXTRACT_FROM_DOUBLE_LINKED_LIST_MAYBE_NULL(self);
1430 if (self->txn) {
1431 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
1432 self->txn=NULL;
1433 }
1434
1435 while(self->children_cursors) {
1436 dummy=DBC_close_internal(self->children_cursors);
1437 Py_XDECREF(dummy);
1438 }
1439
1440#if (DBVER >= 43)
1441 while(self->children_sequences) {
1442 dummy=DBSequence_close_internal(self->children_sequences,0,0);
1443 Py_XDECREF(dummy);
1444 }
1445#endif
1446
1447 MYDB_BEGIN_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001448 err = self->db->close(self->db, flags);
Jesus Ceaef9764f2008-05-13 18:45:46 +00001449 MYDB_END_ALLOW_THREADS;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001450 self->db = NULL;
1451 RETURN_IF_ERR();
1452 }
1453 RETURN_NONE();
1454}
1455
Jesus Ceaef9764f2008-05-13 18:45:46 +00001456static PyObject*
1457DB_close(DBObject* self, PyObject* args)
1458{
1459 int flags=0;
1460 if (!PyArg_ParseTuple(args,"|i:close", &flags))
1461 return NULL;
1462 return DB_close_internal(self,flags);
1463}
1464
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001465
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001466static PyObject*
1467_DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1468{
1469 int err, flags=0, type;
1470 PyObject* txnobj = NULL;
1471 PyObject* retval = NULL;
1472 DBT key, data;
1473 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001474 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001475
1476 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:consume", kwnames,
1477 &txnobj, &flags))
1478 return NULL;
1479
1480 CHECK_DB_NOT_CLOSED(self);
1481 type = _DB_get_type(self);
1482 if (type == -1)
1483 return NULL;
1484 if (type != DB_QUEUE) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001485 PyErr_SetString(PyExc_TypeError,
1486 "Consume methods only allowed for Queue DB's");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001487 return NULL;
1488 }
1489 if (!checkTxnObj(txnobj, &txn))
1490 return NULL;
1491
1492 CLEAR_DBT(key);
1493 CLEAR_DBT(data);
1494 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001495 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001496 data.flags = DB_DBT_MALLOC;
1497 key.flags = DB_DBT_MALLOC;
1498 }
1499
1500 MYDB_BEGIN_ALLOW_THREADS;
1501 err = self->db->get(self->db, txn, &key, &data, flags|consume_flag);
1502 MYDB_END_ALLOW_THREADS;
1503
Gregory P. Smithe9477062005-06-04 06:46:59 +00001504 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1505 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001506 err = 0;
1507 Py_INCREF(Py_None);
1508 retval = Py_None;
1509 }
1510 else if (!err) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001511 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001512 FREE_DBT(key);
1513 FREE_DBT(data);
1514 }
1515
1516 RETURN_IF_ERR();
1517 return retval;
1518}
1519
1520static PyObject*
1521DB_consume(DBObject* self, PyObject* args, PyObject* kwargs, int consume_flag)
1522{
1523 return _DB_consume(self, args, kwargs, DB_CONSUME);
1524}
1525
1526static PyObject*
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001527DB_consume_wait(DBObject* self, PyObject* args, PyObject* kwargs,
1528 int consume_flag)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001529{
1530 return _DB_consume(self, args, kwargs, DB_CONSUME_WAIT);
1531}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001532
1533
1534static PyObject*
1535DB_cursor(DBObject* self, PyObject* args, PyObject* kwargs)
1536{
1537 int err, flags=0;
1538 DBC* dbc;
1539 PyObject* txnobj = NULL;
1540 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001541 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001542
1543 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
1544 &txnobj, &flags))
1545 return NULL;
1546 CHECK_DB_NOT_CLOSED(self);
1547 if (!checkTxnObj(txnobj, &txn))
1548 return NULL;
1549
1550 MYDB_BEGIN_ALLOW_THREADS;
1551 err = self->db->cursor(self->db, txn, &dbc, flags);
1552 MYDB_END_ALLOW_THREADS;
1553 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00001554 return (PyObject*) newDBCursorObject(dbc, (DBTxnObject *)txnobj, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001555}
1556
1557
1558static PyObject*
1559DB_delete(DBObject* self, PyObject* args, PyObject* kwargs)
1560{
1561 PyObject* txnobj = NULL;
1562 int flags = 0;
1563 PyObject* keyobj;
1564 DBT key;
1565 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001566 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001567
1568 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:delete", kwnames,
1569 &keyobj, &txnobj, &flags))
1570 return NULL;
1571 CHECK_DB_NOT_CLOSED(self);
1572 if (!make_key_dbt(self, keyobj, &key, NULL))
1573 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001574 if (!checkTxnObj(txnobj, &txn)) {
1575 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001576 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001577 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001578
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001579 if (-1 == _DB_delete(self, txn, &key, 0)) {
1580 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001581 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001582 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001583
1584 FREE_DBT(key);
1585 RETURN_NONE();
1586}
1587
1588
1589static PyObject*
1590DB_fd(DBObject* self, PyObject* args)
1591{
1592 int err, the_fd;
1593
1594 if (!PyArg_ParseTuple(args,":fd"))
1595 return NULL;
1596 CHECK_DB_NOT_CLOSED(self);
1597
1598 MYDB_BEGIN_ALLOW_THREADS;
1599 err = self->db->fd(self->db, &the_fd);
1600 MYDB_END_ALLOW_THREADS;
1601 RETURN_IF_ERR();
1602 return PyInt_FromLong(the_fd);
1603}
1604
1605
1606static PyObject*
1607DB_get(DBObject* self, PyObject* args, PyObject* kwargs)
1608{
1609 int err, flags=0;
1610 PyObject* txnobj = NULL;
1611 PyObject* keyobj;
1612 PyObject* dfltobj = NULL;
1613 PyObject* retval = NULL;
1614 int dlen = -1;
1615 int doff = -1;
1616 DBT key, data;
1617 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001618 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001619 "doff", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001620
1621 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:get", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001622 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1623 &doff))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001624 return NULL;
1625
1626 CHECK_DB_NOT_CLOSED(self);
1627 if (!make_key_dbt(self, keyobj, &key, &flags))
1628 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001629 if (!checkTxnObj(txnobj, &txn)) {
1630 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001631 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001632 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001633
1634 CLEAR_DBT(data);
1635 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001636 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001637 data.flags = DB_DBT_MALLOC;
1638 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001639 if (!add_partial_dbt(&data, dlen, doff)) {
1640 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001641 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001642 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001643
1644 MYDB_BEGIN_ALLOW_THREADS;
1645 err = self->db->get(self->db, txn, &key, &data, flags);
1646 MYDB_END_ALLOW_THREADS;
1647
Gregory P. Smithe9477062005-06-04 06:46:59 +00001648 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001649 err = 0;
1650 Py_INCREF(dfltobj);
1651 retval = dfltobj;
1652 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001653 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1654 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001655 err = 0;
1656 Py_INCREF(Py_None);
1657 retval = Py_None;
1658 }
1659 else if (!err) {
1660 if (flags & DB_SET_RECNO) /* return both key and data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001661 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001662 else /* return just the data */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001663 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001664 FREE_DBT(data);
1665 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001666 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001667
1668 RETURN_IF_ERR();
1669 return retval;
1670}
1671
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001672#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00001673static PyObject*
1674DB_pget(DBObject* self, PyObject* args, PyObject* kwargs)
1675{
1676 int err, flags=0;
1677 PyObject* txnobj = NULL;
1678 PyObject* keyobj;
1679 PyObject* dfltobj = NULL;
1680 PyObject* retval = NULL;
1681 int dlen = -1;
1682 int doff = -1;
1683 DBT key, pkey, data;
1684 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001685 static char* kwnames[] = {"key", "default", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00001686 "doff", NULL};
Gregory P. Smith19699a92004-06-28 04:06:49 +00001687
1688 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|OOiii:pget", kwnames,
1689 &keyobj, &dfltobj, &txnobj, &flags, &dlen,
1690 &doff))
1691 return NULL;
1692
1693 CHECK_DB_NOT_CLOSED(self);
1694 if (!make_key_dbt(self, keyobj, &key, &flags))
1695 return NULL;
1696 if (!checkTxnObj(txnobj, &txn)) {
1697 FREE_DBT(key);
1698 return NULL;
1699 }
1700
1701 CLEAR_DBT(data);
1702 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001703 /* Tell Berkeley DB to malloc the return value (thread safe) */
Gregory P. Smith19699a92004-06-28 04:06:49 +00001704 data.flags = DB_DBT_MALLOC;
1705 }
1706 if (!add_partial_dbt(&data, dlen, doff)) {
1707 FREE_DBT(key);
1708 return NULL;
1709 }
1710
1711 CLEAR_DBT(pkey);
1712 pkey.flags = DB_DBT_MALLOC;
1713
1714 MYDB_BEGIN_ALLOW_THREADS;
1715 err = self->db->pget(self->db, txn, &key, &pkey, &data, flags);
1716 MYDB_END_ALLOW_THREADS;
1717
Gregory P. Smithe9477062005-06-04 06:46:59 +00001718 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && (dfltobj != NULL)) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001719 err = 0;
1720 Py_INCREF(dfltobj);
1721 retval = dfltobj;
1722 }
Gregory P. Smithe9477062005-06-04 06:46:59 +00001723 else if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1724 && self->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00001725 err = 0;
1726 Py_INCREF(Py_None);
1727 retval = Py_None;
1728 }
1729 else if (!err) {
1730 PyObject *pkeyObj;
1731 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00001732 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001733
1734 if (self->primaryDBType == DB_RECNO ||
1735 self->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001736 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001737 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001738 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001739
1740 if (flags & DB_SET_RECNO) /* return key , pkey and data */
1741 {
1742 PyObject *keyObj;
1743 int type = _DB_get_type(self);
1744 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00001745 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001746 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00001747 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001748#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001749 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001750#else
1751 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
1752#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00001753 Py_DECREF(keyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001754 }
1755 else /* return just the pkey and data */
1756 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001757#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00001758 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00001759#else
1760 retval = Py_BuildValue("OO", pkeyObj, dataObj);
1761#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001762 }
Thomas Woutersb3153832006-03-08 01:47:19 +00001763 Py_DECREF(dataObj);
1764 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00001765 FREE_DBT(pkey);
1766 FREE_DBT(data);
1767 }
1768 FREE_DBT(key);
1769
1770 RETURN_IF_ERR();
1771 return retval;
1772}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00001773#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00001774
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001775
1776/* Return size of entry */
1777static PyObject*
1778DB_get_size(DBObject* self, PyObject* args, PyObject* kwargs)
1779{
1780 int err, flags=0;
1781 PyObject* txnobj = NULL;
1782 PyObject* keyobj;
1783 PyObject* retval = NULL;
1784 DBT key, data;
1785 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001786 static char* kwnames[] = { "key", "txn", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001787
1788 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O:get_size", kwnames,
1789 &keyobj, &txnobj))
1790 return NULL;
1791 CHECK_DB_NOT_CLOSED(self);
1792 if (!make_key_dbt(self, keyobj, &key, &flags))
1793 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001794 if (!checkTxnObj(txnobj, &txn)) {
1795 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001796 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001797 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001798 CLEAR_DBT(data);
1799
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001800 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and
1801 thus getting the record size. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001802 data.flags = DB_DBT_USERMEM;
1803 data.ulen = 0;
1804 MYDB_BEGIN_ALLOW_THREADS;
1805 err = self->db->get(self->db, txn, &key, &data, flags);
1806 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00001807 if (err == DB_BUFFER_SMALL) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001808 retval = PyInt_FromLong((long)data.size);
1809 err = 0;
1810 }
1811
1812 FREE_DBT(key);
1813 FREE_DBT(data);
1814 RETURN_IF_ERR();
1815 return retval;
1816}
1817
1818
1819static PyObject*
1820DB_get_both(DBObject* self, PyObject* args, PyObject* kwargs)
1821{
1822 int err, flags=0;
1823 PyObject* txnobj = NULL;
1824 PyObject* keyobj;
1825 PyObject* dataobj;
1826 PyObject* retval = NULL;
1827 DBT key, data;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001828 void *orig_data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001829 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001830 static char* kwnames[] = { "key", "data", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001831
1832
1833 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oi:get_both", kwnames,
1834 &keyobj, &dataobj, &txnobj, &flags))
1835 return NULL;
1836
1837 CHECK_DB_NOT_CLOSED(self);
1838 if (!make_key_dbt(self, keyobj, &key, NULL))
1839 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001840 if ( !make_dbt(dataobj, &data) ||
1841 !checkTxnObj(txnobj, &txn) )
1842 {
1843 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001844 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00001845 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001846
1847 flags |= DB_GET_BOTH;
Neal Norwitz994ebed2007-06-03 20:32:50 +00001848 orig_data = data.data;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001849
1850 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00001851 /* Tell Berkeley DB to malloc the return value (thread safe) */
Neal Norwitz994ebed2007-06-03 20:32:50 +00001852 /* XXX(nnorwitz): At least 4.4.20 and 4.5.20 require this flag. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001853 data.flags = DB_DBT_MALLOC;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001854 }
1855
1856 MYDB_BEGIN_ALLOW_THREADS;
1857 err = self->db->get(self->db, txn, &key, &data, flags);
1858 MYDB_END_ALLOW_THREADS;
1859
Gregory P. Smithe9477062005-06-04 06:46:59 +00001860 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
1861 && self->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001862 err = 0;
1863 Py_INCREF(Py_None);
1864 retval = Py_None;
1865 }
1866 else if (!err) {
Neal Norwitz994ebed2007-06-03 20:32:50 +00001867 /* XXX(nnorwitz): can we do: retval = dataobj; Py_INCREF(retval); */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001868 retval = Build_PyString(data.data, data.size);
Neal Norwitz994ebed2007-06-03 20:32:50 +00001869
1870 /* Even though the flags require DB_DBT_MALLOC, data is not always
1871 allocated. 4.4: allocated, 4.5: *not* allocated. :-( */
1872 if (data.data != orig_data)
1873 FREE_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001874 }
1875
1876 FREE_DBT(key);
1877 RETURN_IF_ERR();
1878 return retval;
1879}
1880
1881
1882static PyObject*
1883DB_get_byteswapped(DBObject* self, PyObject* args)
1884{
1885#if (DBVER >= 33)
1886 int err = 0;
1887#endif
1888 int retval = -1;
1889
1890 if (!PyArg_ParseTuple(args,":get_byteswapped"))
1891 return NULL;
1892 CHECK_DB_NOT_CLOSED(self);
1893
1894#if (DBVER >= 33)
1895 MYDB_BEGIN_ALLOW_THREADS;
1896 err = self->db->get_byteswapped(self->db, &retval);
1897 MYDB_END_ALLOW_THREADS;
1898 RETURN_IF_ERR();
1899#else
1900 MYDB_BEGIN_ALLOW_THREADS;
1901 retval = self->db->get_byteswapped(self->db);
1902 MYDB_END_ALLOW_THREADS;
1903#endif
1904 return PyInt_FromLong(retval);
1905}
1906
1907
1908static PyObject*
1909DB_get_type(DBObject* self, PyObject* args)
1910{
1911 int type;
1912
1913 if (!PyArg_ParseTuple(args,":get_type"))
1914 return NULL;
1915 CHECK_DB_NOT_CLOSED(self);
1916
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001917 type = _DB_get_type(self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001918 if (type == -1)
1919 return NULL;
1920 return PyInt_FromLong(type);
1921}
1922
1923
1924static PyObject*
1925DB_join(DBObject* self, PyObject* args)
1926{
1927 int err, flags=0;
1928 int length, x;
1929 PyObject* cursorsObj;
1930 DBC** cursors;
1931 DBC* dbc;
1932
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001933 if (!PyArg_ParseTuple(args,"O|i:join", &cursorsObj, &flags))
1934 return NULL;
1935
1936 CHECK_DB_NOT_CLOSED(self);
1937
1938 if (!PySequence_Check(cursorsObj)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001939 PyErr_SetString(PyExc_TypeError,
1940 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001941 return NULL;
1942 }
1943
1944 length = PyObject_Length(cursorsObj);
1945 cursors = malloc((length+1) * sizeof(DBC*));
Neal Norwitz5aa96892006-08-13 18:11:43 +00001946 if (!cursors) {
1947 PyErr_NoMemory();
1948 return NULL;
1949 }
1950
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001951 cursors[length] = NULL;
1952 for (x=0; x<length; x++) {
1953 PyObject* item = PySequence_GetItem(cursorsObj, x);
Thomas Woutersb3153832006-03-08 01:47:19 +00001954 if (item == NULL) {
1955 free(cursors);
1956 return NULL;
1957 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001958 if (!DBCursorObject_Check(item)) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001959 PyErr_SetString(PyExc_TypeError,
1960 "Sequence of DBCursor objects expected");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001961 free(cursors);
1962 return NULL;
1963 }
1964 cursors[x] = ((DBCursorObject*)item)->dbc;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00001965 Py_DECREF(item);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001966 }
1967
1968 MYDB_BEGIN_ALLOW_THREADS;
1969 err = self->db->join(self->db, cursors, &dbc, flags);
1970 MYDB_END_ALLOW_THREADS;
1971 free(cursors);
1972 RETURN_IF_ERR();
1973
Gregory P. Smith7441e652003-11-03 21:35:31 +00001974 /* FIXME: this is a buggy interface. The returned cursor
1975 contains internal references to the passed in cursors
1976 but does not hold python references to them or prevent
1977 them from being closed prematurely. This can cause
1978 python to crash when things are done in the wrong order. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00001979 return (PyObject*) newDBCursorObject(dbc, NULL, self);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001980}
1981
1982
1983static PyObject*
1984DB_key_range(DBObject* self, PyObject* args, PyObject* kwargs)
1985{
1986 int err, flags=0;
1987 PyObject* txnobj = NULL;
1988 PyObject* keyobj;
1989 DBT key;
1990 DB_TXN *txn = NULL;
1991 DB_KEY_RANGE range;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00001992 static char* kwnames[] = { "key", "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00001993
1994 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:key_range", kwnames,
1995 &keyobj, &txnobj, &flags))
1996 return NULL;
1997 CHECK_DB_NOT_CLOSED(self);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00001998 if (!make_dbt(keyobj, &key))
1999 /* BTree only, don't need to allow for an int key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002000 return NULL;
2001 if (!checkTxnObj(txnobj, &txn))
2002 return NULL;
2003
2004 MYDB_BEGIN_ALLOW_THREADS;
2005 err = self->db->key_range(self->db, txn, &key, &range, flags);
2006 MYDB_END_ALLOW_THREADS;
2007
2008 RETURN_IF_ERR();
2009 return Py_BuildValue("ddd", range.less, range.equal, range.greater);
2010}
2011
2012
2013static PyObject*
2014DB_open(DBObject* self, PyObject* args, PyObject* kwargs)
2015{
2016 int err, type = DB_UNKNOWN, flags=0, mode=0660;
2017 char* filename = NULL;
2018 char* dbname = NULL;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002019#if (DBVER >= 41)
2020 PyObject *txnobj = NULL;
2021 DB_TXN *txn = NULL;
2022 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002023 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002024 "filename", "dbname", "dbtype", "flags", "mode", "txn", NULL};
2025 /* without dbname */
Tim Peters85b10522006-02-28 18:33:35 +00002026 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002027 "filename", "dbtype", "flags", "mode", "txn", NULL};
2028#else
2029 /* with dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002030 static char* kwnames[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002031 "filename", "dbname", "dbtype", "flags", "mode", NULL};
2032 /* without dbname */
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002033 static char* kwnames_basic[] = {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002034 "filename", "dbtype", "flags", "mode", NULL};
2035#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002036
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002037#if (DBVER >= 41)
2038 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziiiO:open", kwnames,
2039 &filename, &dbname, &type, &flags, &mode,
2040 &txnobj))
2041#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002042 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|ziii:open", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002043 &filename, &dbname, &type, &flags,
2044 &mode))
2045#endif
2046 {
2047 PyErr_Clear();
2048 type = DB_UNKNOWN; flags = 0; mode = 0660;
2049 filename = NULL; dbname = NULL;
2050#if (DBVER >= 41)
2051 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iiiO:open",
2052 kwnames_basic,
2053 &filename, &type, &flags, &mode,
2054 &txnobj))
2055 return NULL;
2056#else
2057 if (!PyArg_ParseTupleAndKeywords(args, kwargs,"z|iii:open",
2058 kwnames_basic,
2059 &filename, &type, &flags, &mode))
2060 return NULL;
2061#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002062 }
2063
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002064#if (DBVER >= 41)
2065 if (!checkTxnObj(txnobj, &txn)) return NULL;
2066#endif
2067
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002068 if (NULL == self->db) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002069 PyObject *t = Py_BuildValue("(is)", 0,
2070 "Cannot call open() twice for DB object");
2071 PyErr_SetObject(DBError, t);
2072 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002073 return NULL;
2074 }
2075
Jesus Ceaef9764f2008-05-13 18:45:46 +00002076#if (DBVER >= 41)
2077 if (txn) { /* Can't use 'txnobj' because could be 'txnobj==Py_None' */
2078 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_dbs,self);
2079 self->txn=(DBTxnObject *)txnobj;
2080 } else {
2081 self->txn=NULL;
2082 }
2083#else
2084 self->txn=NULL;
2085#endif
2086
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002087 MYDB_BEGIN_ALLOW_THREADS;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002088#if (DBVER >= 41)
2089 err = self->db->open(self->db, txn, filename, dbname, type, flags, mode);
2090#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002091 err = self->db->open(self->db, filename, dbname, type, flags, mode);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002092#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002093 MYDB_END_ALLOW_THREADS;
2094 if (makeDBError(err)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002095 PyObject *dummy;
2096
2097 dummy=DB_close_internal(self,0);
2098 Py_XDECREF(dummy);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002099 return NULL;
2100 }
2101
Gregory P. Smithfc006692007-11-05 09:06:28 +00002102#if (DBVER >= 42)
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002103 self->db->get_flags(self->db, &self->setflags);
Gregory P. Smithfc006692007-11-05 09:06:28 +00002104#endif
Gregory P. Smithec10a4a2007-11-05 02:32:26 +00002105
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002106 self->flags = flags;
Jesus Ceaef9764f2008-05-13 18:45:46 +00002107
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002108 RETURN_NONE();
2109}
2110
2111
2112static PyObject*
2113DB_put(DBObject* self, PyObject* args, PyObject* kwargs)
2114{
2115 int flags=0;
2116 PyObject* txnobj = NULL;
2117 int dlen = -1;
2118 int doff = -1;
2119 PyObject* keyobj, *dataobj, *retval;
2120 DBT key, data;
2121 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002122 static char* kwnames[] = { "key", "data", "txn", "flags", "dlen",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002123 "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002124
2125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|Oiii:put", kwnames,
2126 &keyobj, &dataobj, &txnobj, &flags, &dlen, &doff))
2127 return NULL;
2128
2129 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002130 if (!make_key_dbt(self, keyobj, &key, NULL))
2131 return NULL;
2132 if ( !make_dbt(dataobj, &data) ||
2133 !add_partial_dbt(&data, dlen, doff) ||
2134 !checkTxnObj(txnobj, &txn) )
2135 {
2136 FREE_DBT(key);
2137 return NULL;
2138 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002139
2140 if (-1 == _DB_put(self, txn, &key, &data, flags)) {
2141 FREE_DBT(key);
2142 return NULL;
2143 }
2144
2145 if (flags & DB_APPEND)
2146 retval = PyInt_FromLong(*((db_recno_t*)key.data));
2147 else {
2148 retval = Py_None;
2149 Py_INCREF(retval);
2150 }
2151 FREE_DBT(key);
2152 return retval;
2153}
2154
2155
2156
2157static PyObject*
2158DB_remove(DBObject* self, PyObject* args, PyObject* kwargs)
2159{
2160 char* filename;
2161 char* database = NULL;
2162 int err, flags=0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002163 static char* kwnames[] = { "filename", "dbname", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002164
2165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zi:remove", kwnames,
2166 &filename, &database, &flags))
2167 return NULL;
2168 CHECK_DB_NOT_CLOSED(self);
2169
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002170 err = self->db->remove(self->db, filename, database, flags);
Gregory P. Smithf655dff2003-05-15 00:13:18 +00002171 self->db = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002172 RETURN_IF_ERR();
2173 RETURN_NONE();
2174}
2175
2176
2177
2178static PyObject*
2179DB_rename(DBObject* self, PyObject* args)
2180{
2181 char* filename;
2182 char* database;
2183 char* newname;
2184 int err, flags=0;
2185
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002186 if (!PyArg_ParseTuple(args, "sss|i:rename", &filename, &database, &newname,
2187 &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002188 return NULL;
2189 CHECK_DB_NOT_CLOSED(self);
2190
2191 MYDB_BEGIN_ALLOW_THREADS;
2192 err = self->db->rename(self->db, filename, database, newname, flags);
2193 MYDB_END_ALLOW_THREADS;
2194 RETURN_IF_ERR();
2195 RETURN_NONE();
2196}
2197
2198
2199static PyObject*
2200DB_set_bt_minkey(DBObject* self, PyObject* args)
2201{
2202 int err, minkey;
2203
2204 if (!PyArg_ParseTuple(args,"i:set_bt_minkey", &minkey ))
2205 return NULL;
2206 CHECK_DB_NOT_CLOSED(self);
2207
2208 MYDB_BEGIN_ALLOW_THREADS;
2209 err = self->db->set_bt_minkey(self->db, minkey);
2210 MYDB_END_ALLOW_THREADS;
2211 RETURN_IF_ERR();
2212 RETURN_NONE();
2213}
2214
Neal Norwitz84562352005-10-20 04:30:15 +00002215#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002216static int
Georg Brandlef1701f2006-03-07 14:57:48 +00002217_default_cmp(const DBT *leftKey,
2218 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002219{
2220 int res;
2221 int lsize = leftKey->size, rsize = rightKey->size;
2222
Georg Brandlef1701f2006-03-07 14:57:48 +00002223 res = memcmp(leftKey->data, rightKey->data,
2224 lsize < rsize ? lsize : rsize);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002225
2226 if (res == 0) {
2227 if (lsize < rsize) {
2228 res = -1;
2229 }
2230 else if (lsize > rsize) {
2231 res = 1;
2232 }
2233 }
2234 return res;
2235}
2236
2237static int
Jesus Ceaef9764f2008-05-13 18:45:46 +00002238_db_compareCallback(DB* db,
Georg Brandlef1701f2006-03-07 14:57:48 +00002239 const DBT *leftKey,
2240 const DBT *rightKey)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002241{
2242 int res = 0;
2243 PyObject *args;
Thomas Woutersb2820ae2006-03-12 00:01:38 +00002244 PyObject *result = NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002245 DBObject *self = (DBObject *)db->app_private;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002246
2247 if (self == NULL || self->btCompareCallback == NULL) {
2248 MYDB_BEGIN_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002249 PyErr_SetString(PyExc_TypeError,
2250 (self == 0
2251 ? "DB_bt_compare db is NULL."
2252 : "DB_bt_compare callback is NULL."));
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002253 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002254 PyErr_Print();
2255 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002256 MYDB_END_BLOCK_THREADS;
Georg Brandlef1701f2006-03-07 14:57:48 +00002257 } else {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002258 MYDB_BEGIN_BLOCK_THREADS;
2259
Jesus Ceaef9764f2008-05-13 18:45:46 +00002260 args = BuildValue_SS(leftKey->data, leftKey->size, rightKey->data, rightKey->size);
Georg Brandlef1701f2006-03-07 14:57:48 +00002261 if (args != NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002262 /* XXX(twouters) I highly doubt this INCREF is correct */
Georg Brandlef1701f2006-03-07 14:57:48 +00002263 Py_INCREF(self);
Georg Brandlef1701f2006-03-07 14:57:48 +00002264 result = PyEval_CallObject(self->btCompareCallback, args);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002265 }
Georg Brandlef1701f2006-03-07 14:57:48 +00002266 if (args == NULL || result == NULL) {
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002267 /* we're in a callback within the DB code, we can't raise */
Georg Brandlef1701f2006-03-07 14:57:48 +00002268 PyErr_Print();
2269 res = _default_cmp(leftKey, rightKey);
2270 } else if (PyInt_Check(result)) {
2271 res = PyInt_AsLong(result);
2272 } else {
2273 PyErr_SetString(PyExc_TypeError,
2274 "DB_bt_compare callback MUST return an int.");
2275 /* we're in a callback within the DB code, we can't raise */
2276 PyErr_Print();
2277 res = _default_cmp(leftKey, rightKey);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002278 }
2279
Thomas Woutersb3153832006-03-08 01:47:19 +00002280 Py_XDECREF(args);
Georg Brandlef1701f2006-03-07 14:57:48 +00002281 Py_XDECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002282
2283 MYDB_END_BLOCK_THREADS;
2284 }
2285 return res;
2286}
2287
2288static PyObject*
Georg Brandlef1701f2006-03-07 14:57:48 +00002289DB_set_bt_compare(DBObject* self, PyObject* args)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002290{
2291 int err;
2292 PyObject *comparator;
Thomas Woutersb3153832006-03-08 01:47:19 +00002293 PyObject *tuple, *result;
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002294
Georg Brandlef1701f2006-03-07 14:57:48 +00002295 if (!PyArg_ParseTuple(args, "O:set_bt_compare", &comparator))
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002296 return NULL;
2297
Georg Brandlef1701f2006-03-07 14:57:48 +00002298 CHECK_DB_NOT_CLOSED(self);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002299
Georg Brandlef1701f2006-03-07 14:57:48 +00002300 if (!PyCallable_Check(comparator)) {
2301 makeTypeError("Callable", comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002302 return NULL;
2303 }
2304
2305 /*
2306 * Perform a test call of the comparator function with two empty
2307 * string objects here. verify that it returns an int (0).
2308 * err if not.
2309 */
Thomas Woutersb3153832006-03-08 01:47:19 +00002310 tuple = Py_BuildValue("(ss)", "", "");
Georg Brandlef1701f2006-03-07 14:57:48 +00002311 result = PyEval_CallObject(comparator, tuple);
2312 Py_DECREF(tuple);
Thomas Woutersb3153832006-03-08 01:47:19 +00002313 if (result == NULL)
2314 return NULL;
2315 if (!PyInt_Check(result)) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002316 PyErr_SetString(PyExc_TypeError,
2317 "callback MUST return an int");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002318 return NULL;
Georg Brandlef1701f2006-03-07 14:57:48 +00002319 } else if (PyInt_AsLong(result) != 0) {
2320 PyErr_SetString(PyExc_TypeError,
2321 "callback failed to return 0 on two empty strings");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002322 return NULL;
2323 }
Thomas Woutersb3153832006-03-08 01:47:19 +00002324 Py_DECREF(result);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002325
2326 /* We don't accept multiple set_bt_compare operations, in order to
2327 * simplify the code. This would have no real use, as one cannot
2328 * change the function once the db is opened anyway */
2329 if (self->btCompareCallback != NULL) {
Georg Brandlef1701f2006-03-07 14:57:48 +00002330 PyErr_SetString(PyExc_RuntimeError, "set_bt_compare() cannot be called more than once");
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002331 return NULL;
2332 }
2333
Georg Brandlef1701f2006-03-07 14:57:48 +00002334 Py_INCREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002335 self->btCompareCallback = comparator;
2336
2337 /* This is to workaround a problem with un-initialized threads (see
2338 comment in DB_associate) */
2339#ifdef WITH_THREAD
2340 PyEval_InitThreads();
2341#endif
2342
Thomas Woutersb3153832006-03-08 01:47:19 +00002343 err = self->db->set_bt_compare(self->db, _db_compareCallback);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002344
2345 if (err) {
2346 /* restore the old state in case of error */
Georg Brandlef1701f2006-03-07 14:57:48 +00002347 Py_DECREF(comparator);
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002348 self->btCompareCallback = NULL;
2349 }
2350
Georg Brandlef1701f2006-03-07 14:57:48 +00002351 RETURN_IF_ERR();
2352 RETURN_NONE();
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002353}
Neal Norwitz84562352005-10-20 04:30:15 +00002354#endif /* DBVER >= 33 */
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00002355
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002356
2357static PyObject*
2358DB_set_cachesize(DBObject* self, PyObject* args)
2359{
2360 int err;
2361 int gbytes = 0, bytes = 0, ncache = 0;
2362
2363 if (!PyArg_ParseTuple(args,"ii|i:set_cachesize",
2364 &gbytes,&bytes,&ncache))
2365 return NULL;
2366 CHECK_DB_NOT_CLOSED(self);
2367
2368 MYDB_BEGIN_ALLOW_THREADS;
2369 err = self->db->set_cachesize(self->db, gbytes, bytes, ncache);
2370 MYDB_END_ALLOW_THREADS;
2371 RETURN_IF_ERR();
2372 RETURN_NONE();
2373}
2374
2375
2376static PyObject*
2377DB_set_flags(DBObject* self, PyObject* args)
2378{
2379 int err, flags;
2380
2381 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
2382 return NULL;
2383 CHECK_DB_NOT_CLOSED(self);
2384
2385 MYDB_BEGIN_ALLOW_THREADS;
2386 err = self->db->set_flags(self->db, flags);
2387 MYDB_END_ALLOW_THREADS;
2388 RETURN_IF_ERR();
2389
2390 self->setflags |= flags;
2391 RETURN_NONE();
2392}
2393
2394
2395static PyObject*
2396DB_set_h_ffactor(DBObject* self, PyObject* args)
2397{
2398 int err, ffactor;
2399
2400 if (!PyArg_ParseTuple(args,"i:set_h_ffactor", &ffactor))
2401 return NULL;
2402 CHECK_DB_NOT_CLOSED(self);
2403
2404 MYDB_BEGIN_ALLOW_THREADS;
2405 err = self->db->set_h_ffactor(self->db, ffactor);
2406 MYDB_END_ALLOW_THREADS;
2407 RETURN_IF_ERR();
2408 RETURN_NONE();
2409}
2410
2411
2412static PyObject*
2413DB_set_h_nelem(DBObject* self, PyObject* args)
2414{
2415 int err, nelem;
2416
2417 if (!PyArg_ParseTuple(args,"i:set_h_nelem", &nelem))
2418 return NULL;
2419 CHECK_DB_NOT_CLOSED(self);
2420
2421 MYDB_BEGIN_ALLOW_THREADS;
2422 err = self->db->set_h_nelem(self->db, nelem);
2423 MYDB_END_ALLOW_THREADS;
2424 RETURN_IF_ERR();
2425 RETURN_NONE();
2426}
2427
2428
2429static PyObject*
2430DB_set_lorder(DBObject* self, PyObject* args)
2431{
2432 int err, lorder;
2433
2434 if (!PyArg_ParseTuple(args,"i:set_lorder", &lorder))
2435 return NULL;
2436 CHECK_DB_NOT_CLOSED(self);
2437
2438 MYDB_BEGIN_ALLOW_THREADS;
2439 err = self->db->set_lorder(self->db, lorder);
2440 MYDB_END_ALLOW_THREADS;
2441 RETURN_IF_ERR();
2442 RETURN_NONE();
2443}
2444
2445
2446static PyObject*
2447DB_set_pagesize(DBObject* self, PyObject* args)
2448{
2449 int err, pagesize;
2450
2451 if (!PyArg_ParseTuple(args,"i:set_pagesize", &pagesize))
2452 return NULL;
2453 CHECK_DB_NOT_CLOSED(self);
2454
2455 MYDB_BEGIN_ALLOW_THREADS;
2456 err = self->db->set_pagesize(self->db, pagesize);
2457 MYDB_END_ALLOW_THREADS;
2458 RETURN_IF_ERR();
2459 RETURN_NONE();
2460}
2461
2462
2463static PyObject*
2464DB_set_re_delim(DBObject* self, PyObject* args)
2465{
2466 int err;
2467 char delim;
2468
2469 if (!PyArg_ParseTuple(args,"b:set_re_delim", &delim)) {
2470 PyErr_Clear();
2471 if (!PyArg_ParseTuple(args,"c:set_re_delim", &delim))
2472 return NULL;
2473 }
2474
2475 CHECK_DB_NOT_CLOSED(self);
2476
2477 MYDB_BEGIN_ALLOW_THREADS;
2478 err = self->db->set_re_delim(self->db, delim);
2479 MYDB_END_ALLOW_THREADS;
2480 RETURN_IF_ERR();
2481 RETURN_NONE();
2482}
2483
2484static PyObject*
2485DB_set_re_len(DBObject* self, PyObject* args)
2486{
2487 int err, len;
2488
2489 if (!PyArg_ParseTuple(args,"i:set_re_len", &len))
2490 return NULL;
2491 CHECK_DB_NOT_CLOSED(self);
2492
2493 MYDB_BEGIN_ALLOW_THREADS;
2494 err = self->db->set_re_len(self->db, len);
2495 MYDB_END_ALLOW_THREADS;
2496 RETURN_IF_ERR();
2497 RETURN_NONE();
2498}
2499
2500
2501static PyObject*
2502DB_set_re_pad(DBObject* self, PyObject* args)
2503{
2504 int err;
2505 char pad;
2506
2507 if (!PyArg_ParseTuple(args,"b:set_re_pad", &pad)) {
2508 PyErr_Clear();
2509 if (!PyArg_ParseTuple(args,"c:set_re_pad", &pad))
2510 return NULL;
2511 }
2512 CHECK_DB_NOT_CLOSED(self);
2513
2514 MYDB_BEGIN_ALLOW_THREADS;
2515 err = self->db->set_re_pad(self->db, pad);
2516 MYDB_END_ALLOW_THREADS;
2517 RETURN_IF_ERR();
2518 RETURN_NONE();
2519}
2520
2521
2522static PyObject*
2523DB_set_re_source(DBObject* self, PyObject* args)
2524{
2525 int err;
2526 char *re_source;
2527
2528 if (!PyArg_ParseTuple(args,"s:set_re_source", &re_source))
2529 return NULL;
2530 CHECK_DB_NOT_CLOSED(self);
2531
2532 MYDB_BEGIN_ALLOW_THREADS;
2533 err = self->db->set_re_source(self->db, re_source);
2534 MYDB_END_ALLOW_THREADS;
2535 RETURN_IF_ERR();
2536 RETURN_NONE();
2537}
2538
2539
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002540static PyObject*
2541DB_set_q_extentsize(DBObject* self, PyObject* args)
2542{
2543 int err;
2544 int extentsize;
2545
2546 if (!PyArg_ParseTuple(args,"i:set_q_extentsize", &extentsize))
2547 return NULL;
2548 CHECK_DB_NOT_CLOSED(self);
2549
2550 MYDB_BEGIN_ALLOW_THREADS;
2551 err = self->db->set_q_extentsize(self->db, extentsize);
2552 MYDB_END_ALLOW_THREADS;
2553 RETURN_IF_ERR();
2554 RETURN_NONE();
2555}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002556
2557static PyObject*
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002558DB_stat(DBObject* self, PyObject* args, PyObject* kwargs)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002559{
2560 int err, flags = 0, type;
2561 void* sp;
2562 PyObject* d;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002563#if (DBVER >= 43)
2564 PyObject* txnobj = NULL;
2565 DB_TXN *txn = NULL;
Gregory P. Smith2fa06792006-09-19 17:35:04 +00002566 static char* kwnames[] = { "flags", "txn", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002567#else
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002568 static char* kwnames[] = { "flags", NULL };
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002569#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002570
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002571#if (DBVER >= 43)
2572 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iO:stat", kwnames,
2573 &flags, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002574 return NULL;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002575 if (!checkTxnObj(txnobj, &txn))
2576 return NULL;
2577#else
2578 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
2579 return NULL;
2580#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002581 CHECK_DB_NOT_CLOSED(self);
2582
2583 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002584#if (DBVER >= 43)
2585 err = self->db->stat(self->db, txn, &sp, flags);
2586#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002587 err = self->db->stat(self->db, &sp, flags);
2588#else
2589 err = self->db->stat(self->db, &sp, NULL, flags);
2590#endif
2591 MYDB_END_ALLOW_THREADS;
2592 RETURN_IF_ERR();
2593
2594 self->haveStat = 1;
2595
2596 /* Turn the stat structure into a dictionary */
2597 type = _DB_get_type(self);
2598 if ((type == -1) || ((d = PyDict_New()) == NULL)) {
2599 free(sp);
2600 return NULL;
2601 }
2602
2603#define MAKE_HASH_ENTRY(name) _addIntToDict(d, #name, ((DB_HASH_STAT*)sp)->hash_##name)
2604#define MAKE_BT_ENTRY(name) _addIntToDict(d, #name, ((DB_BTREE_STAT*)sp)->bt_##name)
2605#define MAKE_QUEUE_ENTRY(name) _addIntToDict(d, #name, ((DB_QUEUE_STAT*)sp)->qs_##name)
2606
2607 switch (type) {
2608 case DB_HASH:
2609 MAKE_HASH_ENTRY(magic);
2610 MAKE_HASH_ENTRY(version);
2611 MAKE_HASH_ENTRY(nkeys);
2612 MAKE_HASH_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002613#if (DBVER >= 46)
2614 MAKE_HASH_ENTRY(pagecnt);
2615#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002616 MAKE_HASH_ENTRY(pagesize);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002617#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002618 MAKE_HASH_ENTRY(nelem);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002619#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002620 MAKE_HASH_ENTRY(ffactor);
2621 MAKE_HASH_ENTRY(buckets);
2622 MAKE_HASH_ENTRY(free);
2623 MAKE_HASH_ENTRY(bfree);
2624 MAKE_HASH_ENTRY(bigpages);
2625 MAKE_HASH_ENTRY(big_bfree);
2626 MAKE_HASH_ENTRY(overflows);
2627 MAKE_HASH_ENTRY(ovfl_free);
2628 MAKE_HASH_ENTRY(dup);
2629 MAKE_HASH_ENTRY(dup_free);
2630 break;
2631
2632 case DB_BTREE:
2633 case DB_RECNO:
2634 MAKE_BT_ENTRY(magic);
2635 MAKE_BT_ENTRY(version);
2636 MAKE_BT_ENTRY(nkeys);
2637 MAKE_BT_ENTRY(ndata);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002638#if (DBVER >= 46)
2639 MAKE_BT_ENTRY(pagecnt);
2640#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002641 MAKE_BT_ENTRY(pagesize);
2642 MAKE_BT_ENTRY(minkey);
2643 MAKE_BT_ENTRY(re_len);
2644 MAKE_BT_ENTRY(re_pad);
2645 MAKE_BT_ENTRY(levels);
2646 MAKE_BT_ENTRY(int_pg);
2647 MAKE_BT_ENTRY(leaf_pg);
2648 MAKE_BT_ENTRY(dup_pg);
2649 MAKE_BT_ENTRY(over_pg);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002650#if (DBVER >= 43)
2651 MAKE_BT_ENTRY(empty_pg);
2652#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002653 MAKE_BT_ENTRY(free);
2654 MAKE_BT_ENTRY(int_pgfree);
2655 MAKE_BT_ENTRY(leaf_pgfree);
2656 MAKE_BT_ENTRY(dup_pgfree);
2657 MAKE_BT_ENTRY(over_pgfree);
2658 break;
2659
2660 case DB_QUEUE:
2661 MAKE_QUEUE_ENTRY(magic);
2662 MAKE_QUEUE_ENTRY(version);
2663 MAKE_QUEUE_ENTRY(nkeys);
2664 MAKE_QUEUE_ENTRY(ndata);
2665 MAKE_QUEUE_ENTRY(pagesize);
Jesus Ceaef9764f2008-05-13 18:45:46 +00002666#if (DBVER > 40)
2667 MAKE_QUEUE_ENTRY(extentsize);
2668#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002669 MAKE_QUEUE_ENTRY(pages);
2670 MAKE_QUEUE_ENTRY(re_len);
2671 MAKE_QUEUE_ENTRY(re_pad);
2672 MAKE_QUEUE_ENTRY(pgfree);
2673#if (DBVER == 31)
2674 MAKE_QUEUE_ENTRY(start);
2675#endif
2676 MAKE_QUEUE_ENTRY(first_recno);
2677 MAKE_QUEUE_ENTRY(cur_recno);
2678 break;
2679
2680 default:
2681 PyErr_SetString(PyExc_TypeError, "Unknown DB type, unable to stat");
2682 Py_DECREF(d);
2683 d = NULL;
2684 }
2685
2686#undef MAKE_HASH_ENTRY
2687#undef MAKE_BT_ENTRY
2688#undef MAKE_QUEUE_ENTRY
2689
2690 free(sp);
2691 return d;
2692}
2693
2694static PyObject*
2695DB_sync(DBObject* self, PyObject* args)
2696{
2697 int err;
2698 int flags = 0;
2699
2700 if (!PyArg_ParseTuple(args,"|i:sync", &flags ))
2701 return NULL;
2702 CHECK_DB_NOT_CLOSED(self);
2703
2704 MYDB_BEGIN_ALLOW_THREADS;
2705 err = self->db->sync(self->db, flags);
2706 MYDB_END_ALLOW_THREADS;
2707 RETURN_IF_ERR();
2708 RETURN_NONE();
2709}
2710
2711
2712#if (DBVER >= 33)
2713static PyObject*
2714DB_truncate(DBObject* self, PyObject* args, PyObject* kwargs)
2715{
2716 int err, flags=0;
2717 u_int32_t count=0;
2718 PyObject* txnobj = NULL;
2719 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002720 static char* kwnames[] = { "txn", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002721
2722 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:cursor", kwnames,
2723 &txnobj, &flags))
2724 return NULL;
2725 CHECK_DB_NOT_CLOSED(self);
2726 if (!checkTxnObj(txnobj, &txn))
2727 return NULL;
2728
2729 MYDB_BEGIN_ALLOW_THREADS;
2730 err = self->db->truncate(self->db, txn, &count, flags);
2731 MYDB_END_ALLOW_THREADS;
2732 RETURN_IF_ERR();
2733 return PyInt_FromLong(count);
2734}
2735#endif
2736
2737
2738static PyObject*
2739DB_upgrade(DBObject* self, PyObject* args)
2740{
2741 int err, flags=0;
2742 char *filename;
2743
2744 if (!PyArg_ParseTuple(args,"s|i:upgrade", &filename, &flags))
2745 return NULL;
2746 CHECK_DB_NOT_CLOSED(self);
2747
2748 MYDB_BEGIN_ALLOW_THREADS;
2749 err = self->db->upgrade(self->db, filename, flags);
2750 MYDB_END_ALLOW_THREADS;
2751 RETURN_IF_ERR();
2752 RETURN_NONE();
2753}
2754
2755
2756static PyObject*
2757DB_verify(DBObject* self, PyObject* args, PyObject* kwargs)
2758{
2759 int err, flags=0;
2760 char* fileName;
2761 char* dbName=NULL;
2762 char* outFileName=NULL;
2763 FILE* outFile=NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002764 static char* kwnames[] = { "filename", "dbname", "outfile", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00002765 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002766
2767 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zzi:verify", kwnames,
2768 &fileName, &dbName, &outFileName, &flags))
2769 return NULL;
2770
2771 CHECK_DB_NOT_CLOSED(self);
2772 if (outFileName)
2773 outFile = fopen(outFileName, "w");
Neal Norwitz5aa96892006-08-13 18:11:43 +00002774 /* XXX(nnorwitz): it should probably be an exception if outFile
2775 can't be opened. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002776
2777 MYDB_BEGIN_ALLOW_THREADS;
2778 err = self->db->verify(self->db, fileName, dbName, outFile, flags);
2779 MYDB_END_ALLOW_THREADS;
Neal Norwitz5aa96892006-08-13 18:11:43 +00002780 if (outFile)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002781 fclose(outFile);
Gregory P. Smith41631e82003-09-21 00:08:14 +00002782
Jesus Ceaef9764f2008-05-13 18:45:46 +00002783 { /* DB.verify acts as a DB handle destructor (like close) */
2784 PyObject *error;
2785
2786 error=DB_close_internal(self,0);
2787 if (error ) {
2788 return error;
2789 }
2790 }
Gregory P. Smith41631e82003-09-21 00:08:14 +00002791
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002792 RETURN_IF_ERR();
2793 RETURN_NONE();
2794}
2795
2796
2797static PyObject*
2798DB_set_get_returns_none(DBObject* self, PyObject* args)
2799{
2800 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002801 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002802
2803 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
2804 return NULL;
2805 CHECK_DB_NOT_CLOSED(self);
2806
Gregory P. Smith455d46f2003-07-09 04:45:59 +00002807 if (self->moduleFlags.getReturnsNone)
2808 ++oldValue;
2809 if (self->moduleFlags.cursorSetReturnsNone)
2810 ++oldValue;
2811 self->moduleFlags.getReturnsNone = (flags >= 1);
2812 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002813 return PyInt_FromLong(oldValue);
2814}
2815
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002816#if (DBVER >= 41)
2817static PyObject*
2818DB_set_encrypt(DBObject* self, PyObject* args, PyObject* kwargs)
2819{
2820 int err;
2821 u_int32_t flags=0;
2822 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00002823 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002824
2825 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
2826 &passwd, &flags)) {
2827 return NULL;
2828 }
2829
2830 MYDB_BEGIN_ALLOW_THREADS;
2831 err = self->db->set_encrypt(self->db, passwd, flags);
2832 MYDB_END_ALLOW_THREADS;
2833
2834 RETURN_IF_ERR();
2835 RETURN_NONE();
2836}
2837#endif /* DBVER >= 41 */
2838
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002839
2840/*-------------------------------------------------------------- */
2841/* Mapping and Dictionary-like access routines */
2842
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002843Py_ssize_t DB_length(PyObject* _self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002844{
2845 int err;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002846 Py_ssize_t size = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002847 int flags = 0;
2848 void* sp;
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00002849 DBObject* self = (DBObject*)_self;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002850
2851 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002852 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2853 PyErr_SetObject(DBError, t);
2854 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002855 return -1;
2856 }
2857
2858 if (self->haveStat) { /* Has the stat function been called recently? If
2859 so, we can use the cached value. */
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002860 flags = DB_FAST_STAT;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002861 }
2862
2863 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002864redo_stat_for_length:
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002865#if (DBVER >= 43)
2866 err = self->db->stat(self->db, /*txnid*/ NULL, &sp, flags);
2867#elif (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002868 err = self->db->stat(self->db, &sp, flags);
2869#else
2870 err = self->db->stat(self->db, &sp, NULL, flags);
2871#endif
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002872
2873 /* All the stat structures have matching fields upto the ndata field,
2874 so we can use any of them for the type cast */
2875 size = ((DB_BTREE_STAT*)sp)->bt_ndata;
2876
Jesus Ceaef9764f2008-05-13 18:45:46 +00002877 /* A size of 0 could mean that Berkeley DB no longer had the stat values cached.
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002878 * redo a full stat to make sure.
2879 * Fixes SF python bug 1493322, pybsddb bug 1184012
2880 */
2881 if (size == 0 && (flags & DB_FAST_STAT)) {
2882 flags = 0;
Neal Norwitze75cad62006-06-17 22:38:15 +00002883 if (!err)
2884 free(sp);
Gregory P. Smith3c228b12006-06-05 23:59:37 +00002885 goto redo_stat_for_length;
2886 }
2887
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002888 MYDB_END_ALLOW_THREADS;
2889
2890 if (err)
2891 return -1;
2892
2893 self->haveStat = 1;
2894
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002895 free(sp);
2896 return size;
2897}
2898
2899
2900PyObject* DB_subscript(DBObject* self, PyObject* keyobj)
2901{
2902 int err;
2903 PyObject* retval;
2904 DBT key;
2905 DBT data;
2906
2907 CHECK_DB_NOT_CLOSED(self);
2908 if (!make_key_dbt(self, keyobj, &key, NULL))
2909 return NULL;
2910
2911 CLEAR_DBT(data);
2912 if (CHECK_DBFLAG(self, DB_THREAD)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002913 /* Tell Berkeley DB to malloc the return value (thread safe) */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002914 data.flags = DB_DBT_MALLOC;
2915 }
2916 MYDB_BEGIN_ALLOW_THREADS;
2917 err = self->db->get(self->db, NULL, &key, &data, 0);
2918 MYDB_END_ALLOW_THREADS;
2919 if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
2920 PyErr_SetObject(PyExc_KeyError, keyobj);
2921 retval = NULL;
2922 }
2923 else if (makeDBError(err)) {
2924 retval = NULL;
2925 }
2926 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00002927 retval = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002928 FREE_DBT(data);
2929 }
2930
2931 FREE_DBT(key);
2932 return retval;
2933}
2934
2935
2936static int
2937DB_ass_sub(DBObject* self, PyObject* keyobj, PyObject* dataobj)
2938{
2939 DBT key, data;
2940 int retval;
2941 int flags = 0;
2942
2943 if (self->db == NULL) {
Thomas Woutersb3153832006-03-08 01:47:19 +00002944 PyObject *t = Py_BuildValue("(is)", 0, "DB object has been closed");
2945 PyErr_SetObject(DBError, t);
2946 Py_DECREF(t);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002947 return -1;
2948 }
2949
2950 if (!make_key_dbt(self, keyobj, &key, NULL))
2951 return -1;
2952
2953 if (dataobj != NULL) {
2954 if (!make_dbt(dataobj, &data))
2955 retval = -1;
2956 else {
2957 if (self->setflags & (DB_DUP|DB_DUPSORT))
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002958 /* dictionaries shouldn't have duplicate keys */
2959 flags = DB_NOOVERWRITE;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002960 retval = _DB_put(self, NULL, &key, &data, flags);
2961
2962 if ((retval == -1) && (self->setflags & (DB_DUP|DB_DUPSORT))) {
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002963 /* try deleting any old record that matches and then PUT it
2964 * again... */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002965 _DB_delete(self, NULL, &key, 0);
2966 PyErr_Clear();
2967 retval = _DB_put(self, NULL, &key, &data, flags);
2968 }
2969 }
2970 }
2971 else {
2972 /* dataobj == NULL, so delete the key */
2973 retval = _DB_delete(self, NULL, &key, 0);
2974 }
2975 FREE_DBT(key);
2976 return retval;
2977}
2978
2979
2980static PyObject*
2981DB_has_key(DBObject* self, PyObject* args)
2982{
2983 int err;
2984 PyObject* keyobj;
2985 DBT key, data;
2986 PyObject* txnobj = NULL;
2987 DB_TXN *txn = NULL;
2988
Barry Warsaw9a0d7792002-12-30 20:53:52 +00002989 if (!PyArg_ParseTuple(args,"O|O:has_key", &keyobj, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002990 return NULL;
2991 CHECK_DB_NOT_CLOSED(self);
2992 if (!make_key_dbt(self, keyobj, &key, NULL))
2993 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002994 if (!checkTxnObj(txnobj, &txn)) {
2995 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002996 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00002997 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00002998
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00002999 /* This causes DB_BUFFER_SMALL to be returned when the db has the key because
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003000 it has a record but can't allocate a buffer for the data. This saves
3001 having to deal with data we won't be using.
3002 */
3003 CLEAR_DBT(data);
3004 data.flags = DB_DBT_USERMEM;
3005
3006 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith0c657712004-03-16 06:56:58 +00003007 err = self->db->get(self->db, txn, &key, &data, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003008 MYDB_END_ALLOW_THREADS;
3009 FREE_DBT(key);
Gregory P. Smithe9477062005-06-04 06:46:59 +00003010
3011 if (err == DB_BUFFER_SMALL || err == 0) {
3012 return PyInt_FromLong(1);
3013 } else if (err == DB_NOTFOUND || err == DB_KEYEMPTY) {
3014 return PyInt_FromLong(0);
3015 }
3016
3017 makeDBError(err);
3018 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003019}
3020
3021
3022#define _KEYS_LIST 1
3023#define _VALUES_LIST 2
3024#define _ITEMS_LIST 3
3025
3026static PyObject*
3027_DB_make_list(DBObject* self, DB_TXN* txn, int type)
3028{
3029 int err, dbtype;
3030 DBT key;
3031 DBT data;
3032 DBC *cursor;
3033 PyObject* list;
3034 PyObject* item = NULL;
3035
3036 CHECK_DB_NOT_CLOSED(self);
3037 CLEAR_DBT(key);
3038 CLEAR_DBT(data);
3039
3040 dbtype = _DB_get_type(self);
3041 if (dbtype == -1)
3042 return NULL;
3043
3044 list = PyList_New(0);
Thomas Woutersb3153832006-03-08 01:47:19 +00003045 if (list == NULL)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003046 return NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003047
3048 /* get a cursor */
3049 MYDB_BEGIN_ALLOW_THREADS;
Gregory P. Smith442c9fc2004-09-04 01:36:59 +00003050 err = self->db->cursor(self->db, txn, &cursor, 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003051 MYDB_END_ALLOW_THREADS;
Thomas Woutersb3153832006-03-08 01:47:19 +00003052 if (makeDBError(err)) {
3053 Py_DECREF(list);
3054 return NULL;
3055 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003056
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003057 while (1) { /* use the cursor to traverse the DB, collecting items */
3058 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003059 err = _DBC_get(cursor, &key, &data, DB_NEXT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003060 MYDB_END_ALLOW_THREADS;
3061
3062 if (err) {
3063 /* for any error, break out of the loop */
3064 break;
3065 }
3066
3067 switch (type) {
3068 case _KEYS_LIST:
3069 switch(dbtype) {
3070 case DB_BTREE:
3071 case DB_HASH:
3072 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003073 item = Build_PyString(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003074 break;
3075 case DB_RECNO:
3076 case DB_QUEUE:
3077 item = PyInt_FromLong(*((db_recno_t*)key.data));
3078 break;
3079 }
3080 break;
3081
3082 case _VALUES_LIST:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003083 item = Build_PyString(data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003084 break;
3085
3086 case _ITEMS_LIST:
3087 switch(dbtype) {
3088 case DB_BTREE:
3089 case DB_HASH:
3090 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003091 item = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003092 break;
3093 case DB_RECNO:
3094 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003095 item = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003096 break;
3097 }
3098 break;
Thomas Woutersb3153832006-03-08 01:47:19 +00003099 default:
3100 PyErr_Format(PyExc_ValueError, "Unknown key type 0x%x", type);
3101 item = NULL;
3102 break;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003103 }
3104 if (item == NULL) {
3105 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003106 list = NULL;
3107 goto done;
3108 }
3109 PyList_Append(list, item);
3110 Py_DECREF(item);
3111 }
3112
Gregory P. Smithe9477062005-06-04 06:46:59 +00003113 /* DB_NOTFOUND || DB_KEYEMPTY is okay, it means we got to the end */
3114 if (err != DB_NOTFOUND && err != DB_KEYEMPTY && makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003115 Py_DECREF(list);
3116 list = NULL;
3117 }
3118
3119 done:
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003120 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003121 _DBC_close(cursor);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003122 MYDB_END_ALLOW_THREADS;
3123 return list;
3124}
3125
3126
3127static PyObject*
3128DB_keys(DBObject* self, PyObject* args)
3129{
3130 PyObject* txnobj = NULL;
3131 DB_TXN *txn = NULL;
3132
Georg Brandl96a8c392006-05-29 21:04:52 +00003133 if (!PyArg_UnpackTuple(args, "keys", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003134 return NULL;
3135 if (!checkTxnObj(txnobj, &txn))
3136 return NULL;
3137 return _DB_make_list(self, txn, _KEYS_LIST);
3138}
3139
3140
3141static PyObject*
3142DB_items(DBObject* self, PyObject* args)
3143{
3144 PyObject* txnobj = NULL;
3145 DB_TXN *txn = NULL;
3146
Georg Brandl96a8c392006-05-29 21:04:52 +00003147 if (!PyArg_UnpackTuple(args, "items", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003148 return NULL;
3149 if (!checkTxnObj(txnobj, &txn))
3150 return NULL;
3151 return _DB_make_list(self, txn, _ITEMS_LIST);
3152}
3153
3154
3155static PyObject*
3156DB_values(DBObject* self, PyObject* args)
3157{
3158 PyObject* txnobj = NULL;
3159 DB_TXN *txn = NULL;
3160
Georg Brandl96a8c392006-05-29 21:04:52 +00003161 if (!PyArg_UnpackTuple(args, "values", 0, 1, &txnobj))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003162 return NULL;
3163 if (!checkTxnObj(txnobj, &txn))
3164 return NULL;
3165 return _DB_make_list(self, txn, _VALUES_LIST);
3166}
3167
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003168/* --------------------------------------------------------------------- */
3169/* DBCursor methods */
3170
3171
3172static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003173DBC_close_internal(DBCursorObject* self)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003174{
3175 int err = 0;
3176
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003177 if (self->dbc != NULL) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003178 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
3179 if (self->txn) {
3180 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
3181 self->txn=NULL;
3182 }
3183
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003184 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003185 err = _DBC_close(self->dbc);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003186 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003187 self->dbc = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003188 }
3189 RETURN_IF_ERR();
3190 RETURN_NONE();
3191}
3192
Jesus Ceaef9764f2008-05-13 18:45:46 +00003193static PyObject*
3194DBC_close(DBCursorObject* self, PyObject* args)
3195{
3196 if (!PyArg_ParseTuple(args, ":close"))
3197 return NULL;
3198
3199 return DBC_close_internal(self);
3200}
3201
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003202
3203static PyObject*
3204DBC_count(DBCursorObject* self, PyObject* args)
3205{
3206 int err = 0;
3207 db_recno_t count;
3208 int flags = 0;
3209
3210 if (!PyArg_ParseTuple(args, "|i:count", &flags))
3211 return NULL;
3212
3213 CHECK_CURSOR_NOT_CLOSED(self);
3214
3215 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003216 err = _DBC_count(self->dbc, &count, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003217 MYDB_END_ALLOW_THREADS;
3218 RETURN_IF_ERR();
3219
3220 return PyInt_FromLong(count);
3221}
3222
3223
3224static PyObject*
3225DBC_current(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3226{
3227 return _DBCursor_get(self,DB_CURRENT,args,kwargs,"|iii:current");
3228}
3229
3230
3231static PyObject*
3232DBC_delete(DBCursorObject* self, PyObject* args)
3233{
3234 int err, flags=0;
3235
3236 if (!PyArg_ParseTuple(args, "|i:delete", &flags))
3237 return NULL;
3238
3239 CHECK_CURSOR_NOT_CLOSED(self);
3240
3241 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003242 err = _DBC_del(self->dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003243 MYDB_END_ALLOW_THREADS;
3244 RETURN_IF_ERR();
3245
3246 self->mydb->haveStat = 0;
3247 RETURN_NONE();
3248}
3249
3250
3251static PyObject*
3252DBC_dup(DBCursorObject* self, PyObject* args)
3253{
3254 int err, flags =0;
3255 DBC* dbc = NULL;
3256
3257 if (!PyArg_ParseTuple(args, "|i:dup", &flags))
3258 return NULL;
3259
3260 CHECK_CURSOR_NOT_CLOSED(self);
3261
3262 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003263 err = _DBC_dup(self->dbc, &dbc, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003264 MYDB_END_ALLOW_THREADS;
3265 RETURN_IF_ERR();
3266
Jesus Ceaef9764f2008-05-13 18:45:46 +00003267 return (PyObject*) newDBCursorObject(dbc, self->txn, self->mydb);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003268}
3269
3270static PyObject*
3271DBC_first(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3272{
3273 return _DBCursor_get(self,DB_FIRST,args,kwargs,"|iii:first");
3274}
3275
3276
3277static PyObject*
3278DBC_get(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3279{
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00003280 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003281 PyObject* keyobj = NULL;
3282 PyObject* dataobj = NULL;
3283 PyObject* retval = NULL;
3284 int dlen = -1;
3285 int doff = -1;
3286 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003287 static char* kwnames[] = { "key","data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003288 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003289
3290 CLEAR_DBT(key);
3291 CLEAR_DBT(data);
3292 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:get", &kwnames[2],
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003293 &flags, &dlen, &doff))
3294 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003295 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003296 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:get",
3297 &kwnames[1],
3298 &keyobj, &flags, &dlen, &doff))
3299 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003300 PyErr_Clear();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003301 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:get",
3302 kwnames, &keyobj, &dataobj,
3303 &flags, &dlen, &doff))
3304 {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003305 return NULL;
3306 }
3307 }
3308 }
3309
3310 CHECK_CURSOR_NOT_CLOSED(self);
3311
3312 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3313 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003314 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3315 (!add_partial_dbt(&data, dlen, doff)) )
3316 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003317 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003318 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003319 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003320
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003321 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003322 err = _DBC_get(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003323 MYDB_END_ALLOW_THREADS;
3324
Gregory P. Smithe9477062005-06-04 06:46:59 +00003325 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3326 && self->mydb->moduleFlags.getReturnsNone) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003327 Py_INCREF(Py_None);
3328 retval = Py_None;
3329 }
3330 else if (makeDBError(err)) {
3331 retval = NULL;
3332 }
3333 else {
3334 switch (_DB_get_type(self->mydb)) {
3335 case -1:
3336 retval = NULL;
3337 break;
3338 case DB_BTREE:
3339 case DB_HASH:
3340 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003341 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003342 break;
3343 case DB_RECNO:
3344 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003345 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003346 break;
3347 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003348 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003349 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003350 return retval;
3351}
3352
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003353#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00003354static PyObject*
3355DBC_pget(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3356{
3357 int err, flags=0;
3358 PyObject* keyobj = NULL;
3359 PyObject* dataobj = NULL;
3360 PyObject* retval = NULL;
3361 int dlen = -1;
3362 int doff = -1;
3363 DBT key, pkey, data;
Gregory P. Smith372b5832006-06-05 18:48:21 +00003364 static char* kwnames_keyOnly[] = { "key", "flags", "dlen", "doff", NULL };
3365 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff", NULL };
Gregory P. Smith19699a92004-06-28 04:06:49 +00003366
3367 CLEAR_DBT(key);
3368 CLEAR_DBT(data);
3369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|ii:pget", &kwnames[2],
3370 &flags, &dlen, &doff))
3371 {
3372 PyErr_Clear();
3373 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oi|ii:pget",
Gregory P. Smith372b5832006-06-05 18:48:21 +00003374 kwnames_keyOnly,
Gregory P. Smith19699a92004-06-28 04:06:49 +00003375 &keyobj, &flags, &dlen, &doff))
3376 {
3377 PyErr_Clear();
3378 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OOi|ii:pget",
3379 kwnames, &keyobj, &dataobj,
3380 &flags, &dlen, &doff))
3381 {
3382 return NULL;
3383 }
3384 }
3385 }
3386
3387 CHECK_CURSOR_NOT_CLOSED(self);
3388
3389 if (keyobj && !make_key_dbt(self->mydb, keyobj, &key, NULL))
3390 return NULL;
3391 if ( (dataobj && !make_dbt(dataobj, &data)) ||
3392 (!add_partial_dbt(&data, dlen, doff)) ) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003393 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003394 return NULL;
3395 }
3396
Gregory P. Smith19699a92004-06-28 04:06:49 +00003397 CLEAR_DBT(pkey);
3398 pkey.flags = DB_DBT_MALLOC;
3399
3400 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003401 err = _DBC_pget(self->dbc, &key, &pkey, &data, flags);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003402 MYDB_END_ALLOW_THREADS;
3403
Gregory P. Smithe9477062005-06-04 06:46:59 +00003404 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3405 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith19699a92004-06-28 04:06:49 +00003406 Py_INCREF(Py_None);
3407 retval = Py_None;
3408 }
3409 else if (makeDBError(err)) {
3410 retval = NULL;
3411 }
3412 else {
3413 PyObject *pkeyObj;
3414 PyObject *dataObj;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003415 dataObj = Build_PyString(data.data, data.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003416
3417 if (self->mydb->primaryDBType == DB_RECNO ||
3418 self->mydb->primaryDBType == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003419 pkeyObj = PyInt_FromLong(*(int *)pkey.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003420 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003421 pkeyObj = Build_PyString(pkey.data, pkey.size);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003422
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003423 if (key.data && key.size) /* return key, pkey and data */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003424 {
3425 PyObject *keyObj;
3426 int type = _DB_get_type(self->mydb);
3427 if (type == DB_RECNO || type == DB_QUEUE)
Neal Norwitz40c6b472006-01-05 05:43:35 +00003428 keyObj = PyInt_FromLong(*(int *)key.data);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003429 else
Jesus Ceaef9764f2008-05-13 18:45:46 +00003430 keyObj = Build_PyString(key.data, key.size);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003431#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003432 retval = PyTuple_Pack(3, keyObj, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003433#else
3434 retval = Py_BuildValue("OOO", keyObj, pkeyObj, dataObj);
3435#endif
Thomas Woutersb3153832006-03-08 01:47:19 +00003436 Py_DECREF(keyObj);
Jesus Ceaef9764f2008-05-13 18:45:46 +00003437 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003438 }
3439 else /* return just the pkey and data */
3440 {
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003441#if (PY_VERSION_HEX >= 0x02040000)
Gregory P. Smith4e414d82006-01-24 19:55:02 +00003442 retval = PyTuple_Pack(2, pkeyObj, dataObj);
Gregory P. Smithfd049a62006-01-30 00:22:08 +00003443#else
3444 retval = Py_BuildValue("OO", pkeyObj, dataObj);
3445#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003446 }
Thomas Woutersb3153832006-03-08 01:47:19 +00003447 Py_DECREF(dataObj);
3448 Py_DECREF(pkeyObj);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003449 FREE_DBT(pkey);
Gregory P. Smith19699a92004-06-28 04:06:49 +00003450 }
3451 /* the only time REALLOC should be set is if we used an integer
3452 * key that make_key_dbt malloc'd for us. always free these. */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003453 if (key.flags & DB_DBT_REALLOC) { /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003454 FREE_DBT(key);
3455 }
3456 return retval;
3457}
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00003458#endif
Gregory P. Smith19699a92004-06-28 04:06:49 +00003459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003460
3461static PyObject*
3462DBC_get_recno(DBCursorObject* self, PyObject* args)
3463{
3464 int err;
3465 db_recno_t recno;
3466 DBT key;
3467 DBT data;
3468
3469 if (!PyArg_ParseTuple(args, ":get_recno"))
3470 return NULL;
3471
3472 CHECK_CURSOR_NOT_CLOSED(self);
3473
3474 CLEAR_DBT(key);
3475 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003476
3477 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003478 err = _DBC_get(self->dbc, &key, &data, DB_GET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003479 MYDB_END_ALLOW_THREADS;
3480 RETURN_IF_ERR();
3481
3482 recno = *((db_recno_t*)data.data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003483 return PyInt_FromLong(recno);
3484}
3485
3486
3487static PyObject*
3488DBC_last(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3489{
3490 return _DBCursor_get(self,DB_LAST,args,kwargs,"|iii:last");
3491}
3492
3493
3494static PyObject*
3495DBC_next(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3496{
3497 return _DBCursor_get(self,DB_NEXT,args,kwargs,"|iii:next");
3498}
3499
3500
3501static PyObject*
3502DBC_prev(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3503{
3504 return _DBCursor_get(self,DB_PREV,args,kwargs,"|iii:prev");
3505}
3506
3507
3508static PyObject*
3509DBC_put(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3510{
3511 int err, flags = 0;
3512 PyObject* keyobj, *dataobj;
3513 DBT key, data;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003514 static char* kwnames[] = { "key", "data", "flags", "dlen", "doff",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003515 NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003516 int dlen = -1;
3517 int doff = -1;
3518
3519 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|iii:put", kwnames,
3520 &keyobj, &dataobj, &flags, &dlen, &doff))
3521 return NULL;
3522
3523 CHECK_CURSOR_NOT_CLOSED(self);
3524
3525 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3526 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003527 if (!make_dbt(dataobj, &data) ||
3528 !add_partial_dbt(&data, dlen, doff) )
3529 {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003530 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003531 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003532 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003533
3534 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003535 err = _DBC_put(self->dbc, &key, &data, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003536 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003537 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003538 RETURN_IF_ERR();
3539 self->mydb->haveStat = 0;
3540 RETURN_NONE();
3541}
3542
3543
3544static PyObject*
3545DBC_set(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3546{
3547 int err, flags = 0;
3548 DBT key, data;
3549 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003550 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003551 int dlen = -1;
3552 int doff = -1;
3553
3554 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set", kwnames,
3555 &keyobj, &flags, &dlen, &doff))
3556 return NULL;
3557
3558 CHECK_CURSOR_NOT_CLOSED(self);
3559
3560 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3561 return NULL;
3562
3563 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003564 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003565 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003566 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003567 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003568
3569 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003570 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003571 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003572 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3573 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003574 Py_INCREF(Py_None);
3575 retval = Py_None;
3576 }
3577 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003578 retval = NULL;
3579 }
3580 else {
3581 switch (_DB_get_type(self->mydb)) {
3582 case -1:
3583 retval = NULL;
3584 break;
3585 case DB_BTREE:
3586 case DB_HASH:
3587 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003588 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003589 break;
3590 case DB_RECNO:
3591 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003592 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003593 break;
3594 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003595 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003596 }
Gregory P. Smith19699a92004-06-28 04:06:49 +00003597 /* the only time REALLOC should be set is if we used an integer
3598 * key that make_key_dbt malloc'd for us. always free these. */
3599 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003600 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smith19699a92004-06-28 04:06:49 +00003601 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003602
3603 return retval;
3604}
3605
3606
3607static PyObject*
3608DBC_set_range(DBCursorObject* self, PyObject* args, PyObject* kwargs)
3609{
3610 int err, flags = 0;
3611 DBT key, data;
3612 PyObject* retval, *keyobj;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003613 static char* kwnames[] = { "key", "flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003614 int dlen = -1;
3615 int doff = -1;
3616
3617 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|iii:set_range", kwnames,
3618 &keyobj, &flags, &dlen, &doff))
3619 return NULL;
3620
3621 CHECK_CURSOR_NOT_CLOSED(self);
3622
3623 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3624 return NULL;
3625
3626 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003627 if (!add_partial_dbt(&data, dlen, doff)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003628 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003629 return NULL;
3630 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003631 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003632 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RANGE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003633 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003634 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3635 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003636 Py_INCREF(Py_None);
3637 retval = Py_None;
3638 }
3639 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003640 retval = NULL;
3641 }
3642 else {
3643 switch (_DB_get_type(self->mydb)) {
3644 case -1:
3645 retval = NULL;
3646 break;
3647 case DB_BTREE:
3648 case DB_HASH:
3649 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003650 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003651 break;
3652 case DB_RECNO:
3653 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003654 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003655 break;
3656 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00003657 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003658 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003659 /* the only time REALLOC should be set is if we used an integer
Gregory P. Smith19699a92004-06-28 04:06:49 +00003660 * key that make_key_dbt malloc'd for us. always free these. */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003661 if (key.flags & DB_DBT_REALLOC) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003662 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003663 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003664
3665 return retval;
3666}
3667
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003668static PyObject*
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003669_DBC_get_set_both(DBCursorObject* self, PyObject* keyobj, PyObject* dataobj,
3670 int flags, unsigned int returnsNone)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003671{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003672 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003673 DBT key, data;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003674 PyObject* retval;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003675
Gregory P. Smith7441e652003-11-03 21:35:31 +00003676 /* the caller did this: CHECK_CURSOR_NOT_CLOSED(self); */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003677 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
3678 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003679 if (!make_dbt(dataobj, &data)) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003680 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003681 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003682 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003683
3684 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003685 err = _DBC_get(self->dbc, &key, &data, flags|DB_GET_BOTH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003686 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003687 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY) && returnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003688 Py_INCREF(Py_None);
3689 retval = Py_None;
3690 }
3691 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003692 retval = NULL;
3693 }
3694 else {
3695 switch (_DB_get_type(self->mydb)) {
3696 case -1:
3697 retval = NULL;
3698 break;
3699 case DB_BTREE:
3700 case DB_HASH:
3701 default:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003702 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003703 break;
3704 case DB_RECNO:
3705 case DB_QUEUE:
Jesus Ceaef9764f2008-05-13 18:45:46 +00003706 retval = BuildValue_IS(*((db_recno_t*)key.data), data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003707 break;
3708 }
3709 }
3710
Jesus Ceaef9764f2008-05-13 18:45:46 +00003711 FREE_DBT(key); /* 'make_key_dbt' could do a 'malloc' */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003712 return retval;
3713}
3714
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003715static PyObject*
3716DBC_get_both(DBCursorObject* self, PyObject* args)
3717{
3718 int flags=0;
3719 PyObject *keyobj, *dataobj;
3720
3721 if (!PyArg_ParseTuple(args, "OO|i:get_both", &keyobj, &dataobj, &flags))
3722 return NULL;
3723
Gregory P. Smith7441e652003-11-03 21:35:31 +00003724 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003725 CHECK_CURSOR_NOT_CLOSED(self);
3726
3727 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3728 self->mydb->moduleFlags.getReturnsNone);
3729}
3730
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003731/* Return size of entry */
3732static PyObject*
3733DBC_get_current_size(DBCursorObject* self, PyObject* args)
3734{
3735 int err, flags=DB_CURRENT;
3736 PyObject* retval = NULL;
3737 DBT key, data;
3738
3739 if (!PyArg_ParseTuple(args, ":get_current_size"))
3740 return NULL;
3741 CHECK_CURSOR_NOT_CLOSED(self);
3742 CLEAR_DBT(key);
3743 CLEAR_DBT(data);
3744
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003745 /* We don't allocate any memory, forcing a DB_BUFFER_SMALL error and thus
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003746 getting the record size. */
3747 data.flags = DB_DBT_USERMEM;
3748 data.ulen = 0;
3749 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003750 err = _DBC_get(self->dbc, &key, &data, flags);
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003751 MYDB_END_ALLOW_THREADS;
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00003752 if (err == DB_BUFFER_SMALL || !err) {
3753 /* DB_BUFFER_SMALL means positive size, !err means zero length value */
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003754 retval = PyInt_FromLong((long)data.size);
3755 err = 0;
3756 }
3757
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00003758 RETURN_IF_ERR();
3759 return retval;
3760}
3761
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003762static PyObject*
3763DBC_set_both(DBCursorObject* self, PyObject* args)
3764{
3765 int flags=0;
3766 PyObject *keyobj, *dataobj;
3767
3768 if (!PyArg_ParseTuple(args, "OO|i:set_both", &keyobj, &dataobj, &flags))
3769 return NULL;
3770
Gregory P. Smith7441e652003-11-03 21:35:31 +00003771 /* if the cursor is closed, self->mydb may be invalid */
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003772 CHECK_CURSOR_NOT_CLOSED(self);
3773
3774 return _DBC_get_set_both(self, keyobj, dataobj, flags,
3775 self->mydb->moduleFlags.cursorSetReturnsNone);
3776}
3777
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003778
3779static PyObject*
3780DBC_set_recno(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3781{
3782 int err, irecno, flags=0;
3783 db_recno_t recno;
3784 DBT key, data;
3785 PyObject* retval;
3786 int dlen = -1;
3787 int doff = -1;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003788 static char* kwnames[] = { "recno","flags", "dlen", "doff", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003789
3790 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|iii:set_recno", kwnames,
3791 &irecno, &flags, &dlen, &doff))
3792 return NULL;
3793
3794 CHECK_CURSOR_NOT_CLOSED(self);
3795
3796 CLEAR_DBT(key);
3797 recno = (db_recno_t) irecno;
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003798 /* use allocated space so DB will be able to realloc room for the real
3799 * key */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003800 key.data = malloc(sizeof(db_recno_t));
3801 if (key.data == NULL) {
3802 PyErr_SetString(PyExc_MemoryError, "Key memory allocation failed");
3803 return NULL;
3804 }
3805 key.size = sizeof(db_recno_t);
3806 key.ulen = key.size;
3807 memcpy(key.data, &recno, sizeof(db_recno_t));
3808 key.flags = DB_DBT_REALLOC;
3809
3810 CLEAR_DBT(data);
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003811 if (!add_partial_dbt(&data, dlen, doff)) {
3812 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003813 return NULL;
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003814 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003815
3816 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003817 err = _DBC_get(self->dbc, &key, &data, flags|DB_SET_RECNO);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003818 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003819 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3820 && self->mydb->moduleFlags.cursorSetReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003821 Py_INCREF(Py_None);
3822 retval = Py_None;
3823 }
3824 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003825 retval = NULL;
3826 }
3827 else { /* Can only be used for BTrees, so no need to return int key */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003828 retval = BuildValue_SS(key.data, key.size, data.data, data.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003829 }
Gregory P. Smithdc5af702004-06-27 23:32:34 +00003830 FREE_DBT(key);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003831
3832 return retval;
3833}
3834
3835
3836static PyObject*
3837DBC_consume(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3838{
3839 return _DBCursor_get(self,DB_CONSUME,args,kwargs,"|iii:consume");
3840}
3841
3842
3843static PyObject*
3844DBC_next_dup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3845{
3846 return _DBCursor_get(self,DB_NEXT_DUP,args,kwargs,"|iii:next_dup");
3847}
3848
3849
3850static PyObject*
3851DBC_next_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3852{
3853 return _DBCursor_get(self,DB_NEXT_NODUP,args,kwargs,"|iii:next_nodup");
3854}
3855
3856
3857static PyObject*
3858DBC_prev_nodup(DBCursorObject* self, PyObject* args, PyObject *kwargs)
3859{
3860 return _DBCursor_get(self,DB_PREV_NODUP,args,kwargs,"|iii:prev_nodup");
3861}
3862
3863
3864static PyObject*
3865DBC_join_item(DBCursorObject* self, PyObject* args)
3866{
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003867 int err, flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003868 DBT key, data;
3869 PyObject* retval;
3870
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003871 if (!PyArg_ParseTuple(args, "|i:join_item", &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003872 return NULL;
3873
3874 CHECK_CURSOR_NOT_CLOSED(self);
3875
3876 CLEAR_DBT(key);
3877 CLEAR_DBT(data);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003878
3879 MYDB_BEGIN_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00003880 err = _DBC_get(self->dbc, &key, &data, flags | DB_JOIN_ITEM);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003881 MYDB_END_ALLOW_THREADS;
Gregory P. Smithe9477062005-06-04 06:46:59 +00003882 if ((err == DB_NOTFOUND || err == DB_KEYEMPTY)
3883 && self->mydb->moduleFlags.getReturnsNone) {
Gregory P. Smith455d46f2003-07-09 04:45:59 +00003884 Py_INCREF(Py_None);
3885 retval = Py_None;
3886 }
3887 else if (makeDBError(err)) {
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003888 retval = NULL;
3889 }
3890 else {
Jesus Ceaef9764f2008-05-13 18:45:46 +00003891 retval = BuildValue_S(key.data, key.size);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003892 }
3893
3894 return retval;
3895}
3896
3897
3898
3899/* --------------------------------------------------------------------- */
3900/* DBEnv methods */
3901
3902
3903static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00003904DBEnv_close_internal(DBEnvObject* self, int flags)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003905{
Jesus Ceaef9764f2008-05-13 18:45:46 +00003906 PyObject *dummy;
3907 int err;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003908
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003909 if (!self->closed) { /* Don't close more than once */
Jesus Ceaef9764f2008-05-13 18:45:46 +00003910 while(self->children_txns) {
3911 dummy=DBTxn_abort_discard_internal(self->children_txns,0);
3912 Py_XDECREF(dummy);
3913 }
3914 while(self->children_dbs) {
3915 dummy=DB_close_internal(self->children_dbs,0);
3916 Py_XDECREF(dummy);
3917 }
3918
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003919 MYDB_BEGIN_ALLOW_THREADS;
3920 err = self->db_env->close(self->db_env, flags);
3921 MYDB_END_ALLOW_THREADS;
3922 /* after calling DBEnv->close, regardless of error, this DBEnv
Jesus Ceaef9764f2008-05-13 18:45:46 +00003923 * may not be accessed again (Berkeley DB docs). */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003924 self->closed = 1;
3925 self->db_env = NULL;
3926 RETURN_IF_ERR();
3927 }
3928 RETURN_NONE();
3929}
3930
Jesus Ceaef9764f2008-05-13 18:45:46 +00003931static PyObject*
3932DBEnv_close(DBEnvObject* self, PyObject* args)
3933{
3934 int flags = 0;
3935
3936 if (!PyArg_ParseTuple(args, "|i:close", &flags))
3937 return NULL;
3938 return DBEnv_close_internal(self,flags);
3939}
3940
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00003941
3942static PyObject*
3943DBEnv_open(DBEnvObject* self, PyObject* args)
3944{
3945 int err, flags=0, mode=0660;
3946 char *db_home;
3947
3948 if (!PyArg_ParseTuple(args, "z|ii:open", &db_home, &flags, &mode))
3949 return NULL;
3950
3951 CHECK_ENV_NOT_CLOSED(self);
3952
3953 MYDB_BEGIN_ALLOW_THREADS;
3954 err = self->db_env->open(self->db_env, db_home, flags, mode);
3955 MYDB_END_ALLOW_THREADS;
3956 RETURN_IF_ERR();
3957 self->closed = 0;
3958 self->flags = flags;
3959 RETURN_NONE();
3960}
3961
3962
3963static PyObject*
3964DBEnv_remove(DBEnvObject* self, PyObject* args)
3965{
3966 int err, flags=0;
3967 char *db_home;
3968
3969 if (!PyArg_ParseTuple(args, "s|i:remove", &db_home, &flags))
3970 return NULL;
3971 CHECK_ENV_NOT_CLOSED(self);
3972 MYDB_BEGIN_ALLOW_THREADS;
3973 err = self->db_env->remove(self->db_env, db_home, flags);
3974 MYDB_END_ALLOW_THREADS;
3975 RETURN_IF_ERR();
3976 RETURN_NONE();
3977}
3978
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003979#if (DBVER >= 41)
3980static PyObject*
3981DBEnv_dbremove(DBEnvObject* self, PyObject* args, PyObject* kwargs)
3982{
3983 int err;
3984 u_int32_t flags=0;
3985 char *file = NULL;
3986 char *database = NULL;
3987 PyObject *txnobj = NULL;
3988 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00003989 static char* kwnames[] = { "file", "database", "txn", "flags",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00003990 NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003991
Gregory P. Smith641cddf2006-07-28 01:35:25 +00003992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|zOi:dbremove", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00003993 &file, &database, &txnobj, &flags)) {
3994 return NULL;
3995 }
3996 if (!checkTxnObj(txnobj, &txn)) {
3997 return NULL;
3998 }
3999 CHECK_ENV_NOT_CLOSED(self);
4000 MYDB_BEGIN_ALLOW_THREADS;
4001 err = self->db_env->dbremove(self->db_env, txn, file, database, flags);
4002 MYDB_END_ALLOW_THREADS;
4003 RETURN_IF_ERR();
4004 RETURN_NONE();
4005}
4006
4007static PyObject*
4008DBEnv_dbrename(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4009{
4010 int err;
4011 u_int32_t flags=0;
4012 char *file = NULL;
4013 char *database = NULL;
4014 char *newname = NULL;
4015 PyObject *txnobj = NULL;
4016 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004017 static char* kwnames[] = { "file", "database", "newname", "txn",
Jeremy Hyltonaf68c872005-12-10 18:50:16 +00004018 "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004019
Gregory P. Smith641cddf2006-07-28 01:35:25 +00004020 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "szs|Oi:dbrename", kwnames,
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004021 &file, &database, &newname, &txnobj, &flags)) {
4022 return NULL;
4023 }
4024 if (!checkTxnObj(txnobj, &txn)) {
4025 return NULL;
4026 }
4027 CHECK_ENV_NOT_CLOSED(self);
4028 MYDB_BEGIN_ALLOW_THREADS;
4029 err = self->db_env->dbrename(self->db_env, txn, file, database, newname,
4030 flags);
4031 MYDB_END_ALLOW_THREADS;
4032 RETURN_IF_ERR();
4033 RETURN_NONE();
4034}
4035
4036static PyObject*
4037DBEnv_set_encrypt(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4038{
4039 int err;
4040 u_int32_t flags=0;
4041 char *passwd = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004042 static char* kwnames[] = { "passwd", "flags", NULL };
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004043
4044 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|i:set_encrypt", kwnames,
4045 &passwd, &flags)) {
4046 return NULL;
4047 }
4048
4049 MYDB_BEGIN_ALLOW_THREADS;
4050 err = self->db_env->set_encrypt(self->db_env, passwd, flags);
4051 MYDB_END_ALLOW_THREADS;
4052
4053 RETURN_IF_ERR();
4054 RETURN_NONE();
4055}
4056#endif /* DBVER >= 41 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004057
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004058#if (DBVER >= 40)
4059static PyObject*
4060DBEnv_set_timeout(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4061{
4062 int err;
4063 u_int32_t flags=0;
4064 u_int32_t timeout = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004065 static char* kwnames[] = { "timeout", "flags", NULL };
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00004066
4067 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii:set_timeout", kwnames,
4068 &timeout, &flags)) {
4069 return NULL;
4070 }
4071
4072 MYDB_BEGIN_ALLOW_THREADS;
4073 err = self->db_env->set_timeout(self->db_env, (db_timeout_t)timeout, flags);
4074 MYDB_END_ALLOW_THREADS;
4075
4076 RETURN_IF_ERR();
4077 RETURN_NONE();
4078}
4079#endif /* DBVER >= 40 */
4080
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004081static PyObject*
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00004082DBEnv_set_shm_key(DBEnvObject* self, PyObject* args)
4083{
4084 int err;
4085 long shm_key = 0;
4086
4087 if (!PyArg_ParseTuple(args, "l:set_shm_key", &shm_key))
4088 return NULL;
4089 CHECK_ENV_NOT_CLOSED(self);
4090
4091 err = self->db_env->set_shm_key(self->db_env, shm_key);
4092 RETURN_IF_ERR();
4093 RETURN_NONE();
4094}
4095
4096static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004097DBEnv_set_cachesize(DBEnvObject* self, PyObject* args)
4098{
4099 int err, gbytes=0, bytes=0, ncache=0;
4100
4101 if (!PyArg_ParseTuple(args, "ii|i:set_cachesize",
4102 &gbytes, &bytes, &ncache))
4103 return NULL;
4104 CHECK_ENV_NOT_CLOSED(self);
4105
4106 MYDB_BEGIN_ALLOW_THREADS;
4107 err = self->db_env->set_cachesize(self->db_env, gbytes, bytes, ncache);
4108 MYDB_END_ALLOW_THREADS;
4109 RETURN_IF_ERR();
4110 RETURN_NONE();
4111}
4112
4113
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004114static PyObject*
4115DBEnv_set_flags(DBEnvObject* self, PyObject* args)
4116{
4117 int err, flags=0, onoff=0;
4118
4119 if (!PyArg_ParseTuple(args, "ii:set_flags",
4120 &flags, &onoff))
4121 return NULL;
4122 CHECK_ENV_NOT_CLOSED(self);
4123
4124 MYDB_BEGIN_ALLOW_THREADS;
4125 err = self->db_env->set_flags(self->db_env, flags, onoff);
4126 MYDB_END_ALLOW_THREADS;
4127 RETURN_IF_ERR();
4128 RETURN_NONE();
4129}
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004130
4131
Jesus Ceaca3939c2008-05-22 15:27:38 +00004132#if (DBVER >= 47)
4133static PyObject*
4134DBEnv_log_set_config(DBEnvObject* self, PyObject* args)
4135{
4136 int err, flags, onoff;
4137
4138 if (!PyArg_ParseTuple(args, "ii:log_set_config",
4139 &flags, &onoff))
4140 return NULL;
4141 CHECK_ENV_NOT_CLOSED(self);
4142
4143 MYDB_BEGIN_ALLOW_THREADS;
4144 err = self->db_env->log_set_config(self->db_env, flags, onoff);
4145 MYDB_END_ALLOW_THREADS;
4146 RETURN_IF_ERR();
4147 RETURN_NONE();
4148}
4149#endif /* DBVER >= 47 */
4150
4151
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004152static PyObject*
4153DBEnv_set_data_dir(DBEnvObject* self, PyObject* args)
4154{
4155 int err;
4156 char *dir;
4157
4158 if (!PyArg_ParseTuple(args, "s:set_data_dir", &dir))
4159 return NULL;
4160 CHECK_ENV_NOT_CLOSED(self);
4161
4162 MYDB_BEGIN_ALLOW_THREADS;
4163 err = self->db_env->set_data_dir(self->db_env, dir);
4164 MYDB_END_ALLOW_THREADS;
4165 RETURN_IF_ERR();
4166 RETURN_NONE();
4167}
4168
4169
4170static PyObject*
4171DBEnv_set_lg_bsize(DBEnvObject* self, PyObject* args)
4172{
4173 int err, lg_bsize;
4174
4175 if (!PyArg_ParseTuple(args, "i:set_lg_bsize", &lg_bsize))
4176 return NULL;
4177 CHECK_ENV_NOT_CLOSED(self);
4178
4179 MYDB_BEGIN_ALLOW_THREADS;
4180 err = self->db_env->set_lg_bsize(self->db_env, lg_bsize);
4181 MYDB_END_ALLOW_THREADS;
4182 RETURN_IF_ERR();
4183 RETURN_NONE();
4184}
4185
4186
4187static PyObject*
4188DBEnv_set_lg_dir(DBEnvObject* self, PyObject* args)
4189{
4190 int err;
4191 char *dir;
4192
4193 if (!PyArg_ParseTuple(args, "s:set_lg_dir", &dir))
4194 return NULL;
4195 CHECK_ENV_NOT_CLOSED(self);
4196
4197 MYDB_BEGIN_ALLOW_THREADS;
4198 err = self->db_env->set_lg_dir(self->db_env, dir);
4199 MYDB_END_ALLOW_THREADS;
4200 RETURN_IF_ERR();
4201 RETURN_NONE();
4202}
4203
4204static PyObject*
4205DBEnv_set_lg_max(DBEnvObject* self, PyObject* args)
4206{
4207 int err, lg_max;
4208
4209 if (!PyArg_ParseTuple(args, "i:set_lg_max", &lg_max))
4210 return NULL;
4211 CHECK_ENV_NOT_CLOSED(self);
4212
4213 MYDB_BEGIN_ALLOW_THREADS;
4214 err = self->db_env->set_lg_max(self->db_env, lg_max);
4215 MYDB_END_ALLOW_THREADS;
4216 RETURN_IF_ERR();
4217 RETURN_NONE();
4218}
4219
Jesus Ceaef9764f2008-05-13 18:45:46 +00004220#if (DBVER >= 42)
4221static PyObject*
4222DBEnv_get_lg_max(DBEnvObject* self, PyObject* args)
4223{
4224 int err;
4225 u_int32_t lg_max;
4226
4227 if (!PyArg_ParseTuple(args, ":get_lg_max"))
4228 return NULL;
4229 CHECK_ENV_NOT_CLOSED(self);
4230
4231 MYDB_BEGIN_ALLOW_THREADS;
4232 err = self->db_env->get_lg_max(self->db_env, &lg_max);
4233 MYDB_END_ALLOW_THREADS;
4234 RETURN_IF_ERR();
4235 return PyInt_FromLong(lg_max);
4236}
4237#endif
4238
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004239
Neal Norwitz84562352005-10-20 04:30:15 +00004240#if (DBVER >= 33)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004241static PyObject*
Gregory P. Smithe9477062005-06-04 06:46:59 +00004242DBEnv_set_lg_regionmax(DBEnvObject* self, PyObject* args)
4243{
4244 int err, lg_max;
4245
4246 if (!PyArg_ParseTuple(args, "i:set_lg_regionmax", &lg_max))
4247 return NULL;
4248 CHECK_ENV_NOT_CLOSED(self);
4249
4250 MYDB_BEGIN_ALLOW_THREADS;
4251 err = self->db_env->set_lg_regionmax(self->db_env, lg_max);
4252 MYDB_END_ALLOW_THREADS;
4253 RETURN_IF_ERR();
4254 RETURN_NONE();
4255}
Neal Norwitz84562352005-10-20 04:30:15 +00004256#endif
Gregory P. Smithe9477062005-06-04 06:46:59 +00004257
4258
4259static PyObject*
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004260DBEnv_set_lk_detect(DBEnvObject* self, PyObject* args)
4261{
4262 int err, lk_detect;
4263
4264 if (!PyArg_ParseTuple(args, "i:set_lk_detect", &lk_detect))
4265 return NULL;
4266 CHECK_ENV_NOT_CLOSED(self);
4267
4268 MYDB_BEGIN_ALLOW_THREADS;
4269 err = self->db_env->set_lk_detect(self->db_env, lk_detect);
4270 MYDB_END_ALLOW_THREADS;
4271 RETURN_IF_ERR();
4272 RETURN_NONE();
4273}
4274
4275
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004276#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004277static PyObject*
4278DBEnv_set_lk_max(DBEnvObject* self, PyObject* args)
4279{
4280 int err, max;
4281
4282 if (!PyArg_ParseTuple(args, "i:set_lk_max", &max))
4283 return NULL;
4284 CHECK_ENV_NOT_CLOSED(self);
4285
4286 MYDB_BEGIN_ALLOW_THREADS;
4287 err = self->db_env->set_lk_max(self->db_env, max);
4288 MYDB_END_ALLOW_THREADS;
4289 RETURN_IF_ERR();
4290 RETURN_NONE();
4291}
Gregory P. Smith8b96a352007-01-05 01:59:42 +00004292#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004293
4294
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004295
4296static PyObject*
4297DBEnv_set_lk_max_locks(DBEnvObject* self, PyObject* args)
4298{
4299 int err, max;
4300
4301 if (!PyArg_ParseTuple(args, "i:set_lk_max_locks", &max))
4302 return NULL;
4303 CHECK_ENV_NOT_CLOSED(self);
4304
4305 MYDB_BEGIN_ALLOW_THREADS;
4306 err = self->db_env->set_lk_max_locks(self->db_env, max);
4307 MYDB_END_ALLOW_THREADS;
4308 RETURN_IF_ERR();
4309 RETURN_NONE();
4310}
4311
4312
4313static PyObject*
4314DBEnv_set_lk_max_lockers(DBEnvObject* self, PyObject* args)
4315{
4316 int err, max;
4317
4318 if (!PyArg_ParseTuple(args, "i:set_lk_max_lockers", &max))
4319 return NULL;
4320 CHECK_ENV_NOT_CLOSED(self);
4321
4322 MYDB_BEGIN_ALLOW_THREADS;
4323 err = self->db_env->set_lk_max_lockers(self->db_env, max);
4324 MYDB_END_ALLOW_THREADS;
4325 RETURN_IF_ERR();
4326 RETURN_NONE();
4327}
4328
4329
4330static PyObject*
4331DBEnv_set_lk_max_objects(DBEnvObject* self, PyObject* args)
4332{
4333 int err, max;
4334
4335 if (!PyArg_ParseTuple(args, "i:set_lk_max_objects", &max))
4336 return NULL;
4337 CHECK_ENV_NOT_CLOSED(self);
4338
4339 MYDB_BEGIN_ALLOW_THREADS;
4340 err = self->db_env->set_lk_max_objects(self->db_env, max);
4341 MYDB_END_ALLOW_THREADS;
4342 RETURN_IF_ERR();
4343 RETURN_NONE();
4344}
4345
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004346
4347static PyObject*
4348DBEnv_set_mp_mmapsize(DBEnvObject* self, PyObject* args)
4349{
4350 int err, mp_mmapsize;
4351
4352 if (!PyArg_ParseTuple(args, "i:set_mp_mmapsize", &mp_mmapsize))
4353 return NULL;
4354 CHECK_ENV_NOT_CLOSED(self);
4355
4356 MYDB_BEGIN_ALLOW_THREADS;
4357 err = self->db_env->set_mp_mmapsize(self->db_env, mp_mmapsize);
4358 MYDB_END_ALLOW_THREADS;
4359 RETURN_IF_ERR();
4360 RETURN_NONE();
4361}
4362
4363
4364static PyObject*
4365DBEnv_set_tmp_dir(DBEnvObject* self, PyObject* args)
4366{
4367 int err;
4368 char *dir;
4369
4370 if (!PyArg_ParseTuple(args, "s:set_tmp_dir", &dir))
4371 return NULL;
4372 CHECK_ENV_NOT_CLOSED(self);
4373
4374 MYDB_BEGIN_ALLOW_THREADS;
4375 err = self->db_env->set_tmp_dir(self->db_env, dir);
4376 MYDB_END_ALLOW_THREADS;
4377 RETURN_IF_ERR();
4378 RETURN_NONE();
4379}
4380
4381
Jesus Ceaef9764f2008-05-13 18:45:46 +00004382#if (DBVER >= 40)
4383static PyObject*
4384DBEnv_txn_recover(DBEnvObject* self, PyObject* args)
4385{
4386 int flags = DB_FIRST;
4387 int err, i;
4388 PyObject *list, *tuple, *gid;
4389 DBTxnObject *txn;
4390#define PREPLIST_LEN 16
4391 DB_PREPLIST preplist[PREPLIST_LEN];
4392 long retp;
4393
4394 if (!PyArg_ParseTuple(args, ":txn_recover"))
4395 return NULL;
4396
4397 CHECK_ENV_NOT_CLOSED(self);
4398
4399 list=PyList_New(0);
4400 if (!list)
4401 return NULL;
4402 while (!0) {
4403 MYDB_BEGIN_ALLOW_THREADS
4404 err=self->db_env->txn_recover(self->db_env,
4405 preplist, PREPLIST_LEN, &retp, flags);
4406#undef PREPLIST_LEN
4407 MYDB_END_ALLOW_THREADS
4408 if (err) {
4409 Py_DECREF(list);
4410 RETURN_IF_ERR();
4411 }
4412 if (!retp) break;
4413 flags=DB_NEXT; /* Prepare for next loop pass */
4414 for (i=0; i<retp; i++) {
4415 gid=PyString_FromStringAndSize((char *)(preplist[i].gid),
4416 DB_XIDDATASIZE);
4417 if (!gid) {
4418 Py_DECREF(list);
4419 return NULL;
4420 }
4421 txn=newDBTxnObject(self, NULL, preplist[i].txn, flags);
4422 if (!txn) {
4423 Py_DECREF(list);
4424 Py_DECREF(gid);
4425 return NULL;
4426 }
4427 txn->flag_prepare=1; /* Recover state */
4428 tuple=PyTuple_New(2);
4429 if (!tuple) {
4430 Py_DECREF(list);
4431 Py_DECREF(gid);
4432 Py_DECREF(txn);
4433 return NULL;
4434 }
4435 if (PyTuple_SetItem(tuple, 0, gid)) {
4436 Py_DECREF(list);
4437 Py_DECREF(gid);
4438 Py_DECREF(txn);
4439 Py_DECREF(tuple);
4440 return NULL;
4441 }
4442 if (PyTuple_SetItem(tuple, 1, (PyObject *)txn)) {
4443 Py_DECREF(list);
4444 Py_DECREF(txn);
4445 Py_DECREF(tuple); /* This delete the "gid" also */
4446 return NULL;
4447 }
4448 if (PyList_Append(list, tuple)) {
4449 Py_DECREF(list);
4450 Py_DECREF(tuple);/* This delete the "gid" and the "txn" also */
4451 return NULL;
4452 }
4453 Py_DECREF(tuple);
4454 }
4455 }
4456 return list;
4457}
4458#endif
4459
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004460static PyObject*
4461DBEnv_txn_begin(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4462{
4463 int flags = 0;
4464 PyObject* txnobj = NULL;
4465 DB_TXN *txn = NULL;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00004466 static char* kwnames[] = { "parent", "flags", NULL };
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004467
4468 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:txn_begin", kwnames,
4469 &txnobj, &flags))
4470 return NULL;
4471
4472 if (!checkTxnObj(txnobj, &txn))
4473 return NULL;
4474 CHECK_ENV_NOT_CLOSED(self);
4475
Jesus Ceaef9764f2008-05-13 18:45:46 +00004476 return (PyObject*)newDBTxnObject(self, (DBTxnObject *)txnobj, NULL, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004477}
4478
4479
4480static PyObject*
4481DBEnv_txn_checkpoint(DBEnvObject* self, PyObject* args)
4482{
4483 int err, kbyte=0, min=0, flags=0;
4484
4485 if (!PyArg_ParseTuple(args, "|iii:txn_checkpoint", &kbyte, &min, &flags))
4486 return NULL;
4487 CHECK_ENV_NOT_CLOSED(self);
4488
4489 MYDB_BEGIN_ALLOW_THREADS;
4490#if (DBVER >= 40)
4491 err = self->db_env->txn_checkpoint(self->db_env, kbyte, min, flags);
4492#else
4493 err = txn_checkpoint(self->db_env, kbyte, min, flags);
4494#endif
4495 MYDB_END_ALLOW_THREADS;
4496 RETURN_IF_ERR();
4497 RETURN_NONE();
4498}
4499
4500
4501static PyObject*
4502DBEnv_set_tx_max(DBEnvObject* self, PyObject* args)
4503{
4504 int err, max;
4505
4506 if (!PyArg_ParseTuple(args, "i:set_tx_max", &max))
4507 return NULL;
4508 CHECK_ENV_NOT_CLOSED(self);
4509
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004510 err = self->db_env->set_tx_max(self->db_env, max);
Gregory P. Smith8a474042006-01-27 07:05:40 +00004511 RETURN_IF_ERR();
4512 RETURN_NONE();
4513}
4514
4515
4516static PyObject*
4517DBEnv_set_tx_timestamp(DBEnvObject* self, PyObject* args)
4518{
4519 int err;
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004520 long stamp;
4521 time_t timestamp;
Gregory P. Smith8a474042006-01-27 07:05:40 +00004522
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004523 if (!PyArg_ParseTuple(args, "l:set_tx_timestamp", &stamp))
Gregory P. Smith8a474042006-01-27 07:05:40 +00004524 return NULL;
4525 CHECK_ENV_NOT_CLOSED(self);
Thomas Wouters9d63cca2006-03-01 01:01:55 +00004526 timestamp = (time_t)stamp;
4527 err = self->db_env->set_tx_timestamp(self->db_env, &timestamp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004528 RETURN_IF_ERR();
4529 RETURN_NONE();
4530}
4531
4532
4533static PyObject*
4534DBEnv_lock_detect(DBEnvObject* self, PyObject* args)
4535{
4536 int err, atype, flags=0;
4537 int aborted = 0;
4538
4539 if (!PyArg_ParseTuple(args, "i|i:lock_detect", &atype, &flags))
4540 return NULL;
4541 CHECK_ENV_NOT_CLOSED(self);
4542
4543 MYDB_BEGIN_ALLOW_THREADS;
4544#if (DBVER >= 40)
4545 err = self->db_env->lock_detect(self->db_env, flags, atype, &aborted);
4546#else
4547 err = lock_detect(self->db_env, flags, atype, &aborted);
4548#endif
4549 MYDB_END_ALLOW_THREADS;
4550 RETURN_IF_ERR();
4551 return PyInt_FromLong(aborted);
4552}
4553
4554
4555static PyObject*
4556DBEnv_lock_get(DBEnvObject* self, PyObject* args)
4557{
4558 int flags=0;
4559 int locker, lock_mode;
4560 DBT obj;
4561 PyObject* objobj;
4562
4563 if (!PyArg_ParseTuple(args, "iOi|i:lock_get", &locker, &objobj, &lock_mode, &flags))
4564 return NULL;
4565
4566
4567 if (!make_dbt(objobj, &obj))
4568 return NULL;
4569
4570 return (PyObject*)newDBLockObject(self, locker, &obj, lock_mode, flags);
4571}
4572
4573
4574static PyObject*
4575DBEnv_lock_id(DBEnvObject* self, PyObject* args)
4576{
4577 int err;
4578 u_int32_t theID;
4579
4580 if (!PyArg_ParseTuple(args, ":lock_id"))
4581 return NULL;
4582
4583 CHECK_ENV_NOT_CLOSED(self);
4584 MYDB_BEGIN_ALLOW_THREADS;
4585#if (DBVER >= 40)
4586 err = self->db_env->lock_id(self->db_env, &theID);
4587#else
4588 err = lock_id(self->db_env, &theID);
4589#endif
4590 MYDB_END_ALLOW_THREADS;
4591 RETURN_IF_ERR();
4592
4593 return PyInt_FromLong((long)theID);
4594}
4595
Gregory P. Smithac11e022007-11-05 02:56:31 +00004596#if (DBVER >= 40)
4597static PyObject*
4598DBEnv_lock_id_free(DBEnvObject* self, PyObject* args)
4599{
4600 int err;
4601 u_int32_t theID;
4602
4603 if (!PyArg_ParseTuple(args, "I:lock_id_free", &theID))
4604 return NULL;
4605
4606 CHECK_ENV_NOT_CLOSED(self);
4607 MYDB_BEGIN_ALLOW_THREADS;
4608 err = self->db_env->lock_id_free(self->db_env, theID);
4609 MYDB_END_ALLOW_THREADS;
4610 RETURN_IF_ERR();
4611 RETURN_NONE();
4612}
4613#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004614
4615static PyObject*
4616DBEnv_lock_put(DBEnvObject* self, PyObject* args)
4617{
4618 int err;
4619 DBLockObject* dblockobj;
4620
4621 if (!PyArg_ParseTuple(args, "O!:lock_put", &DBLock_Type, &dblockobj))
4622 return NULL;
4623
4624 CHECK_ENV_NOT_CLOSED(self);
4625 MYDB_BEGIN_ALLOW_THREADS;
4626#if (DBVER >= 40)
4627 err = self->db_env->lock_put(self->db_env, &dblockobj->lock);
4628#else
4629 err = lock_put(self->db_env, &dblockobj->lock);
4630#endif
4631 MYDB_END_ALLOW_THREADS;
4632 RETURN_IF_ERR();
4633 RETURN_NONE();
4634}
4635
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00004636#if (DBVER >= 44)
4637static PyObject*
4638DBEnv_lsn_reset(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4639{
4640 int err;
4641 char *file;
4642 u_int32_t flags = 0;
4643 static char* kwnames[] = { "file", "flags", NULL};
4644
4645 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|i:lsn_reset", kwnames,
4646 &file, &flags))
4647 return NULL;
4648 CHECK_ENV_NOT_CLOSED(self);
4649
4650 MYDB_BEGIN_ALLOW_THREADS;
4651 err = self->db_env->lsn_reset(self->db_env, file, flags);
4652 MYDB_END_ALLOW_THREADS;
4653 RETURN_IF_ERR();
4654 RETURN_NONE();
4655}
4656#endif /* DBVER >= 4.4 */
4657
Gregory P. Smith76a82e82006-06-05 01:39:52 +00004658#if (DBVER >= 40)
4659static PyObject*
4660DBEnv_log_stat(DBEnvObject* self, PyObject* args)
4661{
4662 int err;
4663 DB_LOG_STAT* statp = NULL;
4664 PyObject* d = NULL;
4665 u_int32_t flags = 0;
4666
4667 if (!PyArg_ParseTuple(args, "|i:log_stat", &flags))
4668 return NULL;
4669 CHECK_ENV_NOT_CLOSED(self);
4670
4671 MYDB_BEGIN_ALLOW_THREADS;
4672 err = self->db_env->log_stat(self->db_env, &statp, flags);
4673 MYDB_END_ALLOW_THREADS;
4674 RETURN_IF_ERR();
4675
4676 /* Turn the stat structure into a dictionary */
4677 d = PyDict_New();
4678 if (d == NULL) {
4679 if (statp)
4680 free(statp);
4681 return NULL;
4682 }
4683
4684#define MAKE_ENTRY(name) _addIntToDict(d, #name, statp->st_##name)
4685
4686 MAKE_ENTRY(magic);
4687 MAKE_ENTRY(version);
4688 MAKE_ENTRY(mode);
4689 MAKE_ENTRY(lg_bsize);
4690#if (DBVER >= 44)
4691 MAKE_ENTRY(lg_size);
4692 MAKE_ENTRY(record);
4693#endif
4694#if (DBVER <= 40)
4695 MAKE_ENTRY(lg_max);
4696#endif
4697 MAKE_ENTRY(w_mbytes);
4698 MAKE_ENTRY(w_bytes);
4699 MAKE_ENTRY(wc_mbytes);
4700 MAKE_ENTRY(wc_bytes);
4701 MAKE_ENTRY(wcount);
4702 MAKE_ENTRY(wcount_fill);
4703#if (DBVER >= 44)
4704 MAKE_ENTRY(rcount);
4705#endif
4706 MAKE_ENTRY(scount);
4707 MAKE_ENTRY(cur_file);
4708 MAKE_ENTRY(cur_offset);
4709 MAKE_ENTRY(disk_file);
4710 MAKE_ENTRY(disk_offset);
4711 MAKE_ENTRY(maxcommitperflush);
4712 MAKE_ENTRY(mincommitperflush);
4713 MAKE_ENTRY(regsize);
4714 MAKE_ENTRY(region_wait);
4715 MAKE_ENTRY(region_nowait);
4716
4717#undef MAKE_ENTRY
4718 free(statp);
4719 return d;
4720} /* DBEnv_log_stat */
4721#endif /* DBVER >= 4.0 for log_stat method */
4722
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004723
4724static PyObject*
4725DBEnv_lock_stat(DBEnvObject* self, PyObject* args)
4726{
4727 int err;
4728 DB_LOCK_STAT* sp;
4729 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004730 u_int32_t flags = 0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004731
4732 if (!PyArg_ParseTuple(args, "|i:lock_stat", &flags))
4733 return NULL;
4734 CHECK_ENV_NOT_CLOSED(self);
4735
4736 MYDB_BEGIN_ALLOW_THREADS;
4737#if (DBVER >= 40)
4738 err = self->db_env->lock_stat(self->db_env, &sp, flags);
4739#else
4740#if (DBVER >= 33)
4741 err = lock_stat(self->db_env, &sp);
4742#else
4743 err = lock_stat(self->db_env, &sp, NULL);
4744#endif
4745#endif
4746 MYDB_END_ALLOW_THREADS;
4747 RETURN_IF_ERR();
4748
4749 /* Turn the stat structure into a dictionary */
4750 d = PyDict_New();
4751 if (d == NULL) {
4752 free(sp);
4753 return NULL;
4754 }
4755
4756#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4757
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004758#if (DBVER < 41)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004759 MAKE_ENTRY(lastid);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00004760#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004761#if (DBVER >=41)
4762 MAKE_ENTRY(id);
4763 MAKE_ENTRY(cur_maxid);
4764#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004765 MAKE_ENTRY(nmodes);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004766 MAKE_ENTRY(maxlocks);
4767 MAKE_ENTRY(maxlockers);
4768 MAKE_ENTRY(maxobjects);
4769 MAKE_ENTRY(nlocks);
4770 MAKE_ENTRY(maxnlocks);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004771 MAKE_ENTRY(nlockers);
4772 MAKE_ENTRY(maxnlockers);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004773 MAKE_ENTRY(nobjects);
4774 MAKE_ENTRY(maxnobjects);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004775 MAKE_ENTRY(nrequests);
4776 MAKE_ENTRY(nreleases);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004777#if (DBVER >= 44)
4778 MAKE_ENTRY(nupgrade);
4779 MAKE_ENTRY(ndowngrade);
4780#endif
Gregory P. Smith29602d22006-01-24 09:46:48 +00004781#if (DBVER < 44)
4782 MAKE_ENTRY(nnowaits); /* these were renamed in 4.4 */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004783 MAKE_ENTRY(nconflicts);
Gregory P. Smith29602d22006-01-24 09:46:48 +00004784#else
4785 MAKE_ENTRY(lock_nowait);
4786 MAKE_ENTRY(lock_wait);
4787#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004788 MAKE_ENTRY(ndeadlocks);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004789#if (DBVER >= 41)
4790 MAKE_ENTRY(locktimeout);
4791 MAKE_ENTRY(txntimeout);
4792#endif
4793#if (DBVER >= 40)
4794 MAKE_ENTRY(nlocktimeouts);
4795 MAKE_ENTRY(ntxntimeouts);
4796#endif
4797#if (DBVER >= 46)
4798 MAKE_ENTRY(objs_wait);
4799 MAKE_ENTRY(objs_nowait);
4800 MAKE_ENTRY(lockers_wait);
4801 MAKE_ENTRY(lockers_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004802#if (DBVER >= 47)
4803 MAKE_ENTRY(lock_wait);
4804 MAKE_ENTRY(lock_nowait);
4805#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00004806 MAKE_ENTRY(locks_wait);
4807 MAKE_ENTRY(locks_nowait);
Jesus Ceaca3939c2008-05-22 15:27:38 +00004808#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00004809 MAKE_ENTRY(hash_len);
4810#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004811 MAKE_ENTRY(regsize);
4812 MAKE_ENTRY(region_wait);
4813 MAKE_ENTRY(region_nowait);
4814
4815#undef MAKE_ENTRY
4816 free(sp);
4817 return d;
4818}
4819
Jesus Ceaef9764f2008-05-13 18:45:46 +00004820#if (DBVER >= 40)
4821static PyObject*
4822DBEnv_log_flush(DBEnvObject* self, PyObject* args)
4823{
4824 int err;
4825
4826 if (!PyArg_ParseTuple(args, ":log_flush"))
4827 return NULL;
4828 CHECK_ENV_NOT_CLOSED(self);
4829
4830 MYDB_BEGIN_ALLOW_THREADS
4831 err = self->db_env->log_flush(self->db_env, NULL);
4832 MYDB_END_ALLOW_THREADS
4833
4834 RETURN_IF_ERR();
4835 RETURN_NONE();
4836}
4837#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004838
4839static PyObject*
4840DBEnv_log_archive(DBEnvObject* self, PyObject* args)
4841{
4842 int flags=0;
4843 int err;
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004844 char **log_list = NULL;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004845 PyObject* list;
4846 PyObject* item = NULL;
4847
4848 if (!PyArg_ParseTuple(args, "|i:log_archive", &flags))
4849 return NULL;
4850
4851 CHECK_ENV_NOT_CLOSED(self);
4852 MYDB_BEGIN_ALLOW_THREADS;
4853#if (DBVER >= 40)
4854 err = self->db_env->log_archive(self->db_env, &log_list, flags);
4855#elif (DBVER == 33)
4856 err = log_archive(self->db_env, &log_list, flags);
4857#else
4858 err = log_archive(self->db_env, &log_list, flags, NULL);
4859#endif
4860 MYDB_END_ALLOW_THREADS;
4861 RETURN_IF_ERR();
4862
Gregory P. Smithbad47452006-06-05 00:33:35 +00004863 list = PyList_New(0);
4864 if (list == NULL) {
4865 if (log_list)
4866 free(log_list);
4867 return NULL;
4868 }
4869
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004870 if (log_list) {
Gregory P. Smith3dd20022006-06-05 00:31:01 +00004871 char **log_list_start;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004872 for (log_list_start = log_list; *log_list != NULL; ++log_list) {
4873 item = PyString_FromString (*log_list);
4874 if (item == NULL) {
4875 Py_DECREF(list);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004876 list = NULL;
4877 break;
4878 }
4879 PyList_Append(list, item);
4880 Py_DECREF(item);
4881 }
4882 free(log_list_start);
4883 }
4884 return list;
4885}
4886
4887
4888static PyObject*
4889DBEnv_txn_stat(DBEnvObject* self, PyObject* args)
4890{
4891 int err;
4892 DB_TXN_STAT* sp;
4893 PyObject* d = NULL;
Martin v. Löwisb2c7aff2002-11-23 11:26:07 +00004894 u_int32_t flags=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004895
4896 if (!PyArg_ParseTuple(args, "|i:txn_stat", &flags))
4897 return NULL;
4898 CHECK_ENV_NOT_CLOSED(self);
4899
4900 MYDB_BEGIN_ALLOW_THREADS;
4901#if (DBVER >= 40)
4902 err = self->db_env->txn_stat(self->db_env, &sp, flags);
4903#elif (DBVER == 33)
4904 err = txn_stat(self->db_env, &sp);
4905#else
4906 err = txn_stat(self->db_env, &sp, NULL);
4907#endif
4908 MYDB_END_ALLOW_THREADS;
4909 RETURN_IF_ERR();
4910
4911 /* Turn the stat structure into a dictionary */
4912 d = PyDict_New();
4913 if (d == NULL) {
4914 free(sp);
4915 return NULL;
4916 }
4917
Jesus Ceaef9764f2008-05-13 18:45:46 +00004918#define MAKE_ENTRY(name) _addIntToDict(d, #name, sp->st_##name)
4919#define MAKE_TIME_T_ENTRY(name) _addTimeTToDict(d, #name, sp->st_##name)
4920#define MAKE_DB_LSN_ENTRY(name) _addDB_lsnToDict(d, #name, sp->st_##name)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004921
Jesus Ceaef9764f2008-05-13 18:45:46 +00004922#if (DBVER >= 40)
4923 MAKE_DB_LSN_ENTRY(last_ckp);
4924#endif
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004925 MAKE_TIME_T_ENTRY(time_ckp);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004926 MAKE_ENTRY(last_txnid);
4927 MAKE_ENTRY(maxtxns);
4928 MAKE_ENTRY(nactive);
4929 MAKE_ENTRY(maxnactive);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004930#if (DBVER >= 45)
4931 MAKE_ENTRY(nsnapshot);
4932 MAKE_ENTRY(maxnsnapshot);
4933#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004934 MAKE_ENTRY(nbegins);
4935 MAKE_ENTRY(naborts);
4936 MAKE_ENTRY(ncommits);
Jesus Ceaef9764f2008-05-13 18:45:46 +00004937#if (DBVER >= 40)
4938 MAKE_ENTRY(nrestores);
4939#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004940 MAKE_ENTRY(regsize);
4941 MAKE_ENTRY(region_wait);
4942 MAKE_ENTRY(region_nowait);
4943
Jesus Ceaef9764f2008-05-13 18:45:46 +00004944#undef MAKE_DB_LSN_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004945#undef MAKE_ENTRY
Kristján Valur Jónssonbd77c032007-04-26 15:24:54 +00004946#undef MAKE_TIME_T_ENTRY
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004947 free(sp);
4948 return d;
4949}
4950
4951
4952static PyObject*
4953DBEnv_set_get_returns_none(DBEnvObject* self, PyObject* args)
4954{
4955 int flags=0;
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004956 int oldValue=0;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004957
4958 if (!PyArg_ParseTuple(args,"i:set_get_returns_none", &flags))
4959 return NULL;
4960 CHECK_ENV_NOT_CLOSED(self);
4961
Gregory P. Smith455d46f2003-07-09 04:45:59 +00004962 if (self->moduleFlags.getReturnsNone)
4963 ++oldValue;
4964 if (self->moduleFlags.cursorSetReturnsNone)
4965 ++oldValue;
4966 self->moduleFlags.getReturnsNone = (flags >= 1);
4967 self->moduleFlags.cursorSetReturnsNone = (flags >= 2);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00004968 return PyInt_FromLong(oldValue);
4969}
4970
Jesus Ceaef9764f2008-05-13 18:45:46 +00004971#if (DBVER >= 40)
4972static PyObject*
Jesus Ceaca3939c2008-05-22 15:27:38 +00004973DBEnv_set_rpc_server(DBEnvObject* self, PyObject* args, PyObject* kwargs)
4974{
4975 int err;
4976 char *host;
4977 long cl_timeout=0, sv_timeout=0;
4978
4979 static char* kwnames[] = { "host", "cl_timeout", "sv_timeout", NULL};
4980
4981 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ll:set_rpc_server", kwnames,
4982 &host, &cl_timeout, &sv_timeout))
4983 return NULL;
4984 CHECK_ENV_NOT_CLOSED(self);
4985
4986 MYDB_BEGIN_ALLOW_THREADS;
4987 err = self->db_env->set_rpc_server(self->db_env, NULL, host, cl_timeout,
4988 sv_timeout, 0);
4989 MYDB_END_ALLOW_THREADS;
4990 RETURN_IF_ERR();
4991 RETURN_NONE();
4992}
4993#endif
4994
4995#if (DBVER >= 40)
4996static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00004997DBEnv_set_verbose(DBEnvObject* self, PyObject* args)
4998{
4999 int err;
5000 int which, onoff;
5001
5002 if (!PyArg_ParseTuple(args, "ii:set_verbose", &which, &onoff)) {
5003 return NULL;
5004 }
5005 CHECK_ENV_NOT_CLOSED(self);
5006 MYDB_BEGIN_ALLOW_THREADS;
5007 err = self->db_env->set_verbose(self->db_env, which, onoff);
5008 MYDB_END_ALLOW_THREADS;
5009 RETURN_IF_ERR();
5010 RETURN_NONE();
5011}
5012
5013#if (DBVER >= 42)
5014static PyObject*
5015DBEnv_get_verbose(DBEnvObject* self, PyObject* args)
5016{
5017 int err;
5018 int which;
5019 int verbose;
5020
5021 if (!PyArg_ParseTuple(args, "i:get_verbose", &which)) {
5022 return NULL;
5023 }
5024 CHECK_ENV_NOT_CLOSED(self);
5025 MYDB_BEGIN_ALLOW_THREADS;
5026 err = self->db_env->get_verbose(self->db_env, which, &verbose);
5027 MYDB_END_ALLOW_THREADS;
5028 RETURN_IF_ERR();
5029 return PyBool_FromLong(verbose);
5030}
5031#endif
5032#endif
5033
5034#if (DBVER >= 45)
5035static void
5036_dbenv_event_notifyCallback(DB_ENV* db_env, u_int32_t event, void *event_info)
5037{
5038 DBEnvObject *dbenv;
5039 PyObject* callback;
5040 PyObject* args;
5041 PyObject* result = NULL;
5042
5043 MYDB_BEGIN_BLOCK_THREADS;
5044 dbenv = (DBEnvObject *)db_env->app_private;
5045 callback = dbenv->event_notifyCallback;
5046 if (callback) {
5047 if (event == DB_EVENT_REP_NEWMASTER) {
5048 args = Py_BuildValue("(Oii)", dbenv, event, *((int *)event_info));
5049 } else {
5050 args = Py_BuildValue("(OiO)", dbenv, event, Py_None);
5051 }
5052 if (args) {
5053 result = PyEval_CallObject(callback, args);
5054 }
5055 if ((!args) || (!result)) {
5056 PyErr_Print();
5057 }
5058 Py_XDECREF(args);
5059 Py_XDECREF(result);
5060 }
5061 MYDB_END_BLOCK_THREADS;
5062}
5063#endif
5064
5065#if (DBVER >= 45)
5066static PyObject*
5067DBEnv_set_event_notify(DBEnvObject* self, PyObject* args)
5068{
5069 int err;
5070 PyObject *notifyFunc;
5071
5072 if (!PyArg_ParseTuple(args, "O:set_event_notify", &notifyFunc)) {
5073 return NULL;
5074 }
5075
5076 CHECK_ENV_NOT_CLOSED(self);
5077
5078 if (!PyCallable_Check(notifyFunc)) {
5079 makeTypeError("Callable", notifyFunc);
5080 return NULL;
5081 }
5082
5083 Py_XDECREF(self->event_notifyCallback);
5084 Py_INCREF(notifyFunc);
5085 self->event_notifyCallback = notifyFunc;
5086
5087 MYDB_BEGIN_ALLOW_THREADS;
5088 err = self->db_env->set_event_notify(self->db_env, _dbenv_event_notifyCallback);
5089 MYDB_END_ALLOW_THREADS;
5090
5091 if (err) {
5092 Py_DECREF(notifyFunc);
5093 self->event_notifyCallback = NULL;
5094 }
5095
5096 RETURN_IF_ERR();
5097 RETURN_NONE();
5098}
5099#endif
5100
5101
5102/* --------------------------------------------------------------------- */
5103/* REPLICATION METHODS: Base Replication */
5104
5105#if (DBVER >= 45)
5106static PyObject*
5107DBEnv_rep_set_nsites(DBEnvObject* self, PyObject* args)
5108{
5109 int err;
5110 int nsites;
5111
5112 if (!PyArg_ParseTuple(args, "i:rep_set_nsites", &nsites)) {
5113 return NULL;
5114 }
5115 CHECK_ENV_NOT_CLOSED(self);
5116 MYDB_BEGIN_ALLOW_THREADS;
5117 err = self->db_env->rep_set_nsites(self->db_env, nsites);
5118 MYDB_END_ALLOW_THREADS;
5119 RETURN_IF_ERR();
5120 RETURN_NONE();
5121}
5122
5123static PyObject*
5124DBEnv_rep_get_nsites(DBEnvObject* self, PyObject* args)
5125{
5126 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005127#if (DBVER >= 47)
5128 u_int32_t nsites;
5129#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005130 int nsites;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005131#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005132
5133 if (!PyArg_ParseTuple(args, ":rep_get_nsites")) {
5134 return NULL;
5135 }
5136 CHECK_ENV_NOT_CLOSED(self);
5137 MYDB_BEGIN_ALLOW_THREADS;
5138 err = self->db_env->rep_get_nsites(self->db_env, &nsites);
5139 MYDB_END_ALLOW_THREADS;
5140 RETURN_IF_ERR();
5141 return PyInt_FromLong(nsites);
5142}
5143
5144static PyObject*
5145DBEnv_rep_set_priority(DBEnvObject* self, PyObject* args)
5146{
5147 int err;
5148 int priority;
5149
5150 if (!PyArg_ParseTuple(args, "i:rep_set_priority", &priority)) {
5151 return NULL;
5152 }
5153 CHECK_ENV_NOT_CLOSED(self);
5154 MYDB_BEGIN_ALLOW_THREADS;
5155 err = self->db_env->rep_set_priority(self->db_env, priority);
5156 MYDB_END_ALLOW_THREADS;
5157 RETURN_IF_ERR();
5158 RETURN_NONE();
5159}
5160
5161static PyObject*
5162DBEnv_rep_get_priority(DBEnvObject* self, PyObject* args)
5163{
5164 int err;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005165#if (DBVER >= 47)
5166 u_int32_t priority;
5167#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00005168 int priority;
Jesus Ceaca3939c2008-05-22 15:27:38 +00005169#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005170
5171 if (!PyArg_ParseTuple(args, ":rep_get_priority")) {
5172 return NULL;
5173 }
5174 CHECK_ENV_NOT_CLOSED(self);
5175 MYDB_BEGIN_ALLOW_THREADS;
5176 err = self->db_env->rep_get_priority(self->db_env, &priority);
5177 MYDB_END_ALLOW_THREADS;
5178 RETURN_IF_ERR();
5179 return PyInt_FromLong(priority);
5180}
5181
5182static PyObject*
5183DBEnv_rep_set_timeout(DBEnvObject* self, PyObject* args)
5184{
5185 int err;
5186 int which, timeout;
5187
5188 if (!PyArg_ParseTuple(args, "ii:rep_set_timeout", &which, &timeout)) {
5189 return NULL;
5190 }
5191 CHECK_ENV_NOT_CLOSED(self);
5192 MYDB_BEGIN_ALLOW_THREADS;
5193 err = self->db_env->rep_set_timeout(self->db_env, which, timeout);
5194 MYDB_END_ALLOW_THREADS;
5195 RETURN_IF_ERR();
5196 RETURN_NONE();
5197}
5198
5199static PyObject*
5200DBEnv_rep_get_timeout(DBEnvObject* self, PyObject* args)
5201{
5202 int err;
5203 int which;
5204 u_int32_t timeout;
5205
5206 if (!PyArg_ParseTuple(args, "i:rep_get_timeout", &which)) {
5207 return NULL;
5208 }
5209 CHECK_ENV_NOT_CLOSED(self);
5210 MYDB_BEGIN_ALLOW_THREADS;
5211 err = self->db_env->rep_get_timeout(self->db_env, which, &timeout);
5212 MYDB_END_ALLOW_THREADS;
5213 RETURN_IF_ERR();
5214 return PyInt_FromLong(timeout);
5215}
5216#endif
5217
5218/* --------------------------------------------------------------------- */
5219/* REPLICATION METHODS: Replication Manager */
5220
5221#if (DBVER >= 45)
5222static PyObject*
5223DBEnv_repmgr_start(DBEnvObject* self, PyObject* args, PyObject*
5224 kwargs)
5225{
5226 int err;
5227 int nthreads, flags;
5228 static char* kwnames[] = {"nthreads","flags", NULL};
5229
5230 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5231 "ii:repmgr_start", kwnames, &nthreads, &flags))
5232 {
5233 return NULL;
5234 }
5235 CHECK_ENV_NOT_CLOSED(self);
5236 MYDB_BEGIN_ALLOW_THREADS;
5237 err = self->db_env->repmgr_start(self->db_env, nthreads, flags);
5238 MYDB_END_ALLOW_THREADS;
5239 RETURN_IF_ERR();
5240 RETURN_NONE();
5241}
5242
5243static PyObject*
5244DBEnv_repmgr_set_local_site(DBEnvObject* self, PyObject* args, PyObject*
5245 kwargs)
5246{
5247 int err;
5248 char *host;
5249 int port;
5250 int flags = 0;
5251 static char* kwnames[] = {"host", "port", "flags", NULL};
5252
5253 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5254 "si|i:repmgr_set_local_site", kwnames, &host, &port, &flags))
5255 {
5256 return NULL;
5257 }
5258 CHECK_ENV_NOT_CLOSED(self);
5259 MYDB_BEGIN_ALLOW_THREADS;
5260 err = self->db_env->repmgr_set_local_site(self->db_env, host, port, flags);
5261 MYDB_END_ALLOW_THREADS;
5262 RETURN_IF_ERR();
5263 RETURN_NONE();
5264}
5265
5266static PyObject*
5267DBEnv_repmgr_add_remote_site(DBEnvObject* self, PyObject* args, PyObject*
5268 kwargs)
5269{
5270 int err;
5271 char *host;
5272 int port;
5273 int flags = 0;
5274 int eidp;
5275 static char* kwnames[] = {"host", "port", "flags", NULL};
5276
5277 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
5278 "si|i:repmgr_add_remote_site", kwnames, &host, &port, &flags))
5279 {
5280 return NULL;
5281 }
5282 CHECK_ENV_NOT_CLOSED(self);
5283 MYDB_BEGIN_ALLOW_THREADS;
5284 err = self->db_env->repmgr_add_remote_site(self->db_env, host, port, &eidp, flags);
5285 MYDB_END_ALLOW_THREADS;
5286 RETURN_IF_ERR();
5287 return PyInt_FromLong(eidp);
5288}
5289
5290static PyObject*
5291DBEnv_repmgr_set_ack_policy(DBEnvObject* self, PyObject* args)
5292{
5293 int err;
5294 int ack_policy;
5295
5296 if (!PyArg_ParseTuple(args, "i:repmgr_set_ack_policy", &ack_policy))
5297 {
5298 return NULL;
5299 }
5300 CHECK_ENV_NOT_CLOSED(self);
5301 MYDB_BEGIN_ALLOW_THREADS;
5302 err = self->db_env->repmgr_set_ack_policy(self->db_env, ack_policy);
5303 MYDB_END_ALLOW_THREADS;
5304 RETURN_IF_ERR();
5305 RETURN_NONE();
5306}
5307
5308static PyObject*
5309DBEnv_repmgr_get_ack_policy(DBEnvObject* self, PyObject* args)
5310{
5311 int err;
5312 int ack_policy;
5313
5314 if (!PyArg_ParseTuple(args, ":repmgr_get_ack_policy"))
5315 {
5316 return NULL;
5317 }
5318 CHECK_ENV_NOT_CLOSED(self);
5319 MYDB_BEGIN_ALLOW_THREADS;
5320 err = self->db_env->repmgr_get_ack_policy(self->db_env, &ack_policy);
5321 MYDB_END_ALLOW_THREADS;
5322 RETURN_IF_ERR();
5323 return PyInt_FromLong(ack_policy);
5324}
5325
5326static PyObject*
5327DBEnv_repmgr_site_list(DBEnvObject* self, PyObject* args)
5328{
5329 int err;
5330 unsigned int countp;
5331 DB_REPMGR_SITE *listp;
5332 PyObject *stats, *key, *tuple;
5333
5334 if (!PyArg_ParseTuple(args, ":repmgr_site_list"))
5335 {
5336 return NULL;
5337 }
5338 CHECK_ENV_NOT_CLOSED(self);
5339 MYDB_BEGIN_ALLOW_THREADS;
5340 err = self->db_env->repmgr_site_list(self->db_env, &countp, &listp);
5341 MYDB_END_ALLOW_THREADS;
5342 RETURN_IF_ERR();
5343
5344 stats=PyDict_New();
5345 if (stats == NULL) {
5346 free(listp);
5347 return NULL;
5348 }
5349
5350 for(;countp--;) {
5351 key=PyInt_FromLong(listp[countp].eid);
5352 if(!key) {
5353 Py_DECREF(stats);
5354 free(listp);
5355 return NULL;
5356 }
5357#if (PY_VERSION_HEX >= 0x02040000)
5358 tuple=Py_BuildValue("(sII)", listp[countp].host,
5359 listp[countp].port, listp[countp].status);
5360#else
5361 tuple=Py_BuildValue("(sii)", listp[countp].host,
5362 listp[countp].port, listp[countp].status);
5363#endif
5364 if(!tuple) {
5365 Py_DECREF(key);
5366 Py_DECREF(stats);
5367 free(listp);
5368 return NULL;
5369 }
5370 if(PyDict_SetItem(stats, key, tuple)) {
5371 Py_DECREF(key);
5372 Py_DECREF(tuple);
5373 Py_DECREF(stats);
5374 free(listp);
5375 return NULL;
5376 }
5377 }
5378 free(listp);
5379 return stats;
5380}
5381#endif
5382
5383#if (DBVER >= 46)
5384static PyObject*
5385DBEnv_repmgr_stat_print(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5386{
5387 int err;
5388 int flags=0;
5389 static char* kwnames[] = { "flags", NULL };
5390
5391 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat_print",
5392 kwnames, &flags))
5393 {
5394 return NULL;
5395 }
5396 CHECK_ENV_NOT_CLOSED(self);
5397 MYDB_BEGIN_ALLOW_THREADS;
5398 err = self->db_env->repmgr_stat_print(self->db_env, flags);
5399 MYDB_END_ALLOW_THREADS;
5400 RETURN_IF_ERR();
5401 RETURN_NONE();
5402}
5403
5404static PyObject*
5405DBEnv_repmgr_stat(DBEnvObject* self, PyObject* args, PyObject *kwargs)
5406{
5407 int err;
5408 int flags=0;
5409 DB_REPMGR_STAT *statp;
5410 PyObject *stats;
5411 static char* kwnames[] = { "flags", NULL };
5412
5413 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:repmgr_stat",
5414 kwnames, &flags))
5415 {
5416 return NULL;
5417 }
5418 CHECK_ENV_NOT_CLOSED(self);
5419 MYDB_BEGIN_ALLOW_THREADS;
5420 err = self->db_env->repmgr_stat(self->db_env, &statp, flags);
5421 MYDB_END_ALLOW_THREADS;
5422 RETURN_IF_ERR();
5423
5424 stats=PyDict_New();
5425 if (stats == NULL) {
5426 free(statp);
5427 return NULL;
5428 }
5429
5430#define MAKE_ENTRY(name) _addIntToDict(stats, #name, statp->st_##name)
5431
5432 MAKE_ENTRY(perm_failed);
5433 MAKE_ENTRY(msgs_queued);
5434 MAKE_ENTRY(msgs_dropped);
5435 MAKE_ENTRY(connection_drop);
5436 MAKE_ENTRY(connect_fail);
5437
5438#undef MAKE_ENTRY
5439
5440 free(statp);
5441 return stats;
5442}
5443#endif
5444
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005445
5446/* --------------------------------------------------------------------- */
5447/* DBTxn methods */
5448
5449
Jesus Ceaef9764f2008-05-13 18:45:46 +00005450static void _close_transaction_cursors(DBTxnObject* txn)
5451{
5452 PyObject *dummy;
5453
5454 while(txn->children_cursors) {
5455 PyErr_Warn(PyExc_RuntimeWarning,
5456 "Must close cursors before resolving a transaction.");
5457 dummy=DBC_close_internal(txn->children_cursors);
5458 Py_XDECREF(dummy);
5459 }
5460}
5461
5462static void _promote_transaction_dbs_and_sequences(DBTxnObject *txn)
5463{
5464 DBObject *db;
5465#if (DBVER >= 43)
5466 DBSequenceObject *dbs;
5467#endif
5468
5469 while (txn->children_dbs) {
5470 db=txn->children_dbs;
5471 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(db);
5472 if (txn->parent_txn) {
5473 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_dbs,db);
5474 db->txn=txn->parent_txn;
5475 } else {
5476 /* The db is already linked to its environment,
5477 ** so nothing to do.
5478 */
5479 db->txn=NULL;
5480 }
5481 }
5482
5483#if (DBVER >= 43)
5484 while (txn->children_sequences) {
5485 dbs=txn->children_sequences;
5486 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(dbs);
5487 if (txn->parent_txn) {
5488 INSERT_IN_DOUBLE_LINKED_LIST_TXN(txn->parent_txn->children_sequences,dbs);
5489 dbs->txn=txn->parent_txn;
5490 } else {
5491 /* The sequence is already linked to its
5492 ** parent db. Nothing to do.
5493 */
5494 dbs->txn=NULL;
5495 }
5496 }
5497#endif
5498}
5499
5500
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005501static PyObject*
5502DBTxn_commit(DBTxnObject* self, PyObject* args)
5503{
5504 int flags=0, err;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005505 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005506
5507 if (!PyArg_ParseTuple(args, "|i:commit", &flags))
5508 return NULL;
5509
Jesus Ceaef9764f2008-05-13 18:45:46 +00005510 _close_transaction_cursors(self);
5511
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005512 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005513 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005514 "after txn_commit, txn_abort "
5515 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005516 PyErr_SetObject(DBError, t);
5517 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005518 return NULL;
5519 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005520 self->flag_prepare=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005521 txn = self->txn;
5522 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005523
5524 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5525
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005526 MYDB_BEGIN_ALLOW_THREADS;
5527#if (DBVER >= 40)
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005528 err = txn->commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005529#else
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005530 err = txn_commit(txn, flags);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005531#endif
5532 MYDB_END_ALLOW_THREADS;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005533
5534 _promote_transaction_dbs_and_sequences(self);
5535
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005536 RETURN_IF_ERR();
5537 RETURN_NONE();
5538}
5539
5540static PyObject*
5541DBTxn_prepare(DBTxnObject* self, PyObject* args)
5542{
5543#if (DBVER >= 33)
5544 int err;
5545 char* gid=NULL;
5546 int gid_size=0;
5547
5548 if (!PyArg_ParseTuple(args, "s#:prepare", &gid, &gid_size))
5549 return NULL;
5550
5551 if (gid_size != DB_XIDDATASIZE) {
5552 PyErr_SetString(PyExc_TypeError,
5553 "gid must be DB_XIDDATASIZE bytes long");
5554 return NULL;
5555 }
5556
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005557 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005558 PyObject *t = Py_BuildValue("(is)", 0,"DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005559 "after txn_commit, txn_abort "
5560 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005561 PyErr_SetObject(DBError, t);
5562 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005563 return NULL;
5564 }
Jesus Ceaef9764f2008-05-13 18:45:46 +00005565 self->flag_prepare=1; /* Prepare state */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005566 MYDB_BEGIN_ALLOW_THREADS;
5567#if (DBVER >= 40)
5568 err = self->txn->prepare(self->txn, (u_int8_t*)gid);
5569#else
5570 err = txn_prepare(self->txn, (u_int8_t*)gid);
5571#endif
5572 MYDB_END_ALLOW_THREADS;
5573 RETURN_IF_ERR();
5574 RETURN_NONE();
5575#else
5576 int err;
5577
5578 if (!PyArg_ParseTuple(args, ":prepare"))
5579 return NULL;
5580
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005581 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005582 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005583 "after txn_commit, txn_abort "
5584 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005585 PyErr_SetObject(DBError, t);
5586 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005587 return NULL;
5588 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005589 MYDB_BEGIN_ALLOW_THREADS;
5590 err = txn_prepare(self->txn);
5591 MYDB_END_ALLOW_THREADS;
5592 RETURN_IF_ERR();
5593 RETURN_NONE();
5594#endif
5595}
5596
5597
5598static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005599DBTxn_abort_discard_internal(DBTxnObject* self, int discard)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005600{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005601 PyObject *dummy;
5602 int err=0;
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005603 DB_TXN *txn;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005604
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005605 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005606 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005607 "after txn_commit, txn_abort "
5608 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005609 PyErr_SetObject(DBError, t);
5610 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005611 return NULL;
5612 }
5613 txn = self->txn;
5614 self->txn = NULL; /* this DB_TXN is no longer valid after this call */
Jesus Ceaef9764f2008-05-13 18:45:46 +00005615
5616 _close_transaction_cursors(self);
5617#if (DBVER >= 43)
5618 while (self->children_sequences) {
5619 dummy=DBSequence_close_internal(self->children_sequences,0,0);
5620 Py_XDECREF(dummy);
5621 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005622#endif
Jesus Ceaef9764f2008-05-13 18:45:46 +00005623 while (self->children_dbs) {
5624 dummy=DB_close_internal(self->children_dbs,0);
5625 Py_XDECREF(dummy);
5626 }
5627
5628 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5629
5630 MYDB_BEGIN_ALLOW_THREADS;
5631 if (discard) {
5632 assert(!self->flag_prepare);
5633#if (DBVER >= 40)
5634 err = txn->discard(txn,0);
5635#else
5636 err = txn_discard(txn);
5637#endif
5638 } else {
5639 /*
5640 ** If the transaction is in the "prepare" or "recover" state,
5641 ** we better do not implicitly abort it.
5642 */
5643 if (!self->flag_prepare) {
5644#if (DBVER >= 40)
5645 err = txn->abort(txn);
5646#else
5647 err = txn_abort(txn);
5648#endif
5649 }
5650 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005651 MYDB_END_ALLOW_THREADS;
5652 RETURN_IF_ERR();
5653 RETURN_NONE();
5654}
5655
Jesus Ceaef9764f2008-05-13 18:45:46 +00005656static PyObject*
5657DBTxn_abort(DBTxnObject* self, PyObject* args)
5658{
5659 if (!PyArg_ParseTuple(args, ":abort"))
5660 return NULL;
5661
5662 self->flag_prepare=0;
5663 _close_transaction_cursors(self);
5664
5665 return DBTxn_abort_discard_internal(self,0);
5666}
5667
5668static PyObject*
5669DBTxn_discard(DBTxnObject* self, PyObject* args)
5670{
5671 if (!PyArg_ParseTuple(args, ":discard"))
5672 return NULL;
5673
5674 self->flag_prepare=0;
5675 _close_transaction_cursors(self);
5676
5677 return DBTxn_abort_discard_internal(self,1);
5678}
5679
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005680
5681static PyObject*
5682DBTxn_id(DBTxnObject* self, PyObject* args)
5683{
5684 int id;
5685
5686 if (!PyArg_ParseTuple(args, ":id"))
5687 return NULL;
5688
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005689 if (!self->txn) {
Thomas Woutersb3153832006-03-08 01:47:19 +00005690 PyObject *t = Py_BuildValue("(is)", 0, "DBTxn must not be used "
Jesus Ceaef9764f2008-05-13 18:45:46 +00005691 "after txn_commit, txn_abort "
5692 "or txn_discard");
Thomas Woutersb3153832006-03-08 01:47:19 +00005693 PyErr_SetObject(DBError, t);
5694 Py_DECREF(t);
Gregory P. Smithc25fd3f2003-01-17 07:52:59 +00005695 return NULL;
5696 }
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00005697 MYDB_BEGIN_ALLOW_THREADS;
5698#if (DBVER >= 40)
5699 id = self->txn->id(self->txn);
5700#else
5701 id = txn_id(self->txn);
5702#endif
5703 MYDB_END_ALLOW_THREADS;
5704 return PyInt_FromLong(id);
5705}
5706
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005707#if (DBVER >= 43)
5708/* --------------------------------------------------------------------- */
5709/* DBSequence methods */
5710
5711
5712static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005713DBSequence_close_internal(DBSequenceObject* self, int flags, int do_not_close)
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005714{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005715 int err=0;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005716
Jesus Ceaef9764f2008-05-13 18:45:46 +00005717 if (self->sequence!=NULL) {
5718 EXTRACT_FROM_DOUBLE_LINKED_LIST(self);
5719 if (self->txn) {
5720 EXTRACT_FROM_DOUBLE_LINKED_LIST_TXN(self);
5721 self->txn=NULL;
5722 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005723
Jesus Ceaef9764f2008-05-13 18:45:46 +00005724 if (!do_not_close) {
5725 MYDB_BEGIN_ALLOW_THREADS
5726 err = self->sequence->close(self->sequence, flags);
5727 MYDB_END_ALLOW_THREADS
5728 }
5729 self->sequence = NULL;
5730
5731 RETURN_IF_ERR();
5732 }
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005733
5734 RETURN_NONE();
5735}
5736
5737static PyObject*
Jesus Ceaef9764f2008-05-13 18:45:46 +00005738DBSequence_close(DBSequenceObject* self, PyObject* args)
5739{
5740 int flags=0;
5741 if (!PyArg_ParseTuple(args,"|i:close", &flags))
5742 return NULL;
5743
5744 return DBSequence_close_internal(self,flags,0);
5745}
5746
5747static PyObject*
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005748DBSequence_get(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5749{
5750 int err, flags = 0;
5751 int delta = 1;
5752 db_seq_t value;
5753 PyObject *txnobj = NULL;
5754 DB_TXN *txn = NULL;
5755 static char* kwnames[] = {"delta", "txn", "flags", NULL };
5756 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOi:get", kwnames, &delta, &txnobj, &flags))
5757 return NULL;
5758 CHECK_SEQUENCE_NOT_CLOSED(self)
5759
5760 if (!checkTxnObj(txnobj, &txn))
5761 return NULL;
5762
5763 MYDB_BEGIN_ALLOW_THREADS
5764 err = self->sequence->get(self->sequence, txn, delta, &value, flags);
5765 MYDB_END_ALLOW_THREADS
5766
5767 RETURN_IF_ERR();
5768 return PyLong_FromLongLong(value);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005769}
5770
5771static PyObject*
5772DBSequence_get_dbp(DBSequenceObject* self, PyObject* args)
5773{
5774 if (!PyArg_ParseTuple(args,":get_dbp"))
5775 return NULL;
5776 CHECK_SEQUENCE_NOT_CLOSED(self)
5777 Py_INCREF(self->mydb);
5778 return (PyObject* )self->mydb;
5779}
5780
5781static PyObject*
5782DBSequence_get_key(DBSequenceObject* self, PyObject* args)
5783{
5784 int err;
5785 DBT key;
Neal Norwitz088beae2007-10-12 03:01:54 +00005786 PyObject *retval = NULL;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005787
5788 if (!PyArg_ParseTuple(args,":get_key"))
5789 return NULL;
5790
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005791 key.flags = DB_DBT_MALLOC;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005792 CHECK_SEQUENCE_NOT_CLOSED(self)
5793 MYDB_BEGIN_ALLOW_THREADS
5794 err = self->sequence->get_key(self->sequence, &key);
5795 MYDB_END_ALLOW_THREADS
5796
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005797 if (!err)
Jesus Ceaef9764f2008-05-13 18:45:46 +00005798 retval = Build_PyString(key.data, key.size);
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005799
5800 FREE_DBT(key);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005801 RETURN_IF_ERR();
5802
Gregory P. Smithe70be5c2007-10-06 07:48:10 +00005803 return retval;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005804}
5805
5806static PyObject*
5807DBSequence_init_value(DBSequenceObject* self, PyObject* args)
5808{
5809 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005810 PY_LONG_LONG value;
5811 db_seq_t value2;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005812 if (!PyArg_ParseTuple(args,"L:init_value", &value))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005813 return NULL;
5814 CHECK_SEQUENCE_NOT_CLOSED(self)
5815
Jesus Ceaef9764f2008-05-13 18:45:46 +00005816 value2=value; /* If truncation, compiler should show a warning */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005817 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005818 err = self->sequence->initial_value(self->sequence, value2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005819 MYDB_END_ALLOW_THREADS
5820
5821 RETURN_IF_ERR();
5822
5823 RETURN_NONE();
5824}
5825
5826static PyObject*
5827DBSequence_open(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5828{
5829 int err, flags = 0;
5830 PyObject* keyobj;
5831 PyObject *txnobj = NULL;
5832 DB_TXN *txn = NULL;
5833 DBT key;
5834
5835 static char* kwnames[] = {"key", "txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005836 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Oi:open", kwnames, &keyobj, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005837 return NULL;
5838
5839 if (!checkTxnObj(txnobj, &txn))
5840 return NULL;
5841
5842 if (!make_key_dbt(self->mydb, keyobj, &key, NULL))
5843 return NULL;
5844
5845 MYDB_BEGIN_ALLOW_THREADS
5846 err = self->sequence->open(self->sequence, txn, &key, flags);
5847 MYDB_END_ALLOW_THREADS
5848
5849 CLEAR_DBT(key);
5850 RETURN_IF_ERR();
5851
Jesus Ceaef9764f2008-05-13 18:45:46 +00005852 if (txn) {
5853 INSERT_IN_DOUBLE_LINKED_LIST_TXN(((DBTxnObject *)txnobj)->children_sequences,self);
5854 self->txn=(DBTxnObject *)txnobj;
5855 }
5856
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005857 RETURN_NONE();
5858}
5859
5860static PyObject*
5861DBSequence_remove(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5862{
Jesus Ceaef9764f2008-05-13 18:45:46 +00005863 PyObject *dummy;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005864 int err, flags = 0;
5865 PyObject *txnobj = NULL;
5866 DB_TXN *txn = NULL;
5867
5868 static char* kwnames[] = {"txn", "flags", NULL };
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005869 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:remove", kwnames, &txnobj, &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005870 return NULL;
5871
5872 if (!checkTxnObj(txnobj, &txn))
5873 return NULL;
5874
5875 CHECK_SEQUENCE_NOT_CLOSED(self)
5876
5877 MYDB_BEGIN_ALLOW_THREADS
5878 err = self->sequence->remove(self->sequence, txn, flags);
5879 MYDB_END_ALLOW_THREADS
5880
Jesus Ceaef9764f2008-05-13 18:45:46 +00005881 dummy=DBSequence_close_internal(self,flags,1);
5882 Py_XDECREF(dummy);
5883
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005884 RETURN_IF_ERR();
5885 RETURN_NONE();
5886}
5887
5888static PyObject*
5889DBSequence_set_cachesize(DBSequenceObject* self, PyObject* args)
5890{
5891 int err, size;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005892 if (!PyArg_ParseTuple(args,"i:set_cachesize", &size))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005893 return NULL;
5894 CHECK_SEQUENCE_NOT_CLOSED(self)
5895
5896 MYDB_BEGIN_ALLOW_THREADS
5897 err = self->sequence->set_cachesize(self->sequence, size);
5898 MYDB_END_ALLOW_THREADS
5899
5900 RETURN_IF_ERR();
5901 RETURN_NONE();
5902}
5903
5904static PyObject*
5905DBSequence_get_cachesize(DBSequenceObject* self, PyObject* args)
5906{
5907 int err, size;
5908 if (!PyArg_ParseTuple(args,":get_cachesize"))
5909 return NULL;
5910 CHECK_SEQUENCE_NOT_CLOSED(self)
5911
5912 MYDB_BEGIN_ALLOW_THREADS
5913 err = self->sequence->get_cachesize(self->sequence, &size);
5914 MYDB_END_ALLOW_THREADS
5915
5916 RETURN_IF_ERR();
5917 return PyInt_FromLong(size);
5918}
5919
5920static PyObject*
5921DBSequence_set_flags(DBSequenceObject* self, PyObject* args)
5922{
5923 int err, flags = 0;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005924 if (!PyArg_ParseTuple(args,"i:set_flags", &flags))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005925 return NULL;
5926 CHECK_SEQUENCE_NOT_CLOSED(self)
5927
5928 MYDB_BEGIN_ALLOW_THREADS
5929 err = self->sequence->set_flags(self->sequence, flags);
5930 MYDB_END_ALLOW_THREADS
5931
5932 RETURN_IF_ERR();
5933 RETURN_NONE();
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005934}
5935
5936static PyObject*
5937DBSequence_get_flags(DBSequenceObject* self, PyObject* args)
5938{
5939 unsigned int flags;
5940 int err;
Neal Norwitzdd2a6bf2006-06-06 07:23:01 +00005941 if (!PyArg_ParseTuple(args,":get_flags"))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005942 return NULL;
5943 CHECK_SEQUENCE_NOT_CLOSED(self)
5944
5945 MYDB_BEGIN_ALLOW_THREADS
5946 err = self->sequence->get_flags(self->sequence, &flags);
5947 MYDB_END_ALLOW_THREADS
5948
5949 RETURN_IF_ERR();
5950 return PyInt_FromLong((int)flags);
5951}
5952
5953static PyObject*
5954DBSequence_set_range(DBSequenceObject* self, PyObject* args)
5955{
5956 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005957 PY_LONG_LONG min, max;
5958 db_seq_t min2, max2;
Tim Petersbb21b2c2006-06-06 15:50:17 +00005959 if (!PyArg_ParseTuple(args,"(LL):set_range", &min, &max))
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005960 return NULL;
5961 CHECK_SEQUENCE_NOT_CLOSED(self)
5962
Jesus Ceaef9764f2008-05-13 18:45:46 +00005963 min2=min; /* If truncation, compiler should show a warning */
5964 max2=max;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005965 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005966 err = self->sequence->set_range(self->sequence, min2, max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005967 MYDB_END_ALLOW_THREADS
5968
5969 RETURN_IF_ERR();
5970 RETURN_NONE();
5971}
5972
5973static PyObject*
5974DBSequence_get_range(DBSequenceObject* self, PyObject* args)
5975{
5976 int err;
Jesus Ceaef9764f2008-05-13 18:45:46 +00005977 PY_LONG_LONG min, max;
5978 db_seq_t min2, max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005979 if (!PyArg_ParseTuple(args,":get_range"))
5980 return NULL;
5981 CHECK_SEQUENCE_NOT_CLOSED(self)
5982
5983 MYDB_BEGIN_ALLOW_THREADS
Jesus Ceaef9764f2008-05-13 18:45:46 +00005984 err = self->sequence->get_range(self->sequence, &min2, &max2);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005985 MYDB_END_ALLOW_THREADS
5986
5987 RETURN_IF_ERR();
Jesus Ceaef9764f2008-05-13 18:45:46 +00005988 min=min2; /* If truncation, compiler should show a warning */
5989 max=max2;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00005990 return Py_BuildValue("(LL)", min, max);
5991}
5992
5993static PyObject*
5994DBSequence_stat(DBSequenceObject* self, PyObject* args, PyObject* kwargs)
5995{
5996 int err, flags = 0;
5997 DB_SEQUENCE_STAT* sp = NULL;
5998 PyObject* dict_stat;
5999 static char* kwnames[] = {"flags", NULL };
6000 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:stat", kwnames, &flags))
6001 return NULL;
6002 CHECK_SEQUENCE_NOT_CLOSED(self);
6003
6004 MYDB_BEGIN_ALLOW_THREADS;
6005 err = self->sequence->stat(self->sequence, &sp, flags);
6006 MYDB_END_ALLOW_THREADS;
6007 RETURN_IF_ERR();
6008
6009 if ((dict_stat = PyDict_New()) == NULL) {
6010 free(sp);
6011 return NULL;
6012 }
6013
6014
6015#define MAKE_INT_ENTRY(name) _addIntToDict(dict_stat, #name, sp->st_##name)
6016#define MAKE_LONG_LONG_ENTRY(name) _addDb_seq_tToDict(dict_stat, #name, sp->st_##name)
6017
6018 MAKE_INT_ENTRY(wait);
6019 MAKE_INT_ENTRY(nowait);
6020 MAKE_LONG_LONG_ENTRY(current);
6021 MAKE_LONG_LONG_ENTRY(value);
6022 MAKE_LONG_LONG_ENTRY(last_value);
6023 MAKE_LONG_LONG_ENTRY(min);
6024 MAKE_LONG_LONG_ENTRY(max);
6025 MAKE_INT_ENTRY(cache_size);
6026 MAKE_INT_ENTRY(flags);
6027
6028#undef MAKE_INT_ENTRY
6029#undef MAKE_LONG_LONG_ENTRY
6030
6031 free(sp);
6032 return dict_stat;
6033}
6034#endif
6035
6036
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006037/* --------------------------------------------------------------------- */
6038/* Method definition tables and type objects */
6039
6040static PyMethodDef DB_methods[] = {
6041 {"append", (PyCFunction)DB_append, METH_VARARGS},
6042#if (DBVER >= 33)
6043 {"associate", (PyCFunction)DB_associate, METH_VARARGS|METH_KEYWORDS},
6044#endif
6045 {"close", (PyCFunction)DB_close, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006046 {"consume", (PyCFunction)DB_consume, METH_VARARGS|METH_KEYWORDS},
6047 {"consume_wait", (PyCFunction)DB_consume_wait, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006048 {"cursor", (PyCFunction)DB_cursor, METH_VARARGS|METH_KEYWORDS},
6049 {"delete", (PyCFunction)DB_delete, METH_VARARGS|METH_KEYWORDS},
6050 {"fd", (PyCFunction)DB_fd, METH_VARARGS},
6051 {"get", (PyCFunction)DB_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006052#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00006053 {"pget", (PyCFunction)DB_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006054#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006055 {"get_both", (PyCFunction)DB_get_both, METH_VARARGS|METH_KEYWORDS},
6056 {"get_byteswapped", (PyCFunction)DB_get_byteswapped,METH_VARARGS},
6057 {"get_size", (PyCFunction)DB_get_size, METH_VARARGS|METH_KEYWORDS},
6058 {"get_type", (PyCFunction)DB_get_type, METH_VARARGS},
6059 {"join", (PyCFunction)DB_join, METH_VARARGS},
6060 {"key_range", (PyCFunction)DB_key_range, METH_VARARGS|METH_KEYWORDS},
6061 {"has_key", (PyCFunction)DB_has_key, METH_VARARGS},
6062 {"items", (PyCFunction)DB_items, METH_VARARGS},
6063 {"keys", (PyCFunction)DB_keys, METH_VARARGS},
6064 {"open", (PyCFunction)DB_open, METH_VARARGS|METH_KEYWORDS},
6065 {"put", (PyCFunction)DB_put, METH_VARARGS|METH_KEYWORDS},
6066 {"remove", (PyCFunction)DB_remove, METH_VARARGS|METH_KEYWORDS},
6067 {"rename", (PyCFunction)DB_rename, METH_VARARGS},
6068 {"set_bt_minkey", (PyCFunction)DB_set_bt_minkey, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006069#if (DBVER >= 33)
Gregory P. Smithe4ed2de2005-06-03 07:03:07 +00006070 {"set_bt_compare", (PyCFunction)DB_set_bt_compare, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006071#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006072 {"set_cachesize", (PyCFunction)DB_set_cachesize, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006073#if (DBVER >= 41)
6074 {"set_encrypt", (PyCFunction)DB_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6075#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006076 {"set_flags", (PyCFunction)DB_set_flags, METH_VARARGS},
6077 {"set_h_ffactor", (PyCFunction)DB_set_h_ffactor, METH_VARARGS},
6078 {"set_h_nelem", (PyCFunction)DB_set_h_nelem, METH_VARARGS},
6079 {"set_lorder", (PyCFunction)DB_set_lorder, METH_VARARGS},
6080 {"set_pagesize", (PyCFunction)DB_set_pagesize, METH_VARARGS},
6081 {"set_re_delim", (PyCFunction)DB_set_re_delim, METH_VARARGS},
6082 {"set_re_len", (PyCFunction)DB_set_re_len, METH_VARARGS},
6083 {"set_re_pad", (PyCFunction)DB_set_re_pad, METH_VARARGS},
6084 {"set_re_source", (PyCFunction)DB_set_re_source, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006085 {"set_q_extentsize",(PyCFunction)DB_set_q_extentsize,METH_VARARGS},
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006086 {"stat", (PyCFunction)DB_stat, METH_VARARGS|METH_KEYWORDS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006087 {"sync", (PyCFunction)DB_sync, METH_VARARGS},
6088#if (DBVER >= 33)
6089 {"truncate", (PyCFunction)DB_truncate, METH_VARARGS|METH_KEYWORDS},
6090#endif
6091 {"type", (PyCFunction)DB_get_type, METH_VARARGS},
6092 {"upgrade", (PyCFunction)DB_upgrade, METH_VARARGS},
6093 {"values", (PyCFunction)DB_values, METH_VARARGS},
6094 {"verify", (PyCFunction)DB_verify, METH_VARARGS|METH_KEYWORDS},
6095 {"set_get_returns_none",(PyCFunction)DB_set_get_returns_none, METH_VARARGS},
6096 {NULL, NULL} /* sentinel */
6097};
6098
6099
6100static PyMappingMethods DB_mapping = {
Martin v. Löwis70ee3cc2006-06-12 04:26:31 +00006101 DB_length, /*mp_length*/
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006102 (binaryfunc)DB_subscript, /*mp_subscript*/
6103 (objobjargproc)DB_ass_sub, /*mp_ass_subscript*/
6104};
6105
6106
6107static PyMethodDef DBCursor_methods[] = {
6108 {"close", (PyCFunction)DBC_close, METH_VARARGS},
6109 {"count", (PyCFunction)DBC_count, METH_VARARGS},
6110 {"current", (PyCFunction)DBC_current, METH_VARARGS|METH_KEYWORDS},
6111 {"delete", (PyCFunction)DBC_delete, METH_VARARGS},
6112 {"dup", (PyCFunction)DBC_dup, METH_VARARGS},
6113 {"first", (PyCFunction)DBC_first, METH_VARARGS|METH_KEYWORDS},
6114 {"get", (PyCFunction)DBC_get, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006115#if (DBVER >= 33)
Gregory P. Smith19699a92004-06-28 04:06:49 +00006116 {"pget", (PyCFunction)DBC_pget, METH_VARARGS|METH_KEYWORDS},
Gregory P. Smith8a6a59c2004-12-16 09:47:28 +00006117#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006118 {"get_recno", (PyCFunction)DBC_get_recno, METH_VARARGS},
6119 {"last", (PyCFunction)DBC_last, METH_VARARGS|METH_KEYWORDS},
6120 {"next", (PyCFunction)DBC_next, METH_VARARGS|METH_KEYWORDS},
6121 {"prev", (PyCFunction)DBC_prev, METH_VARARGS|METH_KEYWORDS},
6122 {"put", (PyCFunction)DBC_put, METH_VARARGS|METH_KEYWORDS},
6123 {"set", (PyCFunction)DBC_set, METH_VARARGS|METH_KEYWORDS},
6124 {"set_range", (PyCFunction)DBC_set_range, METH_VARARGS|METH_KEYWORDS},
6125 {"get_both", (PyCFunction)DBC_get_both, METH_VARARGS},
Gregory P. Smithbe0db8b2003-10-01 06:48:51 +00006126 {"get_current_size",(PyCFunction)DBC_get_current_size, METH_VARARGS},
Gregory P. Smith455d46f2003-07-09 04:45:59 +00006127 {"set_both", (PyCFunction)DBC_set_both, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006128 {"set_recno", (PyCFunction)DBC_set_recno, METH_VARARGS|METH_KEYWORDS},
6129 {"consume", (PyCFunction)DBC_consume, METH_VARARGS|METH_KEYWORDS},
6130 {"next_dup", (PyCFunction)DBC_next_dup, METH_VARARGS|METH_KEYWORDS},
6131 {"next_nodup", (PyCFunction)DBC_next_nodup, METH_VARARGS|METH_KEYWORDS},
6132 {"prev_nodup", (PyCFunction)DBC_prev_nodup, METH_VARARGS|METH_KEYWORDS},
6133 {"join_item", (PyCFunction)DBC_join_item, METH_VARARGS},
6134 {NULL, NULL} /* sentinel */
6135};
6136
6137
6138static PyMethodDef DBEnv_methods[] = {
6139 {"close", (PyCFunction)DBEnv_close, METH_VARARGS},
6140 {"open", (PyCFunction)DBEnv_open, METH_VARARGS},
6141 {"remove", (PyCFunction)DBEnv_remove, METH_VARARGS},
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006142#if (DBVER >= 41)
6143 {"dbremove", (PyCFunction)DBEnv_dbremove, METH_VARARGS|METH_KEYWORDS},
6144 {"dbrename", (PyCFunction)DBEnv_dbrename, METH_VARARGS|METH_KEYWORDS},
6145 {"set_encrypt", (PyCFunction)DBEnv_set_encrypt, METH_VARARGS|METH_KEYWORDS},
6146#endif
Gregory P. Smithfe11d3e2003-03-27 17:23:29 +00006147#if (DBVER >= 40)
6148 {"set_timeout", (PyCFunction)DBEnv_set_timeout, METH_VARARGS|METH_KEYWORDS},
6149#endif
Gregory P. Smith6676f6e2003-08-28 21:50:30 +00006150 {"set_shm_key", (PyCFunction)DBEnv_set_shm_key, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006151 {"set_cachesize", (PyCFunction)DBEnv_set_cachesize, METH_VARARGS},
6152 {"set_data_dir", (PyCFunction)DBEnv_set_data_dir, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006153 {"set_flags", (PyCFunction)DBEnv_set_flags, METH_VARARGS},
Jesus Ceaca3939c2008-05-22 15:27:38 +00006154#if (DBVER >= 47)
6155 {"log_set_config", (PyCFunction)DBEnv_log_set_config, METH_VARARGS},
6156#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006157 {"set_lg_bsize", (PyCFunction)DBEnv_set_lg_bsize, METH_VARARGS},
6158 {"set_lg_dir", (PyCFunction)DBEnv_set_lg_dir, METH_VARARGS},
6159 {"set_lg_max", (PyCFunction)DBEnv_set_lg_max, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006160#if (DBVER >= 42)
6161 {"get_lg_max", (PyCFunction)DBEnv_get_lg_max, METH_VARARGS},
6162#endif
Neal Norwitz84562352005-10-20 04:30:15 +00006163#if (DBVER >= 33)
Gregory P. Smithe9477062005-06-04 06:46:59 +00006164 {"set_lg_regionmax",(PyCFunction)DBEnv_set_lg_regionmax, METH_VARARGS},
Neal Norwitz84562352005-10-20 04:30:15 +00006165#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006166 {"set_lk_detect", (PyCFunction)DBEnv_set_lk_detect, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006167#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006168 {"set_lk_max", (PyCFunction)DBEnv_set_lk_max, METH_VARARGS},
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006169#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006170 {"set_lk_max_locks", (PyCFunction)DBEnv_set_lk_max_locks, METH_VARARGS},
6171 {"set_lk_max_lockers", (PyCFunction)DBEnv_set_lk_max_lockers, METH_VARARGS},
6172 {"set_lk_max_objects", (PyCFunction)DBEnv_set_lk_max_objects, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006173 {"set_mp_mmapsize", (PyCFunction)DBEnv_set_mp_mmapsize, METH_VARARGS},
6174 {"set_tmp_dir", (PyCFunction)DBEnv_set_tmp_dir, METH_VARARGS},
6175 {"txn_begin", (PyCFunction)DBEnv_txn_begin, METH_VARARGS|METH_KEYWORDS},
6176 {"txn_checkpoint", (PyCFunction)DBEnv_txn_checkpoint, METH_VARARGS},
6177 {"txn_stat", (PyCFunction)DBEnv_txn_stat, METH_VARARGS},
6178 {"set_tx_max", (PyCFunction)DBEnv_set_tx_max, METH_VARARGS},
Gregory P. Smith8a474042006-01-27 07:05:40 +00006179 {"set_tx_timestamp", (PyCFunction)DBEnv_set_tx_timestamp, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006180 {"lock_detect", (PyCFunction)DBEnv_lock_detect, METH_VARARGS},
6181 {"lock_get", (PyCFunction)DBEnv_lock_get, METH_VARARGS},
6182 {"lock_id", (PyCFunction)DBEnv_lock_id, METH_VARARGS},
Gregory P. Smithac11e022007-11-05 02:56:31 +00006183#if (DBVER >= 40)
6184 {"lock_id_free", (PyCFunction)DBEnv_lock_id_free, METH_VARARGS},
6185#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006186 {"lock_put", (PyCFunction)DBEnv_lock_put, METH_VARARGS},
6187 {"lock_stat", (PyCFunction)DBEnv_lock_stat, METH_VARARGS},
6188 {"log_archive", (PyCFunction)DBEnv_log_archive, METH_VARARGS},
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006189#if (DBVER >= 40)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006190 {"log_flush", (PyCFunction)DBEnv_log_flush, METH_VARARGS},
6191#endif
6192#if (DBVER >= 40)
Gregory P. Smith76a82e82006-06-05 01:39:52 +00006193 {"log_stat", (PyCFunction)DBEnv_log_stat, METH_VARARGS},
6194#endif
Gregory P. Smithdb8a8072006-06-05 01:56:15 +00006195#if (DBVER >= 44)
6196 {"lsn_reset", (PyCFunction)DBEnv_lsn_reset, METH_VARARGS|METH_KEYWORDS},
6197#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006198 {"set_get_returns_none",(PyCFunction)DBEnv_set_get_returns_none, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006199#if (DBVER >= 40)
6200 {"txn_recover", (PyCFunction)DBEnv_txn_recover, METH_VARARGS},
6201#endif
6202#if (DBVER >= 40)
Jesus Ceaca3939c2008-05-22 15:27:38 +00006203 {"set_rpc_server", (PyCFunction)DBEnv_set_rpc_server,
6204 METH_VARARGS||METH_KEYWORDS},
6205#endif
6206#if (DBVER >= 40)
Jesus Ceaef9764f2008-05-13 18:45:46 +00006207 {"set_verbose", (PyCFunction)DBEnv_set_verbose, METH_VARARGS},
6208#if (DBVER >= 42)
6209 {"get_verbose", (PyCFunction)DBEnv_get_verbose, METH_VARARGS},
6210#endif
6211#endif
6212#if (DBVER >= 45)
6213 {"set_event_notify", (PyCFunction)DBEnv_set_event_notify, METH_VARARGS},
6214#endif
6215#if (DBVER >= 45)
6216 {"rep_set_nsites", (PyCFunction)DBEnv_rep_set_nsites, METH_VARARGS},
6217 {"rep_get_nsites", (PyCFunction)DBEnv_rep_get_nsites, METH_VARARGS},
6218 {"rep_set_priority", (PyCFunction)DBEnv_rep_set_priority, METH_VARARGS},
6219 {"rep_get_priority", (PyCFunction)DBEnv_rep_get_priority, METH_VARARGS},
6220 {"rep_set_timeout", (PyCFunction)DBEnv_rep_set_timeout, METH_VARARGS},
6221 {"rep_get_timeout", (PyCFunction)DBEnv_rep_get_timeout, METH_VARARGS},
6222#endif
6223#if (DBVER >= 45)
6224 {"repmgr_start", (PyCFunction)DBEnv_repmgr_start,
6225 METH_VARARGS|METH_KEYWORDS},
6226 {"repmgr_set_local_site", (PyCFunction)DBEnv_repmgr_set_local_site,
6227 METH_VARARGS|METH_KEYWORDS},
6228 {"repmgr_add_remote_site", (PyCFunction)DBEnv_repmgr_add_remote_site,
6229 METH_VARARGS|METH_KEYWORDS},
6230 {"repmgr_set_ack_policy", (PyCFunction)DBEnv_repmgr_set_ack_policy,
6231 METH_VARARGS},
6232 {"repmgr_get_ack_policy", (PyCFunction)DBEnv_repmgr_get_ack_policy,
6233 METH_VARARGS},
6234 {"repmgr_site_list", (PyCFunction)DBEnv_repmgr_site_list,
6235 METH_VARARGS},
6236#endif
6237#if (DBVER >= 46)
6238 {"repmgr_stat", (PyCFunction)DBEnv_repmgr_stat,
6239 METH_VARARGS|METH_KEYWORDS},
6240 {"repmgr_stat_print", (PyCFunction)DBEnv_repmgr_stat_print,
6241 METH_VARARGS|METH_KEYWORDS},
6242#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006243 {NULL, NULL} /* sentinel */
6244};
6245
6246
6247static PyMethodDef DBTxn_methods[] = {
6248 {"commit", (PyCFunction)DBTxn_commit, METH_VARARGS},
6249 {"prepare", (PyCFunction)DBTxn_prepare, METH_VARARGS},
Jesus Ceaef9764f2008-05-13 18:45:46 +00006250 {"discard", (PyCFunction)DBTxn_discard, METH_VARARGS},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006251 {"abort", (PyCFunction)DBTxn_abort, METH_VARARGS},
6252 {"id", (PyCFunction)DBTxn_id, METH_VARARGS},
6253 {NULL, NULL} /* sentinel */
6254};
6255
6256
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006257#if (DBVER >= 43)
6258static PyMethodDef DBSequence_methods[] = {
6259 {"close", (PyCFunction)DBSequence_close, METH_VARARGS},
6260 {"get", (PyCFunction)DBSequence_get, METH_VARARGS|METH_KEYWORDS},
6261 {"get_dbp", (PyCFunction)DBSequence_get_dbp, METH_VARARGS},
6262 {"get_key", (PyCFunction)DBSequence_get_key, METH_VARARGS},
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006263 {"init_value", (PyCFunction)DBSequence_init_value, METH_VARARGS},
6264 {"open", (PyCFunction)DBSequence_open, METH_VARARGS|METH_KEYWORDS},
6265 {"remove", (PyCFunction)DBSequence_remove, METH_VARARGS|METH_KEYWORDS},
6266 {"set_cachesize", (PyCFunction)DBSequence_set_cachesize, METH_VARARGS},
6267 {"get_cachesize", (PyCFunction)DBSequence_get_cachesize, METH_VARARGS},
6268 {"set_flags", (PyCFunction)DBSequence_set_flags, METH_VARARGS},
6269 {"get_flags", (PyCFunction)DBSequence_get_flags, METH_VARARGS},
6270 {"set_range", (PyCFunction)DBSequence_set_range, METH_VARARGS},
6271 {"get_range", (PyCFunction)DBSequence_get_range, METH_VARARGS},
6272 {"stat", (PyCFunction)DBSequence_stat, METH_VARARGS|METH_KEYWORDS},
6273 {NULL, NULL} /* sentinel */
6274};
6275#endif
6276
6277
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006278static PyObject*
6279DB_getattr(DBObject* self, char *name)
6280{
6281 return Py_FindMethod(DB_methods, (PyObject* )self, name);
6282}
6283
6284
6285static PyObject*
6286DBEnv_getattr(DBEnvObject* self, char *name)
6287{
6288 if (!strcmp(name, "db_home")) {
Jesus Ceaef9764f2008-05-13 18:45:46 +00006289 const char *home = NULL;
6290 CHECK_ENV_NOT_CLOSED(self);
6291#if (DBVER >= 42)
6292 self->db_env->get_home(self->db_env, &home);
6293#else
6294 home=self->db_env->db_home;
6295#endif
6296 if (home == NULL) {
6297 RETURN_NONE();
6298 }
6299 return PyString_FromString(home);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006300 }
6301
6302 return Py_FindMethod(DBEnv_methods, (PyObject* )self, name);
6303}
6304
6305
6306static PyObject*
6307DBCursor_getattr(DBCursorObject* self, char *name)
6308{
6309 return Py_FindMethod(DBCursor_methods, (PyObject* )self, name);
6310}
6311
6312static PyObject*
6313DBTxn_getattr(DBTxnObject* self, char *name)
6314{
6315 return Py_FindMethod(DBTxn_methods, (PyObject* )self, name);
6316}
6317
6318static PyObject*
6319DBLock_getattr(DBLockObject* self, char *name)
6320{
6321 return NULL;
6322}
6323
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006324#if (DBVER >= 43)
6325static PyObject*
6326DBSequence_getattr(DBSequenceObject* self, char *name)
6327{
6328 return Py_FindMethod(DBSequence_methods, (PyObject* )self, name);
6329}
6330#endif
6331
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006332statichere PyTypeObject DB_Type = {
6333 PyObject_HEAD_INIT(NULL)
6334 0, /*ob_size*/
6335 "DB", /*tp_name*/
6336 sizeof(DBObject), /*tp_basicsize*/
6337 0, /*tp_itemsize*/
6338 /* methods */
6339 (destructor)DB_dealloc, /*tp_dealloc*/
6340 0, /*tp_print*/
6341 (getattrfunc)DB_getattr, /*tp_getattr*/
6342 0, /*tp_setattr*/
6343 0, /*tp_compare*/
6344 0, /*tp_repr*/
6345 0, /*tp_as_number*/
6346 0, /*tp_as_sequence*/
6347 &DB_mapping,/*tp_as_mapping*/
6348 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006349 0, /* tp_call */
6350 0, /* tp_str */
6351 0, /* tp_getattro */
6352 0, /* tp_setattro */
6353 0, /* tp_as_buffer */
6354 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6355 0, /* tp_doc */
6356 0, /* tp_traverse */
6357 0, /* tp_clear */
6358 0, /* tp_richcompare */
6359 offsetof(DBObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006360};
6361
6362
6363statichere PyTypeObject DBCursor_Type = {
6364 PyObject_HEAD_INIT(NULL)
6365 0, /*ob_size*/
6366 "DBCursor", /*tp_name*/
6367 sizeof(DBCursorObject), /*tp_basicsize*/
6368 0, /*tp_itemsize*/
6369 /* methods */
6370 (destructor)DBCursor_dealloc,/*tp_dealloc*/
6371 0, /*tp_print*/
6372 (getattrfunc)DBCursor_getattr, /*tp_getattr*/
6373 0, /*tp_setattr*/
6374 0, /*tp_compare*/
6375 0, /*tp_repr*/
6376 0, /*tp_as_number*/
6377 0, /*tp_as_sequence*/
6378 0, /*tp_as_mapping*/
6379 0, /*tp_hash*/
Gregory P. Smitha703a212003-11-03 01:04:41 +00006380 0, /* tp_call */
6381 0, /* tp_str */
6382 0, /* tp_getattro */
6383 0, /* tp_setattro */
6384 0, /* tp_as_buffer */
6385 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6386 0, /* tp_doc */
6387 0, /* tp_traverse */
6388 0, /* tp_clear */
6389 0, /* tp_richcompare */
6390 offsetof(DBCursorObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006391};
6392
6393
6394statichere PyTypeObject DBEnv_Type = {
6395 PyObject_HEAD_INIT(NULL)
6396 0, /*ob_size*/
6397 "DBEnv", /*tp_name*/
6398 sizeof(DBEnvObject), /*tp_basicsize*/
6399 0, /*tp_itemsize*/
6400 /* methods */
6401 (destructor)DBEnv_dealloc, /*tp_dealloc*/
6402 0, /*tp_print*/
6403 (getattrfunc)DBEnv_getattr, /*tp_getattr*/
6404 0, /*tp_setattr*/
6405 0, /*tp_compare*/
6406 0, /*tp_repr*/
6407 0, /*tp_as_number*/
6408 0, /*tp_as_sequence*/
6409 0, /*tp_as_mapping*/
6410 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006411 0, /* tp_call */
6412 0, /* tp_str */
6413 0, /* tp_getattro */
6414 0, /* tp_setattro */
6415 0, /* tp_as_buffer */
6416 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6417 0, /* tp_doc */
6418 0, /* tp_traverse */
6419 0, /* tp_clear */
6420 0, /* tp_richcompare */
6421 offsetof(DBEnvObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006422};
6423
6424statichere PyTypeObject DBTxn_Type = {
6425 PyObject_HEAD_INIT(NULL)
6426 0, /*ob_size*/
6427 "DBTxn", /*tp_name*/
6428 sizeof(DBTxnObject), /*tp_basicsize*/
6429 0, /*tp_itemsize*/
6430 /* methods */
6431 (destructor)DBTxn_dealloc, /*tp_dealloc*/
6432 0, /*tp_print*/
6433 (getattrfunc)DBTxn_getattr, /*tp_getattr*/
6434 0, /*tp_setattr*/
6435 0, /*tp_compare*/
6436 0, /*tp_repr*/
6437 0, /*tp_as_number*/
6438 0, /*tp_as_sequence*/
6439 0, /*tp_as_mapping*/
6440 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006441 0, /* tp_call */
6442 0, /* tp_str */
6443 0, /* tp_getattro */
6444 0, /* tp_setattro */
6445 0, /* tp_as_buffer */
6446 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6447 0, /* tp_doc */
6448 0, /* tp_traverse */
6449 0, /* tp_clear */
6450 0, /* tp_richcompare */
6451 offsetof(DBTxnObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006452};
6453
6454
6455statichere PyTypeObject DBLock_Type = {
6456 PyObject_HEAD_INIT(NULL)
6457 0, /*ob_size*/
6458 "DBLock", /*tp_name*/
6459 sizeof(DBLockObject), /*tp_basicsize*/
6460 0, /*tp_itemsize*/
6461 /* methods */
6462 (destructor)DBLock_dealloc, /*tp_dealloc*/
6463 0, /*tp_print*/
6464 (getattrfunc)DBLock_getattr, /*tp_getattr*/
6465 0, /*tp_setattr*/
6466 0, /*tp_compare*/
6467 0, /*tp_repr*/
6468 0, /*tp_as_number*/
6469 0, /*tp_as_sequence*/
6470 0, /*tp_as_mapping*/
6471 0, /*tp_hash*/
Gregory P. Smith31c50652004-06-28 01:20:40 +00006472 0, /* tp_call */
6473 0, /* tp_str */
6474 0, /* tp_getattro */
6475 0, /* tp_setattro */
6476 0, /* tp_as_buffer */
6477 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6478 0, /* tp_doc */
6479 0, /* tp_traverse */
6480 0, /* tp_clear */
6481 0, /* tp_richcompare */
6482 offsetof(DBLockObject, in_weakreflist), /* tp_weaklistoffset */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006483};
6484
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006485#if (DBVER >= 43)
6486statichere PyTypeObject DBSequence_Type = {
6487 PyObject_HEAD_INIT(NULL)
6488 0, /*ob_size*/
6489 "DBSequence", /*tp_name*/
6490 sizeof(DBSequenceObject), /*tp_basicsize*/
6491 0, /*tp_itemsize*/
6492 /* methods */
6493 (destructor)DBSequence_dealloc, /*tp_dealloc*/
6494 0, /*tp_print*/
6495 (getattrfunc)DBSequence_getattr,/*tp_getattr*/
6496 0, /*tp_setattr*/
6497 0, /*tp_compare*/
6498 0, /*tp_repr*/
6499 0, /*tp_as_number*/
6500 0, /*tp_as_sequence*/
6501 0, /*tp_as_mapping*/
6502 0, /*tp_hash*/
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006503 0, /* tp_call */
6504 0, /* tp_str */
6505 0, /* tp_getattro */
6506 0, /* tp_setattro */
6507 0, /* tp_as_buffer */
6508 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
6509 0, /* tp_doc */
6510 0, /* tp_traverse */
6511 0, /* tp_clear */
6512 0, /* tp_richcompare */
6513 offsetof(DBSequenceObject, in_weakreflist), /* tp_weaklistoffset */
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006514};
6515#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006516
6517/* --------------------------------------------------------------------- */
6518/* Module-level functions */
6519
6520static PyObject*
6521DB_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6522{
6523 PyObject* dbenvobj = NULL;
6524 int flags = 0;
Martin v. Löwis02cbf4a2006-02-27 17:20:04 +00006525 static char* kwnames[] = { "dbEnv", "flags", NULL};
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006526
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006527 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Oi:DB", kwnames,
6528 &dbenvobj, &flags))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006529 return NULL;
6530 if (dbenvobj == Py_None)
6531 dbenvobj = NULL;
6532 else if (dbenvobj && !DBEnvObject_Check(dbenvobj)) {
6533 makeTypeError("DBEnv", dbenvobj);
6534 return NULL;
6535 }
6536
6537 return (PyObject* )newDBObject((DBEnvObject*)dbenvobj, flags);
6538}
6539
6540
6541static PyObject*
6542DBEnv_construct(PyObject* self, PyObject* args)
6543{
6544 int flags = 0;
6545 if (!PyArg_ParseTuple(args, "|i:DbEnv", &flags)) return NULL;
6546 return (PyObject* )newDBEnvObject(flags);
6547}
6548
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006549#if (DBVER >= 43)
6550static PyObject*
6551DBSequence_construct(PyObject* self, PyObject* args, PyObject* kwargs)
6552{
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006553 PyObject* dbobj;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006554 int flags = 0;
6555 static char* kwnames[] = { "db", "flags", NULL};
6556
6557 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:DBSequence", kwnames, &dbobj, &flags))
6558 return NULL;
Neal Norwitzb4fcf8d2006-06-11 05:44:18 +00006559 if (!DBObject_Check(dbobj)) {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006560 makeTypeError("DB", dbobj);
6561 return NULL;
6562 }
6563 return (PyObject* )newDBSequenceObject((DBObject*)dbobj, flags);
6564}
6565#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006566
6567static char bsddb_version_doc[] =
6568"Returns a tuple of major, minor, and patch release numbers of the\n\
6569underlying DB library.";
6570
6571static PyObject*
6572bsddb_version(PyObject* self, PyObject* args)
6573{
6574 int major, minor, patch;
6575
6576 if (!PyArg_ParseTuple(args, ":version"))
6577 return NULL;
6578 db_version(&major, &minor, &patch);
6579 return Py_BuildValue("(iii)", major, minor, patch);
6580}
6581
6582
6583/* List of functions defined in the module */
6584
6585static PyMethodDef bsddb_methods[] = {
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006586 {"DB", (PyCFunction)DB_construct, METH_VARARGS | METH_KEYWORDS },
6587 {"DBEnv", (PyCFunction)DBEnv_construct, METH_VARARGS},
6588#if (DBVER >= 43)
6589 {"DBSequence", (PyCFunction)DBSequence_construct, METH_VARARGS | METH_KEYWORDS },
6590#endif
6591 {"version", (PyCFunction)bsddb_version, METH_VARARGS, bsddb_version_doc},
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006592 {NULL, NULL} /* sentinel */
6593};
6594
Gregory P. Smith39250532007-10-09 06:02:21 +00006595/* API structure */
6596static BSDDB_api bsddb_api;
6597
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006598
6599/* --------------------------------------------------------------------- */
6600/* Module initialization */
6601
6602
6603/* Convenience routine to export an integer value.
6604 * Errors are silently ignored, for better or for worse...
6605 */
6606#define ADD_INT(dict, NAME) _addIntToDict(dict, #NAME, NAME)
6607
Gregory P. Smith41631e82003-09-21 00:08:14 +00006608#define MODULE_NAME_MAX_LEN 11
6609static char _bsddbModuleName[MODULE_NAME_MAX_LEN+1] = "_bsddb";
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006610
6611DL_EXPORT(void) init_bsddb(void)
6612{
6613 PyObject* m;
6614 PyObject* d;
6615 PyObject* pybsddb_version_s = PyString_FromString( PY_BSDDB_VERSION );
6616 PyObject* db_version_s = PyString_FromString( DB_VERSION_STRING );
6617 PyObject* cvsid_s = PyString_FromString( rcs_id );
Gregory P. Smith39250532007-10-09 06:02:21 +00006618 PyObject* py_api;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006619
6620 /* Initialize the type of the new type objects here; doing it here
6621 is required for portability to Windows without requiring C++. */
Christian Heimese93237d2007-12-19 02:37:44 +00006622 Py_TYPE(&DB_Type) = &PyType_Type;
6623 Py_TYPE(&DBCursor_Type) = &PyType_Type;
6624 Py_TYPE(&DBEnv_Type) = &PyType_Type;
6625 Py_TYPE(&DBTxn_Type) = &PyType_Type;
6626 Py_TYPE(&DBLock_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006627#if (DBVER >= 43)
Christian Heimese93237d2007-12-19 02:37:44 +00006628 Py_TYPE(&DBSequence_Type) = &PyType_Type;
Gregory P. Smithf0547d02006-06-05 17:38:04 +00006629#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006630
6631
Mark Hammonda69d4092003-04-22 23:13:27 +00006632#if defined(WITH_THREAD) && !defined(MYDB_USE_GILSTATE)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006633 /* Save the current interpreter, so callbacks can do the right thing. */
Nicholas Bastin2786d902004-03-25 02:16:23 +00006634 _db_interpreterState = PyThreadState_GET()->interp;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006635#endif
6636
6637 /* Create the module and add the functions */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006638 m = Py_InitModule(_bsddbModuleName, bsddb_methods);
Neal Norwitz1ac754f2006-01-19 06:09:39 +00006639 if (m == NULL)
6640 return;
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006641
6642 /* Add some symbolic constants to the module */
6643 d = PyModule_GetDict(m);
6644 PyDict_SetItemString(d, "__version__", pybsddb_version_s);
6645 PyDict_SetItemString(d, "cvsid", cvsid_s);
6646 PyDict_SetItemString(d, "DB_VERSION_STRING", db_version_s);
6647 Py_DECREF(pybsddb_version_s);
6648 pybsddb_version_s = NULL;
6649 Py_DECREF(cvsid_s);
6650 cvsid_s = NULL;
6651 Py_DECREF(db_version_s);
6652 db_version_s = NULL;
6653
6654 ADD_INT(d, DB_VERSION_MAJOR);
6655 ADD_INT(d, DB_VERSION_MINOR);
6656 ADD_INT(d, DB_VERSION_PATCH);
6657
6658 ADD_INT(d, DB_MAX_PAGES);
6659 ADD_INT(d, DB_MAX_RECORDS);
6660
Gregory P. Smith41631e82003-09-21 00:08:14 +00006661#if (DBVER >= 42)
6662 ADD_INT(d, DB_RPCCLIENT);
6663#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006664 ADD_INT(d, DB_CLIENT);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006665 /* allow apps to be written using DB_RPCCLIENT on older Berkeley DB */
Gregory P. Smith41631e82003-09-21 00:08:14 +00006666 _addIntToDict(d, "DB_RPCCLIENT", DB_CLIENT);
6667#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006668 ADD_INT(d, DB_XA_CREATE);
6669
6670 ADD_INT(d, DB_CREATE);
6671 ADD_INT(d, DB_NOMMAP);
6672 ADD_INT(d, DB_THREAD);
Jesus Ceaef9764f2008-05-13 18:45:46 +00006673#if (DBVER >= 45)
6674 ADD_INT(d, DB_MULTIVERSION);
6675#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006676
6677 ADD_INT(d, DB_FORCE);
6678 ADD_INT(d, DB_INIT_CDB);
6679 ADD_INT(d, DB_INIT_LOCK);
6680 ADD_INT(d, DB_INIT_LOG);
6681 ADD_INT(d, DB_INIT_MPOOL);
6682 ADD_INT(d, DB_INIT_TXN);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006683 ADD_INT(d, DB_JOINENV);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006684
Jesus Ceaef9764f2008-05-13 18:45:46 +00006685#if (DBVER >= 40)
6686 ADD_INT(d, DB_XIDDATASIZE);
6687#endif
6688
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006689 ADD_INT(d, DB_RECOVER);
6690 ADD_INT(d, DB_RECOVER_FATAL);
6691 ADD_INT(d, DB_TXN_NOSYNC);
6692 ADD_INT(d, DB_USE_ENVIRON);
6693 ADD_INT(d, DB_USE_ENVIRON_ROOT);
6694
6695 ADD_INT(d, DB_LOCKDOWN);
6696 ADD_INT(d, DB_PRIVATE);
6697 ADD_INT(d, DB_SYSTEM_MEM);
6698
6699 ADD_INT(d, DB_TXN_SYNC);
6700 ADD_INT(d, DB_TXN_NOWAIT);
6701
6702 ADD_INT(d, DB_EXCL);
6703 ADD_INT(d, DB_FCNTL_LOCKING);
6704 ADD_INT(d, DB_ODDFILESIZE);
6705 ADD_INT(d, DB_RDWRMASTER);
6706 ADD_INT(d, DB_RDONLY);
6707 ADD_INT(d, DB_TRUNCATE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006708 ADD_INT(d, DB_EXTENT);
6709 ADD_INT(d, DB_CDB_ALLDB);
6710 ADD_INT(d, DB_VERIFY);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006711 ADD_INT(d, DB_UPGRADE);
6712
6713 ADD_INT(d, DB_AGGRESSIVE);
6714 ADD_INT(d, DB_NOORDERCHK);
6715 ADD_INT(d, DB_ORDERCHKONLY);
6716 ADD_INT(d, DB_PR_PAGE);
6717#if ! (DBVER >= 33)
6718 ADD_INT(d, DB_VRFY_FLAGMASK);
6719 ADD_INT(d, DB_PR_HEADERS);
6720#endif
6721 ADD_INT(d, DB_PR_RECOVERYTEST);
6722 ADD_INT(d, DB_SALVAGE);
6723
6724 ADD_INT(d, DB_LOCK_NORUN);
6725 ADD_INT(d, DB_LOCK_DEFAULT);
6726 ADD_INT(d, DB_LOCK_OLDEST);
6727 ADD_INT(d, DB_LOCK_RANDOM);
6728 ADD_INT(d, DB_LOCK_YOUNGEST);
6729#if (DBVER >= 33)
6730 ADD_INT(d, DB_LOCK_MAXLOCKS);
6731 ADD_INT(d, DB_LOCK_MINLOCKS);
6732 ADD_INT(d, DB_LOCK_MINWRITE);
6733#endif
6734
Jesus Ceaef9764f2008-05-13 18:45:46 +00006735#if (DBVER >= 40)
6736 ADD_INT(d, DB_LOCK_EXPIRE);
6737#endif
6738#if (DBVER >= 43)
6739 ADD_INT(d, DB_LOCK_MAXWRITE);
6740#endif
6741
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006742
6743#if (DBVER >= 33)
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006744 /* docs say to use zero instead */
6745 _addIntToDict(d, "DB_LOCK_CONFLICT", 0);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006746#else
6747 ADD_INT(d, DB_LOCK_CONFLICT);
6748#endif
6749
6750 ADD_INT(d, DB_LOCK_DUMP);
6751 ADD_INT(d, DB_LOCK_GET);
6752 ADD_INT(d, DB_LOCK_INHERIT);
6753 ADD_INT(d, DB_LOCK_PUT);
6754 ADD_INT(d, DB_LOCK_PUT_ALL);
6755 ADD_INT(d, DB_LOCK_PUT_OBJ);
6756
6757 ADD_INT(d, DB_LOCK_NG);
6758 ADD_INT(d, DB_LOCK_READ);
6759 ADD_INT(d, DB_LOCK_WRITE);
6760 ADD_INT(d, DB_LOCK_NOWAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006761 ADD_INT(d, DB_LOCK_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006762 ADD_INT(d, DB_LOCK_IWRITE);
6763 ADD_INT(d, DB_LOCK_IREAD);
6764 ADD_INT(d, DB_LOCK_IWR);
6765#if (DBVER >= 33)
Gregory P. Smith29602d22006-01-24 09:46:48 +00006766#if (DBVER < 44)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006767 ADD_INT(d, DB_LOCK_DIRTY);
Gregory P. Smith29602d22006-01-24 09:46:48 +00006768#else
6769 ADD_INT(d, DB_LOCK_READ_UNCOMMITTED); /* renamed in 4.4 */
6770#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006771 ADD_INT(d, DB_LOCK_WWRITE);
6772#endif
6773
6774 ADD_INT(d, DB_LOCK_RECORD);
6775 ADD_INT(d, DB_LOCK_UPGRADE);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006776 ADD_INT(d, DB_LOCK_SWITCH);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006777#if (DBVER >= 33)
6778 ADD_INT(d, DB_LOCK_UPGRADE_WRITE);
6779#endif
6780
6781 ADD_INT(d, DB_LOCK_NOWAIT);
6782 ADD_INT(d, DB_LOCK_RECORD);
6783 ADD_INT(d, DB_LOCK_UPGRADE);
6784
6785#if (DBVER >= 33)
6786 ADD_INT(d, DB_LSTAT_ABORTED);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006787#if (DBVER < 43)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006788 ADD_INT(d, DB_LSTAT_ERR);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00006789#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006790 ADD_INT(d, DB_LSTAT_FREE);
6791 ADD_INT(d, DB_LSTAT_HELD);
6792#if (DBVER == 33)
6793 ADD_INT(d, DB_LSTAT_NOGRANT);
6794#endif
6795 ADD_INT(d, DB_LSTAT_PENDING);
6796 ADD_INT(d, DB_LSTAT_WAITING);
6797#endif
6798
6799 ADD_INT(d, DB_ARCH_ABS);
6800 ADD_INT(d, DB_ARCH_DATA);
6801 ADD_INT(d, DB_ARCH_LOG);
Gregory P. Smith3dd20022006-06-05 00:31:01 +00006802#if (DBVER >= 42)
6803 ADD_INT(d, DB_ARCH_REMOVE);
6804#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006805
6806 ADD_INT(d, DB_BTREE);
6807 ADD_INT(d, DB_HASH);
6808 ADD_INT(d, DB_RECNO);
6809 ADD_INT(d, DB_QUEUE);
6810 ADD_INT(d, DB_UNKNOWN);
6811
6812 ADD_INT(d, DB_DUP);
6813 ADD_INT(d, DB_DUPSORT);
6814 ADD_INT(d, DB_RECNUM);
6815 ADD_INT(d, DB_RENUMBER);
6816 ADD_INT(d, DB_REVSPLITOFF);
6817 ADD_INT(d, DB_SNAPSHOT);
6818
6819 ADD_INT(d, DB_JOIN_NOSORT);
6820
6821 ADD_INT(d, DB_AFTER);
6822 ADD_INT(d, DB_APPEND);
6823 ADD_INT(d, DB_BEFORE);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006824#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006825 ADD_INT(d, DB_CACHED_COUNTS);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006826#endif
Jesus Ceaca3939c2008-05-22 15:27:38 +00006827
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006828#if (DBVER >= 41)
6829 _addIntToDict(d, "DB_CHECKPOINT", 0);
6830#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006831 ADD_INT(d, DB_CHECKPOINT);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006832 ADD_INT(d, DB_CURLSN);
6833#endif
Gregory P. Smith41631e82003-09-21 00:08:14 +00006834#if ((DBVER >= 33) && (DBVER <= 41))
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006835 ADD_INT(d, DB_COMMIT);
6836#endif
6837 ADD_INT(d, DB_CONSUME);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006838 ADD_INT(d, DB_CONSUME_WAIT);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006839 ADD_INT(d, DB_CURRENT);
6840#if (DBVER >= 33)
6841 ADD_INT(d, DB_FAST_STAT);
6842#endif
6843 ADD_INT(d, DB_FIRST);
6844 ADD_INT(d, DB_FLUSH);
6845 ADD_INT(d, DB_GET_BOTH);
6846 ADD_INT(d, DB_GET_RECNO);
6847 ADD_INT(d, DB_JOIN_ITEM);
6848 ADD_INT(d, DB_KEYFIRST);
6849 ADD_INT(d, DB_KEYLAST);
6850 ADD_INT(d, DB_LAST);
6851 ADD_INT(d, DB_NEXT);
6852 ADD_INT(d, DB_NEXT_DUP);
6853 ADD_INT(d, DB_NEXT_NODUP);
6854 ADD_INT(d, DB_NODUPDATA);
6855 ADD_INT(d, DB_NOOVERWRITE);
6856 ADD_INT(d, DB_NOSYNC);
6857 ADD_INT(d, DB_POSITION);
6858 ADD_INT(d, DB_PREV);
6859 ADD_INT(d, DB_PREV_NODUP);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006860#if (DBVER < 45)
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006861 ADD_INT(d, DB_RECORDCOUNT);
Gregory P. Smith8b96a352007-01-05 01:59:42 +00006862#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006863 ADD_INT(d, DB_SET);
6864 ADD_INT(d, DB_SET_RANGE);
6865 ADD_INT(d, DB_SET_RECNO);
6866 ADD_INT(d, DB_WRITECURSOR);
6867
6868 ADD_INT(d, DB_OPFLAGS_MASK);
6869 ADD_INT(d, DB_RMW);
6870#if (DBVER >= 33)
6871 ADD_INT(d, DB_DIRTY_READ);
6872 ADD_INT(d, DB_MULTIPLE);
6873 ADD_INT(d, DB_MULTIPLE_KEY);
6874#endif
6875
Gregory P. Smith29602d22006-01-24 09:46:48 +00006876#if (DBVER >= 44)
6877 ADD_INT(d, DB_READ_UNCOMMITTED); /* replaces DB_DIRTY_READ in 4.4 */
6878 ADD_INT(d, DB_READ_COMMITTED);
6879#endif
6880
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006881#if (DBVER >= 33)
6882 ADD_INT(d, DB_DONOTINDEX);
6883#endif
6884
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006885#if (DBVER >= 41)
6886 _addIntToDict(d, "DB_INCOMPLETE", 0);
6887#else
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006888 ADD_INT(d, DB_INCOMPLETE);
Barry Warsaw9a0d7792002-12-30 20:53:52 +00006889#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00006890 ADD_INT(d, DB_KEYEMPTY);
6891 ADD_INT(d, DB_KEYEXIST);
6892 ADD_INT(d, DB_LOCK_DEADLOCK);
6893 ADD_INT(d, DB_LOCK_NOTGRANTED);
6894 ADD_INT(d, DB_NOSERVER);
6895 ADD_INT(d, DB_NOSERVER_HOME);
6896 ADD_INT(d, DB_NOSERVER_ID);
6897 ADD_INT(d, DB_NOTFOUND);
6898 ADD_INT(d, DB_OLD_VERSION);
6899 ADD_INT(d, DB_RUNRECOVERY);
6900 ADD_INT(d, DB_VERIFY_BAD);
6901#if (DBVER >= 33)
6902 ADD_INT(d, DB_PAGE_NOTFOUND);
6903 ADD_INT(d, DB_SECONDARY_BAD);
6904#endif
6905#if (DBVER >= 40)
6906 ADD_INT(d, DB_STAT_CLEAR);
6907 ADD_INT(d, DB_REGION_INIT);
6908 ADD_INT(d, DB_NOLOCKING);
6909 ADD_INT(d, DB_YIELDCPU);
6910 ADD_INT(d, DB_PANIC_ENVIRONMENT);
6911 ADD_INT(d, DB_NOPANIC);
6912#endif
6913
Jesus Ceaef9764f2008-05-13 18:45:46 +00006914#if (DBVER >= 41)
6915 ADD_INT(d, DB_OVERWRITE);
6916#endif
6917
Gregory P. Smithaae141a2007-11-01 21:08:14 +00006918#ifdef DB_REGISTER
6919 ADD_INT(d, DB_REGISTER);
6920#endif
6921
Gregory P. Smith41631e82003-09-21 00:08:14 +00006922#if (DBVER >= 42)
6923 ADD_INT(d, DB_TIME_NOTGRANTED);
6924 ADD_INT(d, DB_TXN_NOT_DURABLE);
6925 ADD_INT(d, DB_TXN_WRITE_NOSYNC);
Gregory P. Smith41631e82003-09-21 00:08:14 +00006926 ADD_INT(d, DB_DIRECT_DB);
6927 ADD_INT(d, DB_INIT_REP);
6928 ADD_INT(d, DB_ENCRYPT);
6929 ADD_INT(d, DB_CHKSUM);
6930#endif
6931
Jesus Ceaca3939c2008-05-22 15:27:38 +00006932#if (DBVER >= 42) && (DBVER < 47)
6933 ADD_INT(d, DB_LOG_AUTOREMOVE);
6934 ADD_INT(d, DB_DIRECT_LOG);
6935#endif
6936
6937#if (DBVER >= 47)
6938 ADD_INT(d, DB_LOG_DIRECT);
6939 ADD_INT(d, DB_LOG_DSYNC);
6940 ADD_INT(d, DB_LOG_IN_MEMORY);
6941 ADD_INT(d, DB_LOG_AUTO_REMOVE);
6942 ADD_INT(d, DB_LOG_ZERO);
6943#endif
6944
Jesus Ceaef9764f2008-05-13 18:45:46 +00006945#if (DBVER >= 44)
6946 ADD_INT(d, DB_DSYNC_DB);
6947#endif
6948
6949#if (DBVER >= 45)
6950 ADD_INT(d, DB_TXN_SNAPSHOT);
6951#endif
6952
6953#if (DBVER >= 40)
6954 ADD_INT(d, DB_VERB_DEADLOCK);
6955#if (DBVER >= 46)
6956 ADD_INT(d, DB_VERB_FILEOPS);
6957 ADD_INT(d, DB_VERB_FILEOPS_ALL);
6958#endif
6959 ADD_INT(d, DB_VERB_RECOVERY);
6960#if (DBVER >= 44)
6961 ADD_INT(d, DB_VERB_REGISTER);
6962#endif
6963 ADD_INT(d, DB_VERB_REPLICATION);
6964 ADD_INT(d, DB_VERB_WAITSFOR);
6965#endif
6966
6967#if (DBVER >= 45)
6968 ADD_INT(d, DB_EVENT_PANIC);
6969 ADD_INT(d, DB_EVENT_REP_CLIENT);
6970#if (DBVER >= 46)
6971 ADD_INT(d, DB_EVENT_REP_ELECTED);
6972#endif
6973 ADD_INT(d, DB_EVENT_REP_MASTER);
6974 ADD_INT(d, DB_EVENT_REP_NEWMASTER);
6975#if (DBVER >= 46)
6976 ADD_INT(d, DB_EVENT_REP_PERM_FAILED);
6977#endif
6978 ADD_INT(d, DB_EVENT_REP_STARTUPDONE);
6979 ADD_INT(d, DB_EVENT_WRITE_FAILED);
6980#endif
6981
6982#if (DBVER >= 40)
6983 ADD_INT(d, DB_REP_MASTER);
6984 ADD_INT(d, DB_REP_CLIENT);
6985#if (DBVER >= 45)
6986 ADD_INT(d, DB_REP_ELECTION);
6987
6988 ADD_INT(d, DB_REP_ACK_TIMEOUT);
6989 ADD_INT(d, DB_REP_CONNECTION_RETRY);
6990 ADD_INT(d, DB_REP_ELECTION_TIMEOUT);
6991 ADD_INT(d, DB_REP_ELECTION_RETRY);
6992#endif
6993#if (DBVER >= 46)
6994 ADD_INT(d, DB_REP_CHECKPOINT_DELAY);
6995 ADD_INT(d, DB_REP_FULL_ELECTION_TIMEOUT);
6996#endif
6997#endif
6998
6999#if (DBVER >= 45)
7000 ADD_INT(d, DB_REPMGR_PEER);
7001 ADD_INT(d, DB_REPMGR_ACKS_ALL);
7002 ADD_INT(d, DB_REPMGR_ACKS_ALL_PEERS);
7003 ADD_INT(d, DB_REPMGR_ACKS_NONE);
7004 ADD_INT(d, DB_REPMGR_ACKS_ONE);
7005 ADD_INT(d, DB_REPMGR_ACKS_ONE_PEER);
7006 ADD_INT(d, DB_REPMGR_ACKS_QUORUM);
7007 ADD_INT(d, DB_REPMGR_CONNECTED);
7008 ADD_INT(d, DB_REPMGR_DISCONNECTED);
7009 ADD_INT(d, DB_STAT_CLEAR);
7010 ADD_INT(d, DB_STAT_ALL);
7011#endif
7012
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007013#if (DBVER >= 43)
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007014 ADD_INT(d, DB_BUFFER_SMALL);
Gregory P. Smithf0547d02006-06-05 17:38:04 +00007015 ADD_INT(d, DB_SEQ_DEC);
7016 ADD_INT(d, DB_SEQ_INC);
7017 ADD_INT(d, DB_SEQ_WRAP);
Gregory P. Smith8b7e9172004-12-13 09:51:23 +00007018#endif
7019
Jesus Ceaca3939c2008-05-22 15:27:38 +00007020#if (DBVER >= 43) && (DBVER < 47)
7021 ADD_INT(d, DB_LOG_INMEMORY);
7022 ADD_INT(d, DB_DSYNC_LOG);
7023#endif
7024
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007025#if (DBVER >= 41)
7026 ADD_INT(d, DB_ENCRYPT_AES);
7027 ADD_INT(d, DB_AUTO_COMMIT);
7028#else
Jesus Ceaef9764f2008-05-13 18:45:46 +00007029 /* allow Berkeley DB 4.1 aware apps to run on older versions */
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007030 _addIntToDict(d, "DB_AUTO_COMMIT", 0);
7031#endif
7032
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007033 ADD_INT(d, EINVAL);
7034 ADD_INT(d, EACCES);
7035 ADD_INT(d, ENOSPC);
7036 ADD_INT(d, ENOMEM);
7037 ADD_INT(d, EAGAIN);
7038 ADD_INT(d, EBUSY);
7039 ADD_INT(d, EEXIST);
7040 ADD_INT(d, ENOENT);
7041 ADD_INT(d, EPERM);
7042
Barry Warsaw1baa9822003-03-31 19:51:29 +00007043#if (DBVER >= 40)
7044 ADD_INT(d, DB_SET_LOCK_TIMEOUT);
7045 ADD_INT(d, DB_SET_TXN_TIMEOUT);
7046#endif
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007047
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007048 /* The exception name must be correct for pickled exception *
7049 * objects to unpickle properly. */
7050#ifdef PYBSDDB_STANDALONE /* different value needed for standalone pybsddb */
7051#define PYBSDDB_EXCEPTION_BASE "bsddb3.db."
7052#else
7053#define PYBSDDB_EXCEPTION_BASE "bsddb.db."
7054#endif
7055
7056 /* All the rest of the exceptions derive only from DBError */
7057#define MAKE_EX(name) name = PyErr_NewException(PYBSDDB_EXCEPTION_BASE #name, DBError, NULL); \
7058 PyDict_SetItemString(d, #name, name)
7059
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007060 /* The base exception class is DBError */
Gregory P. Smith7f5b6f42006-04-08 07:10:51 +00007061 DBError = NULL; /* used in MAKE_EX so that it derives from nothing */
7062 MAKE_EX(DBError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007063
Gregory P. Smithe9477062005-06-04 06:46:59 +00007064 /* Some magic to make DBNotFoundError and DBKeyEmptyError derive
7065 * from both DBError and KeyError, since the API only supports
7066 * using one base class. */
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007067 PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
Gregory P. Smithe9477062005-06-04 06:46:59 +00007068 PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
7069 "class DBKeyEmptyError(DBError, KeyError): pass",
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007070 Py_file_input, d, d);
7071 DBNotFoundError = PyDict_GetItemString(d, "DBNotFoundError");
Gregory P. Smithe9477062005-06-04 06:46:59 +00007072 DBKeyEmptyError = PyDict_GetItemString(d, "DBKeyEmptyError");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007073 PyDict_DelItemString(d, "KeyError");
7074
7075
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007076#if !INCOMPLETE_IS_WARNING
7077 MAKE_EX(DBIncompleteError);
7078#endif
Gregory P. Smithe2767172003-11-02 08:06:29 +00007079 MAKE_EX(DBCursorClosedError);
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007080 MAKE_EX(DBKeyEmptyError);
7081 MAKE_EX(DBKeyExistError);
7082 MAKE_EX(DBLockDeadlockError);
7083 MAKE_EX(DBLockNotGrantedError);
7084 MAKE_EX(DBOldVersionError);
7085 MAKE_EX(DBRunRecoveryError);
7086 MAKE_EX(DBVerifyBadError);
7087 MAKE_EX(DBNoServerError);
7088 MAKE_EX(DBNoServerHomeError);
7089 MAKE_EX(DBNoServerIDError);
7090#if (DBVER >= 33)
7091 MAKE_EX(DBPageNotFoundError);
7092 MAKE_EX(DBSecondaryBadError);
7093#endif
7094
7095 MAKE_EX(DBInvalidArgError);
7096 MAKE_EX(DBAccessError);
7097 MAKE_EX(DBNoSpaceError);
7098 MAKE_EX(DBNoMemoryError);
7099 MAKE_EX(DBAgainError);
7100 MAKE_EX(DBBusyError);
7101 MAKE_EX(DBFileExistsError);
7102 MAKE_EX(DBNoSuchFileError);
7103 MAKE_EX(DBPermissionsError);
7104
Jesus Ceaef9764f2008-05-13 18:45:46 +00007105#if (DBVER >= 42)
7106 MAKE_EX(DBRepHandleDeadError);
7107#endif
7108
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007109#undef MAKE_EX
7110
Gregory P. Smith39250532007-10-09 06:02:21 +00007111 /* Initiliase the C API structure and add it to the module */
7112 bsddb_api.db_type = &DB_Type;
7113 bsddb_api.dbcursor_type = &DBCursor_Type;
7114 bsddb_api.dbenv_type = &DBEnv_Type;
7115 bsddb_api.dbtxn_type = &DBTxn_Type;
7116 bsddb_api.dblock_type = &DBLock_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007117#if (DBVER >= 43)
Gregory P. Smith39250532007-10-09 06:02:21 +00007118 bsddb_api.dbsequence_type = &DBSequence_Type;
Neal Norwitzf3ca1692007-10-12 03:52:34 +00007119#endif
Gregory P. Smith39250532007-10-09 06:02:21 +00007120 bsddb_api.makeDBError = makeDBError;
7121
7122 py_api = PyCObject_FromVoidPtr((void*)&bsddb_api, NULL);
7123 PyDict_SetItemString(d, "api", py_api);
7124 Py_DECREF(py_api);
7125
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007126 /* Check for errors */
7127 if (PyErr_Occurred()) {
7128 PyErr_Print();
Barry Warsaw9a0d7792002-12-30 20:53:52 +00007129 Py_FatalError("can't initialize module _bsddb");
Martin v. Löwis6aa4a1f2002-11-19 08:09:52 +00007130 }
7131}
Gregory P. Smith41631e82003-09-21 00:08:14 +00007132
7133/* allow this module to be named _pybsddb so that it can be installed
7134 * and imported on top of python >= 2.3 that includes its own older
7135 * copy of the library named _bsddb without importing the old version. */
7136DL_EXPORT(void) init_pybsddb(void)
7137{
7138 strncpy(_bsddbModuleName, "_pybsddb", MODULE_NAME_MAX_LEN);
7139 init_bsddb();
7140}